diff options
| author | Yong He <yonghe@outlook.com> | 2024-03-27 12:21:07 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-27 12:21:07 -0700 |
| commit | 8395acfa0ad8379011e4470b94362189cafac93f (patch) | |
| tree | 4395205a3969d2cd3d3b6407fa77786b26aec809 | |
| parent | c5369d507341e6b6fe64d4e6f26e194cd39235ca (diff) | |
Fix lookup to prevent finding `typedef` itself. (#3848)
| -rw-r--r-- | source/slang/slang-ast-support-types.h | 3 | ||||
| -rw-r--r-- | source/slang/slang-check-decl.cpp | 3 | ||||
| -rw-r--r-- | source/slang/slang-check-expr.cpp | 7 | ||||
| -rw-r--r-- | source/slang/slang-check-impl.h | 10 | ||||
| -rw-r--r-- | source/slang/slang-lookup.cpp | 18 | ||||
| -rw-r--r-- | source/slang/slang-lookup.h | 6 | ||||
| -rw-r--r-- | source/slang/slang-parser.cpp | 11 | ||||
| -rw-r--r-- | tests/bugs/gh-3845-2.slang | 26 | ||||
| -rw-r--r-- | tests/bugs/gh-3845.slang | 27 |
9 files changed, 98 insertions, 13 deletions
diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h index e4e3be384..196a1d002 100644 --- a/source/slang/slang-ast-support-types.h +++ b/source/slang/slang-ast-support-types.h @@ -1421,6 +1421,9 @@ namespace Slang Scope* scope = nullptr; Scope* endScope = nullptr; + // A decl to exclude from the lookup, used to exclude the current decl being checked, such as in typedef Foo Foo; + // to avoid finding itself. + Decl* declToExclude = nullptr; LookupMask mask = LookupMask::Default; LookupOptions options = LookupOptions::None; diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index c844fb82a..ed97e412d 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -6203,7 +6203,8 @@ namespace Slang void SemanticsDeclHeaderVisitor::visitTypeDefDecl(TypeDefDecl* decl) { - decl->type = CheckProperType(decl->type); + SemanticsVisitor visitor(withDeclToExcludeFromLookup(decl)); + decl->type = visitor.CheckProperType(decl->type); checkVisibility(decl); } diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp index a31e17123..ad6bb2a86 100644 --- a/source/slang/slang-check-expr.cpp +++ b/source/slang/slang-check-expr.cpp @@ -2601,8 +2601,7 @@ namespace Slang } expr->type = QualType(m_astBuilder->getErrorType()); auto lookupResult = lookUp( - m_astBuilder, - this, expr->name, expr->scope); + m_astBuilder, this, expr->name, expr->scope, LookupMask::Default, false, getDeclToExcludeFromLookup()); bool diagnosed = false; lookupResult = filterLookupResultByVisibilityAndDiagnose(lookupResult, expr->loc, diagnosed); @@ -3703,7 +3702,9 @@ namespace Slang this, expr->name, namespaceDecl, - DeclRef(namespaceDecl)); + DeclRef(namespaceDecl), + LookupMask::Default, + getDeclToExcludeFromLookup()); AddToLookupResult(globalLookupResult, nsLookupResult); } } diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h index 278fc3265..a3ecc28b4 100644 --- a/source/slang/slang-check-impl.h +++ b/source/slang/slang-check-impl.h @@ -921,6 +921,15 @@ namespace Slang return result; } + SemanticsContext withDeclToExcludeFromLookup(Decl* decl) + { + SemanticsContext result(*this); + result.m_declToExcludeFromLookup = decl; + return result; + } + + Decl* getDeclToExcludeFromLookup() { return m_declToExcludeFromLookup; } + private: SharedSemanticsContext* m_shared = nullptr; @@ -928,6 +937,7 @@ namespace Slang ExprLocalScope* m_exprLocalScope = nullptr; + Decl* m_declToExcludeFromLookup = nullptr; protected: // TODO: consider making more of this state `private`... diff --git a/source/slang/slang-lookup.cpp b/source/slang/slang-lookup.cpp index 301c86aa8..6a62303d2 100644 --- a/source/slang/slang-lookup.cpp +++ b/source/slang/slang-lookup.cpp @@ -213,6 +213,8 @@ static void _lookUpDirectAndTransparentMembers( // it's unchecked or being checked then it isn't declared yet. if(!request.shouldConsiderAllLocalNames() && request.semantics && _isUncheckedLocalVar(m)) continue; + if (m == request.declToExclude) + continue; if (!DeclPassesLookupMask(m, request.mask)) continue; @@ -253,13 +255,15 @@ LookupRequest initLookupRequest( Name* name, LookupMask mask, LookupOptions options, - Scope* scope) + Scope* scope, + Decl* declToExclude) { LookupRequest request; request.semantics = semantics; request.mask = mask; request.options = options; request.scope = scope; + request.declToExclude = declToExclude; if (semantics && semantics->getSession() && name == semantics->getSession()->getCompletionRequestTokenName()) @@ -275,9 +279,10 @@ LookupResult lookUpDirectAndTransparentMembers( Name* name, ContainerDecl* containerDecl, DeclRef<Decl> parentDeclRef, - LookupMask mask) + LookupMask mask, + Decl* declToExclude) { - LookupRequest request = initLookupRequest(semantics, name, mask, LookupOptions::None, nullptr); + LookupRequest request = initLookupRequest(semantics, name, mask, LookupOptions::None, nullptr, declToExclude); LookupResult result; _lookUpDirectAndTransparentMembers( astBuilder, @@ -892,13 +897,14 @@ LookupResult lookUp( Name* name, Scope* scope, LookupMask mask, - bool considerAllLocalNamesInScope) + bool considerAllLocalNamesInScope, + Decl* declToExclude) { LookupResult result; const auto options = considerAllLocalNamesInScope ? LookupOptions::ConsiderAllLocalNamesInScope : LookupOptions::None; - LookupRequest request = initLookupRequest(semantics, name, mask, options, scope); + LookupRequest request = initLookupRequest(semantics, name, mask, options, scope, declToExclude); _lookUpInScopes(astBuilder, name, request, result); return result; } @@ -913,7 +919,7 @@ LookupResult lookUpMember( LookupOptions options) { LookupResult result; - LookupRequest request = initLookupRequest(semantics, name, mask, options, sourceScope); + LookupRequest request = initLookupRequest(semantics, name, mask, options, sourceScope, nullptr); _lookUpMembersInType(astBuilder, name, type, request, result, nullptr); return result; } diff --git a/source/slang/slang-lookup.h b/source/slang/slang-lookup.h index 84b453bf2..fb7511428 100644 --- a/source/slang/slang-lookup.h +++ b/source/slang/slang-lookup.h @@ -19,7 +19,8 @@ LookupResult lookUp( Name* name, Scope* scope, LookupMask mask = LookupMask::Default, - bool considerAllLocalNamesInScope = false); + bool considerAllLocalNamesInScope = false, + Decl* declToExclude = nullptr); // Perform member lookup in the context of a type LookupResult lookUpMember( @@ -38,7 +39,8 @@ LookupResult lookUpDirectAndTransparentMembers( Name* name, ContainerDecl* containerDecl, DeclRef<Decl> parentDeclRef, // The parent of the resulting declref. - LookupMask mask = LookupMask::Default); + LookupMask mask = LookupMask::Default, + Decl* declToExclude = nullptr); // TODO: this belongs somewhere else diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp index b99df18e4..cc3a661f3 100644 --- a/source/slang/slang-parser.cpp +++ b/source/slang/slang-parser.cpp @@ -2576,11 +2576,20 @@ namespace Slang typeSpec.expr = parseFuncTypeExpr(parser); return typeSpec; } + + bool inGlobalScope = false; + if (AdvanceIf(parser, TokenType::Scope)) + { + inGlobalScope = true; + } Token typeName = parser->ReadToken(TokenType::Identifier); auto basicType = parser->astBuilder->create<VarExpr>(); - basicType->scope = parser->currentLookupScope; + if (inGlobalScope) + basicType->scope = parser->currentModule->ownedScope; + else + basicType->scope = parser->currentLookupScope; basicType->loc = typeName.loc; basicType->name = typeName.getNameOrNull(); diff --git a/tests/bugs/gh-3845-2.slang b/tests/bugs/gh-3845-2.slang new file mode 100644 index 000000000..06a3d1c99 --- /dev/null +++ b/tests/bugs/gh-3845-2.slang @@ -0,0 +1,26 @@ +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-shaderobj -output-using-type +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-shaderobj -vk -output-using-type + +struct Foo {float v;}; + +namespace foo { + typedef ::Foo Foo; // unexpected '::', expected identifier; works in dxc/hlsl + + float test(Foo f) + { + return f.v; + } +} + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer<float> outputBuffer; + +[numthreads(4, 1, 1)] +[shader("compute")] +void computeMain(uint3 dispatchThreadID: SV_DispatchThreadID) +{ + Foo f; + f.v = 1.0; + // CHECK: 1.0 + outputBuffer[0] = foo.test(f); +} diff --git a/tests/bugs/gh-3845.slang b/tests/bugs/gh-3845.slang new file mode 100644 index 000000000..fe8da5acf --- /dev/null +++ b/tests/bugs/gh-3845.slang @@ -0,0 +1,27 @@ +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-shaderobj -output-using-type +//TEST(compute):COMPARE_COMPUTE(filecheck-buffer=CHECK):-shaderobj -vk -output-using-type + + +struct Foo {float v;}; + +namespace foo { + typedef Foo Foo; // cyclic reference 'Foo'; allowed in dxc/hlsl + + float test(Foo f) + { + return f.v; + } +} + +//TEST_INPUT:ubuffer(data=[0 0 0 0], stride=4):out,name outputBuffer +RWStructuredBuffer<float> outputBuffer; + +[numthreads(4, 1, 1)] +[shader("compute")] +void computeMain(uint3 dispatchThreadID: SV_DispatchThreadID) +{ + Foo f; + f.v = 1.0; + // CHECK: 1.0 + outputBuffer[0] = foo.test(f); +} |
