diff options
| -rw-r--r-- | source/slang/slang-ast-support-types.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 11 | ||||
| -rw-r--r-- | source/slang/slang-check-expr.cpp | 3 | ||||
| -rw-r--r-- | source/slang/slang-check-impl.h | 11 | ||||
| -rw-r--r-- | source/slang/slang-lookup.cpp | 17 | ||||
| -rw-r--r-- | source/slang/slang-lookup.h | 3 | ||||
| -rw-r--r-- | tests/language-feature/enums/unscoped-enum-explicit-type-2.slang | 33 |
7 files changed, 68 insertions, 11 deletions
diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h index 21ca27a90..1d3de9c54 100644 --- a/source/slang/slang-ast-support-types.h +++ b/source/slang/slang-ast-support-types.h @@ -1225,6 +1225,7 @@ enum class LookupOptions : uint8_t /// checking to see if a keyword is shadowed. IgnoreInheritance = 1 << 4, ///< Lookup only non inheritance children of a struct (including `extension`) + IgnoreTransparentMembers = 1 << 5, }; inline LookupOptions operator&(LookupOptions a, LookupOptions b) { diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 2a5b5a4e3..0319eb260 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -2897,14 +2897,13 @@ void SemanticsDeclBasesVisitor::visitInheritanceDecl(InheritanceDecl* inheritanc { // check the type being inherited from auto base = inheritanceDecl->base; - Decl* toExclude = nullptr; Decl* parent = getParentDecl(inheritanceDecl); - // We exclude in the case that a circular reference is possible. This is when a parent is a - // transparent decl. If we just blanket "block" all ensure's of a parent a generic may fail when - // trying to fetch a parent + // We exclude transparent members in the case that a circular reference is + // possible. This is when a parent is also a transparent decl. + SemanticsContext context(*this); if (parent->findModifier<TransparentModifier>()) - toExclude = parent; - SemanticsDeclVisitorBase baseVistor(this->withDeclToExcludeFromLookup(toExclude)); + context = context.excludeTransparentMembersFromLookup(); + SemanticsDeclVisitorBase baseVistor(context); baseVistor.CheckConstraintSubType(base); base = baseVistor.TranslateTypeNode(base); inheritanceDecl->base = base; diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index ce6206973..135632ba8 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -3092,7 +3092,8 @@ Expr* SemanticsExprVisitor::visitVarExpr(VarExpr* expr) expr->scope, LookupMask::Default, false, - getDeclToExcludeFromLookup()); + getDeclToExcludeFromLookup(), + getExcludeTransparentMembersFromLookup()); bool diagnosed = false; lookupResult = filterLookupResultByVisibilityAndDiagnose(lookupResult, expr->loc, diagnosed); diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h index 3ef1e8f3b..638706814 100644 --- a/source/slang/slang-check-impl.h +++ b/source/slang/slang-check-impl.h @@ -1068,6 +1068,15 @@ public: Decl* getDeclToExcludeFromLookup() { return m_declToExcludeFromLookup; } + SemanticsContext excludeTransparentMembersFromLookup() + { + SemanticsContext result(*this); + result.m_excludeTransparentMembersFromLookup = true; + return result; + } + + bool getExcludeTransparentMembersFromLookup() { return m_excludeTransparentMembersFromLookup; } + OrderedHashSet<Type*>* getCapturedTypePacks() { return m_capturedTypePacks; } GLSLBindingOffsetTracker* getGLSLBindingOffsetTracker() @@ -1084,6 +1093,8 @@ private: Decl* m_declToExcludeFromLookup = nullptr; + bool m_excludeTransparentMembersFromLookup = false; + protected: // TODO: consider making more of this state `private`... diff --git a/source/slang/slang-lookup.cpp b/source/slang/slang-lookup.cpp index e4f2b188d..3667e2cd2 100644 --- a/source/slang/slang-lookup.cpp +++ b/source/slang/slang-lookup.cpp @@ -237,6 +237,12 @@ static void _lookUpDirectAndTransparentMembers( if ((int)request.mask & (int)LookupMask::Attribute) return; + // Also skip transparent members if they're explicitly excluded by the + // request. This prevents cyclic lookups e.g. when looking up UnscopedEnum's + // underlying types. + if (((int)request.options & (int)LookupOptions::IgnoreTransparentMembers) != 0) + return; + for (auto transparentInfo : containerDecl->getTransparentMembers()) { // The reference to the transparent member should use the same @@ -1059,11 +1065,16 @@ LookupResult lookUp( Scope* scope, LookupMask mask, bool considerAllLocalNamesInScope, - Decl* declToExclude) + Decl* declToExclude, + bool ignoreTransparentMembers) { LookupResult result; - const auto options = considerAllLocalNamesInScope ? LookupOptions::ConsiderAllLocalNamesInScope - : LookupOptions::None; + const auto options = + (LookupOptions)((int)(considerAllLocalNamesInScope + ? LookupOptions::ConsiderAllLocalNamesInScope + : LookupOptions::None) | + (int)(ignoreTransparentMembers ? LookupOptions::IgnoreTransparentMembers + : LookupOptions::None)); LookupRequest request = initLookupRequest(semantics, name, mask, options, scope, declToExclude); _lookUpInScopes(astBuilder, name, request, result); return result; diff --git a/source/slang/slang-lookup.h b/source/slang/slang-lookup.h index ad8b64e7e..21c7b9b98 100644 --- a/source/slang/slang-lookup.h +++ b/source/slang/slang-lookup.h @@ -21,7 +21,8 @@ LookupResult lookUp( Scope* scope, LookupMask mask = LookupMask::Default, bool considerAllLocalNamesInScope = false, - Decl* declToExclude = nullptr); + Decl* declToExclude = nullptr, + bool ignoreTransparentMembers = false); // Perform member lookup in the context of a type LookupResult lookUpMember( diff --git a/tests/language-feature/enums/unscoped-enum-explicit-type-2.slang b/tests/language-feature/enums/unscoped-enum-explicit-type-2.slang new file mode 100644 index 000000000..1c74dd7b7 --- /dev/null +++ b/tests/language-feature/enums/unscoped-enum-explicit-type-2.slang @@ -0,0 +1,33 @@ +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK): -shaderobj +//TEST(compute, vulkan):COMPARE_COMPUTE(filecheck-buffer=CHECK):-vk -shaderobj + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name=outputBuffer +RWStructuredBuffer<uint32_t> outputBuffer; + +[UnscopedEnum] +enum unscopedEnum1 : uint32_t +{ + ENUM1_A = 1, + ENUM1_B = 2 +}; + +[UnscopedEnum] +enum unscopedEnum2 : uint32_t +{ + ENUM2_A = 3, + ENUM2_B = 4 +}; + +[numthreads(1,1,1)] +void computeMain() +{ + // CHECK: 1 + // CHECK: 2 + // CHECK: 3 + // CHECK: 4 + outputBuffer[0] = ENUM1_A; + outputBuffer[1] = ENUM1_B; + outputBuffer[2] = ENUM2_A; + outputBuffer[3] = ENUM2_B; +} + |
