summaryrefslogtreecommitdiff
path: root/source/slang/slang-check-decl.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-12-06 12:05:07 -0800
committerGitHub <noreply@github.com>2023-12-06 12:05:07 -0800
commit11111e5733b189127dc2c4934d67693b9bc6e764 (patch)
tree0ba84df3e856eb104abec2ecac47242bc70a7b7d /source/slang/slang-check-decl.cpp
parentfa6d8717d02912697c09f2d7de802723ac6d6e47 (diff)
Support visibility control and default to `internal`. (#3380)
* Support visibility control and default to `internal`. * Fix wip. * Fixes. * Fix. * Fix test. * Add legacy language detection and compatibility for existing code. * Add doc. --------- Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source/slang/slang-check-decl.cpp')
-rw-r--r--source/slang/slang-check-decl.cpp100
1 files changed, 89 insertions, 11 deletions
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index b4cc6c00a..671bb26dd 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -298,7 +298,9 @@ namespace Slang
{
// Things at the global scope are always "members" of their module.
//
- if(as<ModuleDecl>(parentDecl))
+ if(as<NamespaceDeclBase>(parentDecl))
+ return false;
+ if (as<FileDecl>(parentDecl))
return false;
// Anything explicitly marked `static` and not at module scope
@@ -373,7 +375,7 @@ namespace Slang
auto parentDecl = decl->parentDecl;
if (auto genericDecl = as<GenericDecl>(parentDecl))
parentDecl = genericDecl->parentDecl;
- return as<NamespaceDeclBase>(parentDecl) != nullptr;
+ return as<NamespaceDeclBase>(parentDecl) != nullptr || as<FileDecl>(parentDecl) != nullptr;
}
/// Is `decl` a global shader parameter declaration?
@@ -385,7 +387,7 @@ namespace Slang
// A global shader parameter must be declared at global or namespace
// scope, so that it has a single definition across the module.
//
- if(!as<NamespaceDeclBase>(decl->parentDecl)) return false;
+ if(!isGlobalDecl(decl)) return false;
// A global variable marked `static` indicates a traditional
// global variable (albeit one that is implicitly local to
@@ -733,6 +735,7 @@ namespace Slang
// The coding of this loop is somewhat defensive to deal
// with special cases that will be described along the way.
//
+ auto outerScope = getScope(decl);
for(;;)
{
// The first thing is to check what state the decl is
@@ -757,6 +760,8 @@ namespace Slang
// cannot affect the state in which the declaration is *checked*.
//
SemanticsContext subContext = baseContext ? SemanticsContext(*baseContext) : SemanticsContext(getShared());
+ if (outerScope)
+ subContext = subContext.withOuterScope(outerScope);
_dispatchDeclCheckingVisitor(decl, nextState, subContext);
// In the common case, the visitor will have done the necessary
@@ -1245,6 +1250,8 @@ namespace Slang
}
}
}
+
+ checkVisibility(varDecl);
}
void SemanticsDeclHeaderVisitor::visitStructDecl(StructDecl* structDecl)
@@ -1261,11 +1268,12 @@ namespace Slang
{
addModifier(structDecl, m_astBuilder->create<NVAPIMagicModifier>());
}
+ checkVisibility(structDecl);
}
void SemanticsDeclHeaderVisitor::visitClassDecl(ClassDecl* classDecl)
{
- SLANG_UNUSED(classDecl);
+ checkVisibility(classDecl);
}
void SemanticsDeclBodyVisitor::checkVarDeclCommon(VarDeclBase* varDecl)
@@ -1313,6 +1321,7 @@ namespace Slang
OverloadResolveContext overloadContext;
overloadContext.loc = varDecl->nameAndLoc.loc;
overloadContext.mode = OverloadResolveContext::Mode::JustTrying;
+ overloadContext.sourceScope = m_outerScope;
AddTypeOverloadCandidates(type, overloadContext);
if(overloadContext.bestCandidates.getCount() != 0)
@@ -1368,6 +1377,24 @@ namespace Slang
}
}
+ void addVisibilityModifier(ASTBuilder* builder, Decl* decl, DeclVisibility vis)
+ {
+ switch (vis)
+ {
+ case DeclVisibility::Public:
+ addModifier(decl, builder->create<PublicModifier>());
+ break;
+ case DeclVisibility::Internal:
+ addModifier(decl, builder->create<InternalModifier>());
+ break;
+ case DeclVisibility::Private:
+ addModifier(decl, builder->create<PrivateModifier>());
+ break;
+ default:
+ break;
+ }
+ }
+
bool SemanticsVisitor::trySynthesizeDifferentialAssociatedTypeRequirementWitness(
ConformanceCheckingContext* context,
DeclRef<AssocTypeDecl> requirementDeclRef,
@@ -1434,6 +1461,10 @@ namespace Slang
diffField->checkState = DeclCheckState::SignatureChecked;
diffField->parentDecl = aggTypeDecl;
aggTypeDecl->members.add(diffField);
+
+ auto visibility = getDeclVisibility(member);
+ addVisibilityModifier(m_astBuilder, diffField, visibility);
+
aggTypeDecl->invalidateMemberDictionary();
// Inject a `DerivativeMember` modifier on the differential field to point to itself.
@@ -1539,6 +1570,15 @@ namespace Slang
addModifier(aggTypeDecl, m_astBuilder->create<SynthesizedModifier>());
+ // The visibility of synthesized decl should be the min of the parent decl and the requirement.
+ if (auto visModifier = requirementDeclRef.getDecl()->findModifier<VisibilityModifier>())
+ {
+ auto requirementVisibility = getDeclVisibility(requirementDeclRef.getDecl());
+ auto thisVisibility = getDeclVisibility(context->parentDecl);
+ auto visibility = Math::Min(thisVisibility, requirementVisibility);
+ addVisibilityModifier(m_astBuilder, aggTypeDecl, visibility);
+ }
+
// Synthesize the rest of IDifferential method conformances by recursively checking
// conformance on the synthesized decl.
checkAggTypeConformance(aggTypeDecl);
@@ -1890,6 +1930,7 @@ namespace Slang
DeclCheckState::ModifiersChecked,
DeclCheckState::ReadyForReference,
DeclCheckState::ReadyForLookup,
+ DeclCheckState::ReadyForConformances,
DeclCheckState::Checked
};
for(auto s : states)
@@ -2810,6 +2851,7 @@ namespace Slang
{
synFuncDecl->nameAndLoc.name = getSession()->getNameObj("$__syn_" + synFuncDecl->nameAndLoc.name->text);
}
+
// The result type of our synthesized method will be the expected
// result type from the interface requirement.
//
@@ -2933,6 +2975,14 @@ namespace Slang
auto attr = m_astBuilder->create<BackwardDifferentiableAttribute>();
addModifier(synFuncDecl, attr);
}
+ // The visibility of synthesized decl should be the min of the parent decl and the requirement.
+ if (auto visModifier = requiredMemberDeclRef.getDecl()->findModifier<VisibilityModifier>())
+ {
+ auto requirementVisibility = getDeclVisibility(requiredMemberDeclRef.getDecl());
+ auto thisVisibility = getDeclVisibility(context->parentDecl);
+ auto visibility = Math::Min(thisVisibility, requirementVisibility);
+ addVisibilityModifier(m_astBuilder, synFuncDecl, visibility);
+ }
}
return synFuncDecl;
@@ -3471,6 +3521,15 @@ namespace Slang
synPropertyDecl->parentDecl = context->parentDecl;
+ // The visibility of synthesized decl should be the min of the parent decl and the requirement.
+ if (auto visModifier = requiredMemberDeclRef.getDecl()->findModifier<VisibilityModifier>())
+ {
+ auto requirementVisibility = getDeclVisibility(requiredMemberDeclRef.getDecl());
+ auto thisVisibility = getDeclVisibility(context->parentDecl);
+ auto visibility = Math::Min(thisVisibility, requirementVisibility);
+ addVisibilityModifier(m_astBuilder, synPropertyDecl, visibility);
+ }
+
// Once our synthesized declaration is complete, we need
// to install it as the witness that satifies the given
// requirement.
@@ -3969,7 +4028,7 @@ namespace Slang
// requests will be handled further down. For now we include
// lookup results that might be usable, but not as-is.
//
- auto lookupResult = lookUpMember(m_astBuilder, this, name, subType, LookupMask::Default, LookupOptions::IgnoreBaseInterfaces);
+ auto lookupResult = lookUpMember(m_astBuilder, this, name, subType, nullptr, LookupMask::Default, LookupOptions::IgnoreBaseInterfaces);
if(!lookupResult.isValid())
{
@@ -4502,6 +4561,8 @@ namespace Slang
void SemanticsDeclBasesVisitor::visitInterfaceDecl(InterfaceDecl* decl)
{
+ SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(this, decl);
+ checkVisibility(decl);
for( auto inheritanceDecl : decl->getMembersOfType<InheritanceDecl>() )
{
ensureDecl(inheritanceDecl, DeclCheckState::CanUseBaseOfInheritanceDecl);
@@ -4567,6 +4628,8 @@ namespace Slang
// Furthermore, only the first inheritance clause (in source
// order) is allowed to declare a base `struct` type.
//
+ SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(this, decl);
+
Index inheritanceClauseCounter = 0;
for( auto inheritanceDecl : decl->getMembersOfType<InheritanceDecl>() )
{
@@ -4636,6 +4699,7 @@ namespace Slang
// Furthermore, only the first inheritance clause (in source
// order) is allowed to declare a base `class` type.
//
+ SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(this, decl);
Index inheritanceClauseCounter = 0;
for (auto inheritanceDecl : decl->getMembersOfType<InheritanceDecl>())
{
@@ -4768,6 +4832,9 @@ namespace Slang
void SemanticsDeclBasesVisitor::visitEnumDecl(EnumDecl* decl)
{
+ SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(this, decl);
+ checkVisibility(decl);
+
// An `enum` type can inherit from interfaces, and also
// from a single "tag" type that must:
//
@@ -4775,7 +4842,6 @@ namespace Slang
// * come first in the list of base types
//
Index inheritanceClauseCounter = 0;
-
Type* tagType = nullptr;
InheritanceDecl* tagTypeInheritanceDecl = nullptr;
for(auto inheritanceDecl : decl->getMembersOfType<InheritanceDecl>())
@@ -4938,6 +5004,8 @@ namespace Slang
void SemanticsDeclBodyVisitor::visitEnumDecl(EnumDecl* decl)
{
+ SLANG_OUTER_SCOPE_CONTEXT_DECL_RAII(this, decl);
+
auto enumType = DeclRefType::create(m_astBuilder, makeDeclRef(decl));
auto tagType = decl->tagType;
@@ -5063,6 +5131,7 @@ namespace Slang
void SemanticsDeclHeaderVisitor::visitTypeDefDecl(TypeDefDecl* decl)
{
decl->type = CheckProperType(decl->type);
+ checkVisibility(decl);
}
void SemanticsDeclHeaderVisitor::visitGlobalGenericParamDecl(GlobalGenericParamDecl* decl)
@@ -5079,6 +5148,7 @@ namespace Slang
auto interfaceDecl = as<InterfaceDecl>(decl->parentDecl);
if (!interfaceDecl)
getSink()->diagnose(decl, Slang::Diagnostics::assocTypeInInterfaceOnly);
+ checkVisibility(decl);
}
void SemanticsDeclBodyVisitor::visitFunctionDeclBase(FunctionDeclBase* decl)
@@ -6154,6 +6224,7 @@ namespace Slang
}
}
}
+ checkVisibility(decl);
}
void SemanticsDeclHeaderVisitor::visitFuncDecl(FuncDecl* funcDecl)
@@ -6464,6 +6535,7 @@ namespace Slang
{
decl->type = CheckUsableType(decl->type);
visitAbstractStorageDeclCommon(decl);
+ checkVisibility(decl);
}
Type* SemanticsDeclHeaderVisitor::_getAccessorStorageType(AccessorDecl* decl)
@@ -6768,13 +6840,19 @@ namespace Slang
importedModulesList.add(moduleDecl);
importedModulesSet.add(moduleDecl);
- // Create a new sub-scope to wire the module
+ // Create a new sub-scope to wire the module's scope and its nested FileDecl's scopes
// into our lookup chain.
- auto subScope = getASTBuilder()->create<Scope>();
- subScope->containerDecl = moduleDecl;
+ for (auto moduleScope = moduleDecl->ownedScope; moduleScope; moduleScope = moduleScope->nextSibling)
+ {
+ if (moduleScope->containerDecl != moduleDecl && moduleScope->containerDecl->parentDecl != moduleDecl)
+ continue;
- subScope->nextSibling = scope->nextSibling;
- scope->nextSibling = subScope;
+ auto subScope = getASTBuilder()->create<Scope>();
+ subScope->containerDecl = moduleScope->containerDecl;
+
+ subScope->nextSibling = scope->nextSibling;
+ scope->nextSibling = subScope;
+ }
// Also import any modules from nested `import` declarations
// with the `__exported` modifier