summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
authorJulius Ikkala <julius.ikkala@gmail.com>2025-01-17 03:06:00 +0200
committerGitHub <noreply@github.com>2025-01-17 01:06:00 +0000
commitd3ad6bb4997d3b7ba2dc9653a2d5f7dc965b150f (patch)
tree4726f721cec95ec5ea2ec8408a081ca93338e923 /source/slang
parente771f1945ed692168a2634d66a0907acc9c68858 (diff)
Fix cyclic lookups with UnscopedEnums (#6110)
* Fix cyclic lookups with UnscopedEnums * Add test with multiple unscoped enums with explicit types --------- Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/slang-ast-support-types.h1
-rw-r--r--source/slang/slang-check-decl.cpp11
-rw-r--r--source/slang/slang-check-expr.cpp3
-rw-r--r--source/slang/slang-check-impl.h11
-rw-r--r--source/slang/slang-lookup.cpp17
-rw-r--r--source/slang/slang-lookup.h3
6 files changed, 35 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(