https://github.com/sdkrystian updated https://github.com/llvm/llvm-project/pull/92318
>From 4ae259b21661caae2a9cd89437c56f3915195682 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Wed, 15 May 2024 16:13:03 -0400 Subject: [PATCH 1/4] [Clang][Sema] Don't build CXXDependentScopeMemberExprs for potentially implicit class member access expressions --- clang/include/clang/Sema/Sema.h | 11 +-- clang/lib/Sema/SemaCXXScopeSpec.cpp | 8 ++ clang/lib/Sema/SemaExpr.cpp | 31 ++---- clang/lib/Sema/SemaTemplate.cpp | 98 ++++++------------- clang/lib/Sema/TreeTransform.h | 6 +- .../class.mfct/class.mfct.non-static/p3.cpp | 91 ++++++++++++++++- ...ms-function-specialization-class-scope.cpp | 52 ++++++++++ .../ms-lookup-template-base-classes.cpp | 12 +-- .../ASTMatchers/ASTMatchersNodeTest.cpp | 6 +- 9 files changed, 206 insertions(+), 109 deletions(-) diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 66d5e2d4a4ade..c35cb815fdfeb 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5366,11 +5366,9 @@ class Sema final : public SemaBase { bool UseArgumentDependentLookup(const CXXScopeSpec &SS, const LookupResult &R, bool HasTrailingLParen); - ExprResult - BuildQualifiedDeclarationNameExpr(CXXScopeSpec &SS, - const DeclarationNameInfo &NameInfo, - bool IsAddressOfOperand, const Scope *S, - TypeSourceInfo **RecoveryTSI = nullptr); + ExprResult BuildQualifiedDeclarationNameExpr( + CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI = nullptr); ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, @@ -8982,7 +8980,8 @@ class Sema final : public SemaBase { ExprResult BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs); + const TemplateArgumentListInfo *TemplateArgs, + bool IsAddressOfOperand); TemplateNameKind ActOnTemplateName(Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, diff --git a/clang/lib/Sema/SemaCXXScopeSpec.cpp b/clang/lib/Sema/SemaCXXScopeSpec.cpp index fca5bd131bbc0..c405fbc0aa421 100644 --- a/clang/lib/Sema/SemaCXXScopeSpec.cpp +++ b/clang/lib/Sema/SemaCXXScopeSpec.cpp @@ -796,6 +796,14 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, NestedNameSpecInfo &IdInfo, Diag(IdInfo.IdentifierLoc, diag::ext_undeclared_unqual_id_with_dependent_base) << IdInfo.Identifier << ContainingClass; + // Fake up a nested-name-specifier that starts with the + // injected-class-name of the enclosing class. + QualType T = Context.getTypeDeclType(ContainingClass); + TypeLocBuilder TLB; + TLB.pushTrivial(Context, T, IdInfo.IdentifierLoc); + SS.Extend(Context, /*TemplateKWLoc=*/SourceLocation(), + TLB.getTypeLocInContext(Context, T), IdInfo.IdentifierLoc); + // Add the identifier to form a dependent name. SS.Extend(Context, IdInfo.Identifier, IdInfo.IdentifierLoc, IdInfo.CCLoc); return false; diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 274e1fb183534..0e42501ea8ce2 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2946,26 +2946,14 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, /// this path. ExprResult Sema::BuildQualifiedDeclarationNameExpr( CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, - bool IsAddressOfOperand, const Scope *S, TypeSourceInfo **RecoveryTSI) { - if (NameInfo.getName().isDependentName()) - return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - DeclContext *DC = computeDeclContext(SS, false); - if (!DC) - return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - NameInfo, /*TemplateArgs=*/nullptr); - - if (RequireCompleteDeclContext(SS, DC)) - return ExprError(); - + bool IsAddressOfOperand, TypeSourceInfo **RecoveryTSI) { LookupResult R(*this, NameInfo, LookupOrdinaryName); - LookupQualifiedName(R, DC); + LookupParsedName(R, /*S=*/nullptr, &SS, /*ObjectType=*/QualType()); if (R.isAmbiguous()) return ExprError(); - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) return BuildDependentDeclRefExpr(SS, /*TemplateKWLoc=*/SourceLocation(), NameInfo, /*TemplateArgs=*/nullptr); @@ -2974,6 +2962,7 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( // diagnostic during template instantiation is likely bogus, e.g. if a class // is invalid because it's derived from an invalid base class, then missing // members were likely supposed to be inherited. + DeclContext *DC = computeDeclContext(SS); if (const auto *CD = dyn_cast<CXXRecordDecl>(DC)) if (CD->isInvalidDecl()) return ExprError(); @@ -3017,16 +3006,14 @@ ExprResult Sema::BuildQualifiedDeclarationNameExpr( return ExprEmpty(); } - // Defend against this resolving to an implicit member access. We usually - // won't get here if this might be a legitimate a class member (we end up in - // BuildMemberReferenceExpr instead), but this can be valid if we're forming - // a pointer-to-member or in an unevaluated context in C++11. - if (!R.empty() && (*R.begin())->isCXXClassMember() && !IsAddressOfOperand) + // If necessary, build an implicit class member access. + if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) return BuildPossibleImplicitMemberExpr(SS, /*TemplateKWLoc=*/SourceLocation(), - R, /*TemplateArgs=*/nullptr, S); + R, /*TemplateArgs=*/nullptr, + /*S=*/nullptr); - return BuildDeclarationNameExpr(SS, R, /* ADL */ false); + return BuildDeclarationNameExpr(SS, R, /*ADL=*/false); } /// Cast a base object to a member's actual type. diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index a5350ceb59cb7..80247c8b633ed 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -726,44 +726,18 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs) { - DeclContext *DC = getFunctionLevelDeclContext(); - - // C++11 [expr.prim.general]p12: - // An id-expression that denotes a non-static data member or non-static - // member function of a class can only be used: - // (...) - // - if that id-expression denotes a non-static data member and it - // appears in an unevaluated operand. - // - // If this might be the case, form a DependentScopeDeclRefExpr instead of a - // CXXDependentScopeMemberExpr. The former can instantiate to either - // DeclRefExpr or MemberExpr depending on lookup results, while the latter is - // always a MemberExpr. - bool MightBeCxx11UnevalField = - getLangOpts().CPlusPlus11 && isUnevaluatedContext(); - - // Check if the nested name specifier is an enum type. - bool IsEnum = false; - if (NestedNameSpecifier *NNS = SS.getScopeRep()) - IsEnum = isa_and_nonnull<EnumType>(NNS->getAsType()); - - if (!MightBeCxx11UnevalField && !isAddressOfOperand && !IsEnum && - isa<CXXMethodDecl>(DC) && - cast<CXXMethodDecl>(DC)->isImplicitObjectMemberFunction()) { - QualType ThisType = - cast<CXXMethodDecl>(DC)->getThisType().getNonReferenceType(); - - // Since the 'this' expression is synthesized, we don't need to - // perform the double-lookup check. - NamedDecl *FirstQualifierInScope = nullptr; + if (SS.isEmpty()) { + QualType ThisType = getCurrentThisType(); + if (ThisType.isNull()) + return ExprError(); return CXXDependentScopeMemberExpr::Create( - Context, /*This=*/nullptr, ThisType, + Context, /*Base=*/nullptr, ThisType, /*IsArrow=*/!Context.getLangOpts().HLSL, - /*Op=*/SourceLocation(), SS.getWithLocInContext(Context), TemplateKWLoc, - FirstQualifierInScope, NameInfo, TemplateArgs); + /*OperatorLoc=*/SourceLocation(), + /*QualifierLoc*/ NestedNameSpecifierLoc(), TemplateKWLoc, + /*FirstQualifierFoundInScope*/ nullptr, NameInfo, TemplateArgs); } - return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); } @@ -772,13 +746,15 @@ Sema::BuildDependentDeclRefExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs) { - // DependentScopeDeclRefExpr::Create requires a valid QualifierLoc - NestedNameSpecifierLoc QualifierLoc = SS.getWithLocInContext(Context); - if (!QualifierLoc) - return ExprError(); + // DependentScopeDeclRefExpr::Create requires a valid NestedNameSpecifierLoc + if (!SS.isValid()) + return CreateRecoveryExpr( + SS.getBeginLoc(), + TemplateArgs ? TemplateArgs->getRAngleLoc() : NameInfo.getEndLoc(), {}); return DependentScopeDeclRefExpr::Create( - Context, QualifierLoc, TemplateKWLoc, NameInfo, TemplateArgs); + Context, SS.getWithLocInContext(Context), TemplateKWLoc, NameInfo, + TemplateArgs); } @@ -5745,50 +5721,36 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, } // We actually only call this from template instantiation. -ExprResult -Sema::BuildQualifiedTemplateIdExpr(CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - const DeclarationNameInfo &NameInfo, - const TemplateArgumentListInfo *TemplateArgs) { - +ExprResult Sema::BuildQualifiedTemplateIdExpr( + CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + const DeclarationNameInfo &NameInfo, + const TemplateArgumentListInfo *TemplateArgs, bool IsAddressOfOperand) { assert(TemplateArgs || TemplateKWLoc.isValid()); - DeclContext *DC; - if (!(DC = computeDeclContext(SS, false)) || - DC->isDependentContext() || - RequireCompleteDeclContext(SS, DC)) - return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); LookupResult R(*this, NameInfo, LookupOrdinaryName); - if (LookupTemplateName(R, (Scope *)nullptr, SS, QualType(), - /*Entering*/ false, TemplateKWLoc)) + if (LookupTemplateName(R, /*S=*/nullptr, SS, /*ObjectType=*/QualType(), + /*EnteringContext=*/false, TemplateKWLoc)) return ExprError(); if (R.isAmbiguous()) return ExprError(); + if (R.wasNotFoundInCurrentInstantiation() || SS.isInvalid()) + return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); + if (R.empty()) { + DeclContext *DC = computeDeclContext(SS); Diag(NameInfo.getLoc(), diag::err_no_member) << NameInfo.getName() << DC << SS.getRange(); return ExprError(); } - auto DiagnoseTypeTemplateDecl = [&](TemplateDecl *Temp, - bool isTypeAliasTemplateDecl) { - Diag(NameInfo.getLoc(), diag::err_template_kw_refers_to_type_template) - << SS.getScopeRep() << NameInfo.getName().getAsString() << SS.getRange() - << isTypeAliasTemplateDecl; - Diag(Temp->getLocation(), diag::note_referenced_type_template) - << isTypeAliasTemplateDecl; - return CreateRecoveryExpr(NameInfo.getBeginLoc(), NameInfo.getEndLoc(), {}); - }; - - if (ClassTemplateDecl *Temp = R.getAsSingle<ClassTemplateDecl>()) - return DiagnoseTypeTemplateDecl(Temp, false); - - if (TypeAliasTemplateDecl *Temp = R.getAsSingle<TypeAliasTemplateDecl>()) - return DiagnoseTypeTemplateDecl(Temp, true); + // If necessary, build an implicit class member access. + if (isPotentialImplicitMemberAccess(SS, R, IsAddressOfOperand)) + return BuildPossibleImplicitMemberExpr(SS, TemplateKWLoc, R, TemplateArgs, + /*S=*/nullptr); - return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL*/ false, TemplateArgs); + return BuildTemplateIdExpr(SS, TemplateKWLoc, R, /*ADL=*/false, TemplateArgs); } /// Form a template name from a name that is syntactically required to name a diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index b10e5ba65eb1c..2625d4e44bb84 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3478,11 +3478,11 @@ class TreeTransform { SS.Adopt(QualifierLoc); if (TemplateArgs || TemplateKWLoc.isValid()) - return getSema().BuildQualifiedTemplateIdExpr(SS, TemplateKWLoc, NameInfo, - TemplateArgs); + return getSema().BuildQualifiedTemplateIdExpr( + SS, TemplateKWLoc, NameInfo, TemplateArgs, IsAddressOfOperand); return getSema().BuildQualifiedDeclarationNameExpr( - SS, NameInfo, IsAddressOfOperand, /*S*/nullptr, RecoveryTSI); + SS, NameInfo, IsAddressOfOperand, RecoveryTSI); } /// Build a new template-id expression. diff --git a/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp b/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp index 9116e7146f812..01fa923dd1715 100644 --- a/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp +++ b/clang/test/CXX/class/class.mfct/class.mfct.non-static/p3.cpp @@ -70,7 +70,7 @@ namespace test2 { } void test1() { - B<T>::foo(); + B<T>::foo(); // expected-error {{call to non-static member function without an object argument}} } static void test2() { @@ -91,8 +91,95 @@ namespace test2 { int test() { A<int> a; a.test0(); // no instantiation note here, decl is ill-formed - a.test1(); + a.test1(); // expected-note {{in instantiation}} a.test2(); // expected-note {{in instantiation}} a.test3(); // expected-note {{in instantiation}} } } + +namespace test3 { + struct A { + void f0(); + + template<typename T> + void f1(); + + static void f2(); + + template<typename T> + static void f3(); + + int x0; + + static constexpr int x1 = 0; + + template<typename T> + static constexpr int x2 = 0; + }; + + template<typename T> + struct B : T { + auto g0() -> decltype(T::f0()); + + auto g1() -> decltype(T::template f1<int>()); + + auto g2() -> decltype(T::f2()); + + auto g3() -> decltype(T::template f3<int>()); + + auto g4() -> decltype(T::x0); + + auto g5() -> decltype(T::x1); + + auto g6() -> decltype(T::template x2<int>); + + decltype(T::f0()) g7(); // expected-error {{call to non-static member function without an object argument}} + + decltype(T::template f1<int>()) g8(); // expected-error {{call to non-static member function without an object argument}} + + decltype(T::f2()) g9(); + + decltype(T::template f3<int>()) g10(); + + decltype(T::x0) g11(); + + decltype(T::x1) g12(); + + decltype(T::template x2<int>) g13(); + }; + + template struct B<A>; // expected-note {{in instantiation of}} + + template<typename T> + struct C : T { + static auto g0() -> decltype(T::f0()); // expected-error {{'this' cannot be implicitly used in a static member function declaration}} + + static auto g1() -> decltype(T::template f1<int>()); // expected-error {{'this' cannot be implicitly used in a static member function declaration}} + + static auto g2() -> decltype(T::f2()); + + static auto g3() -> decltype(T::template f3<int>()); + + static auto g4() -> decltype(T::x0); // expected-error {{'this' cannot be implicitly used in a static member function declaration}} + + static auto g5() -> decltype(T::x1); + + static auto g6() -> decltype(T::template x2<int>); + + static decltype(T::f0()) g7(); // expected-error {{call to non-static member function without an object argument}} + + static decltype(T::template f1<int>()) g8(); // expected-error {{call to non-static member function without an object argument}} + + static decltype(T::f2()) g9(); + + static decltype(T::template f3<int>()) g10(); + + static decltype(T::x0) g11(); + + static decltype(T::x1) g12(); + + static decltype(T::template x2<int>) g13(); + }; + + template struct C<A>; // expected-note {{in instantiation of}} +} diff --git a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp index c49d2cb2422fa..e1f3ab37ad947 100644 --- a/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp +++ b/clang/test/SemaTemplate/ms-function-specialization-class-scope.cpp @@ -464,6 +464,32 @@ namespace UsesThis { g1(x1); g1(y0); g1(y1); + + T::f0(0); + T::f0(z); + T::f0(x0); + T::f0(x1); + T::f0(y0); + T::f0(y1); + T::g0(0); + T::g0(z); + T::g0(x0); + T::g0(x1); + T::g0(y0); + T::g0(y1); + + E::f1(0); + E::f1(z); + E::f1(x0); + E::f1(x1); + E::f1(y0); + E::f1(y1); + E::g1(0); + E::g1(z); + E::g1(x0); + E::g1(x1); + E::g1(y0); + E::g1(y1); } template<> @@ -519,6 +545,32 @@ namespace UsesThis { g1(x1); // expected-error {{invalid use of member 'x1' in static member function}} g1(y0); g1(y1); + + T::f0(0); // expected-error {{call to non-static member function without an object argument}} + T::f0(z); // expected-error {{call to non-static member function without an object argument}} + T::f0(x0); // expected-error {{call to non-static member function without an object argument}} + T::f0(x1); // expected-error {{call to non-static member function without an object argument}} + T::f0(y0); // expected-error {{call to non-static member function without an object argument}} + T::f0(y1); // expected-error {{call to non-static member function without an object argument}} + T::g0(0); + T::g0(z); + T::g0(x0); // expected-error {{invalid use of member 'x0' in static member function}} + T::g0(x1); // expected-error {{invalid use of member 'x1' in static member function}} + T::g0(y0); + T::g0(y1); + + E::f1(0); // expected-error {{call to non-static member function without an object argument}} + E::f1(z); // expected-error {{call to non-static member function without an object argument}} + E::f1(x0); // expected-error {{call to non-static member function without an object argument}} + E::f1(x1); // expected-error {{call to non-static member function without an object argument}} + E::f1(y0); // expected-error {{call to non-static member function without an object argument}} + E::f1(y1); // expected-error {{call to non-static member function without an object argument}} + E::g1(0); + E::g1(z); + E::g1(x0); // expected-error {{invalid use of member 'x0' in static member function}} + E::g1(x1); // expected-error {{invalid use of member 'x1' in static member function}} + E::g1(y0); + E::g1(y1); } }; diff --git a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp index 534a5dc9ddc10..547e5945ac6bc 100644 --- a/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp +++ b/clang/test/SemaTemplate/ms-lookup-template-base-classes.cpp @@ -102,7 +102,7 @@ class B : public A<T> { }; template class B<int>; // expected-note {{requested here}} -} +} @@ -111,8 +111,8 @@ namespace lookup_dependent_base_class_default_argument { template<class T> class A { public: - static int f1(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} - int f2(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} + static int f1(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} + int f2(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} }; template<class T> @@ -137,7 +137,7 @@ namespace lookup_dependent_base_class_friend { template <class T> class B { public: - static void g(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} + static void g(); // expected-note {{must qualify identifier to find this declaration in dependent base class}} }; template <class T> @@ -228,7 +228,7 @@ template <typename T> struct C : T { int *bar() { return &b; } // expected-error {{no member named 'b' in 'PR16014::C<A>'}} expected-warning {{lookup into dependent bases}} int baz() { return T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} int T::*qux() { return &T::b; } // expected-error {{no member named 'b' in 'PR16014::A'}} - int T::*fuz() { return &U::a; } // expected-error {{use of undeclared identifier 'U'}} \ + int T::*fuz() { return &U::a; } // expected-error {{no member named 'U' in 'PR16014::C<A>'}} \ // expected-warning {{unqualified lookup into dependent bases of class template 'C'}} }; @@ -258,7 +258,7 @@ struct A : T { ::UndefClass::undef(); // expected-error {{no member named 'UndefClass' in the global namespace}} } void baz() { - B::qux(); // expected-error {{use of undeclared identifier 'B'}} \ + B::qux(); // expected-error {{no member named 'B' in 'PR19233::A<D>'}} \ // expected-warning {{unqualified lookup into dependent bases of class template 'A'}} } }; diff --git a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp index 65df513d27137..2e42b85808953 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp +++ b/clang/unittests/ASTMatchers/ASTMatchersNodeTest.cpp @@ -614,8 +614,10 @@ TEST_P(ASTMatchersTest, MemberExpr_MatchesVariable) { EXPECT_TRUE(matches("template <class T>" "class X : T { void f() { this->T::v; } };", cxxDependentScopeMemberExpr())); - EXPECT_TRUE(matches("template <class T> class X : T { void f() { T::v; } };", - cxxDependentScopeMemberExpr())); + // FIXME: Add a matcher for DependentScopeDeclRefExpr. + EXPECT_TRUE( + notMatches("template <class T> class X : T { void f() { T::v; } };", + cxxDependentScopeMemberExpr())); EXPECT_TRUE(matches("template <class T> void x() { T t; t.v; }", cxxDependentScopeMemberExpr())); } >From db8dc4f1c1c32722aa7dad797422d24aca1d8024 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Wed, 15 May 2024 18:02:14 -0400 Subject: [PATCH 2/4] [FOLD] comment fixup --- clang/lib/Sema/SemaTemplate.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 80247c8b633ed..41240daeffaae 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -727,6 +727,10 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, bool isAddressOfOperand, const TemplateArgumentListInfo *TemplateArgs) { if (SS.isEmpty()) { + // FIXME: This codepath is only used by dependent unqualified names + // (e.g. a dependent conversion-function-id, or operator= once we support + // it). It doesn't quite do the right thing, and it will silently fail if + // getCurrentThisType() returns null. QualType ThisType = getCurrentThisType(); if (ThisType.isNull()) return ExprError(); @@ -735,8 +739,8 @@ Sema::ActOnDependentIdExpression(const CXXScopeSpec &SS, Context, /*Base=*/nullptr, ThisType, /*IsArrow=*/!Context.getLangOpts().HLSL, /*OperatorLoc=*/SourceLocation(), - /*QualifierLoc*/ NestedNameSpecifierLoc(), TemplateKWLoc, - /*FirstQualifierFoundInScope*/ nullptr, NameInfo, TemplateArgs); + /*QualifierLoc=*/NestedNameSpecifierLoc(), TemplateKWLoc, + /*FirstQualifierFoundInScope=*/nullptr, NameInfo, TemplateArgs); } return BuildDependentDeclRefExpr(SS, TemplateKWLoc, NameInfo, TemplateArgs); } >From 6813e7d926fa31c503b61a331f31e07658beda4b Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Thu, 16 May 2024 07:42:36 -0400 Subject: [PATCH 3/4] [FOLD] replace uses of LookupResult::NotFoundInCurrentInstantiation with wasNotFoundInCurrentInstantiation() --- clang/lib/Sema/SemaExpr.cpp | 2 +- clang/lib/Sema/SemaTemplate.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 0e42501ea8ce2..9818d7afe8e10 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2791,7 +2791,7 @@ Sema::ActOnIdExpression(Scope *S, CXXScopeSpec &SS, // If the result might be in a dependent base class, this is a dependent // id-expression. - if (R.getResultKind() == LookupResult::NotFoundInCurrentInstantiation) + if (R.wasNotFoundInCurrentInstantiation()) return ActOnDependentIdExpression(SS, TemplateKWLoc, NameInfo, IsAddressOfOperand, TemplateArgs); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 41240daeffaae..fe82665cf282c 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -5946,8 +5946,7 @@ bool Sema::CheckTemplateTypeArgument( LookupParsedName(Result, CurScope, &SS, /*ObjectType=*/QualType()); if (Result.getAsSingle<TypeDecl>() || - Result.getResultKind() == - LookupResult::NotFoundInCurrentInstantiation) { + Result.wasNotFoundInCurrentInstantiation()) { assert(SS.getScopeRep() && "dependent scope expr must has a scope!"); // Suggest that the user add 'typename' before the NNS. SourceLocation Loc = AL.getSourceRange().getBegin(); >From 4ee87cef2b5731be3d0f6715e1ee26d9659911f2 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Thu, 16 May 2024 17:41:08 -0400 Subject: [PATCH 4/4] [FOLD] add release note --- clang/docs/ReleaseNotes.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d2928e418623..d849cae20594c 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -724,6 +724,8 @@ Bug Fixes to C++ Support templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Clang no longer transforms dependent qualified names into implicit class member access expressions + until it can be determined whether the name is that of a non-static member. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits