diff options
| author | Yong He <yonghe@outlook.com> | 2023-12-06 12:05:07 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-12-06 12:05:07 -0800 |
| commit | 11111e5733b189127dc2c4934d67693b9bc6e764 (patch) | |
| tree | 0ba84df3e856eb104abec2ecac47242bc70a7b7d /source/slang/slang-check-decl.cpp | |
| parent | fa6d8717d02912697c09f2d7de802723ac6d6e47 (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.cpp | 100 |
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 |
