From dc39390759a3925902c70b673bcd261bc46b2420 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 1 Mar 2024 08:08:52 -0500 Subject: [PATCH 01/27] [Clang][Sema] Earlier resolution of class member access expressions naming member of the current instantiation --- clang/lib/AST/Expr.cpp | 2 +- clang/lib/Sema/SemaExpr.cpp | 4 +- clang/lib/Sema/SemaExprMember.cpp | 121 ++++++++++++++------ clang/lib/Sema/SemaOverload.cpp | 3 + clang/test/SemaTemplate/dependent-names.cpp | 4 +- 5 files changed, 93 insertions(+), 41 deletions(-) diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 9eec7edc9d1a3..ef0a149a7e693 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -103,7 +103,7 @@ const Expr *Expr::skipRValueSubobjectAdjustments( } } else if (const auto *ME = dyn_cast(E)) { if (!ME->isArrow()) { - assert(ME->getBase()->getType()->isRecordType()); + assert(ME->getBase()->getType()->getAsRecordDecl()); if (const auto *Field = dyn_cast(ME->getMemberDecl())) { if (!Field->isBitField() && !Field->getType()->isReferenceType()) { E = ME->getBase(); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 5c861467bc102..020130b885cd0 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -673,7 +673,9 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // expressions of certain types in C++. if (getLangOpts().CPlusPlus && (E->getType() == Context.OverloadTy || - T->isDependentType() || + // FIXME: This is a hack! We want the lvalue-to-rvalue conversion applied + // to pointer types even if the pointee type is dependent. + (T->isDependentType() && !T->isPointerType()) || T->isRecordType())) return E; diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 6e30716b9ae43..850f182facf2d 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -667,8 +667,8 @@ namespace { // classes, one of its base classes. class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback { public: - explicit RecordMemberExprValidatorCCC(const RecordType *RTy) - : Record(RTy->getDecl()) { + explicit RecordMemberExprValidatorCCC(QualType RTy) + : Record(RTy->getAsRecordDecl()) { // Don't add bare keywords to the consumer since they will always fail // validation by virtue of not being associated with any decls. WantTypeSpecifiers = false; @@ -714,33 +714,55 @@ class RecordMemberExprValidatorCCC final : public CorrectionCandidateCallback { static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, Expr *BaseExpr, - const RecordType *RTy, + QualType RTy, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, bool HasTemplateArgs, SourceLocation TemplateKWLoc, TypoExpr *&TE) { + RecordDecl *RDecl = RTy->getAsRecordDecl(); + DeclContext *DC = SemaRef.computeDeclContext(RTy); + // If the object expression is dependent and isn't the current instantiation, + // lookup will not find anything and we must defer until instantiation. + if (!DC) { + R.setNotFoundInCurrentInstantiation(); + return false; + } + + // FIXME: Should this use Name.isDependentName()? + if (DeclarationName Name = R.getLookupName(); + Name.getNameKind() == DeclarationName::CXXConversionFunctionName && + Name.getCXXNameType()->isDependentType()) { + R.setNotFoundInCurrentInstantiation(); + return false; + } + SourceRange BaseRange = BaseExpr ? BaseExpr->getSourceRange() : SourceRange(); - RecordDecl *RDecl = RTy->getDecl(); - if (!SemaRef.isThisOutsideMemberFunctionBody(QualType(RTy, 0)) && - SemaRef.RequireCompleteType(OpLoc, QualType(RTy, 0), + if (!RTy->isDependentType() && + !SemaRef.isThisOutsideMemberFunctionBody(RTy) && + SemaRef.RequireCompleteType(OpLoc, RTy, diag::err_typecheck_incomplete_tag, BaseRange)) return true; if (HasTemplateArgs || TemplateKWLoc.isValid()) { // LookupTemplateName doesn't expect these both to exist simultaneously. - QualType ObjectType = SS.isSet() ? QualType() : QualType(RTy, 0); + QualType ObjectType = SS.isSet() ? QualType() : RTy; bool MOUS; return SemaRef.LookupTemplateName(R, nullptr, SS, ObjectType, false, MOUS, TemplateKWLoc); } - DeclContext *DC = RDecl; if (SS.isSet()) { // If the member name was a qualified-id, look into the // nested-name-specifier. DC = SemaRef.computeDeclContext(SS, false); + // We tried to look into a dependent context that is not the current + // instantiation. Defer lookup until instantiation. + if (!DC) { + R.setNotFoundInCurrentInstantiation(); + return false; + } if (SemaRef.RequireCompleteDeclContext(SS, DC)) { SemaRef.Diag(SS.getRange().getEnd(), diag::err_typecheck_incomplete_tag) @@ -760,7 +782,7 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, // The record definition is complete, now look up the member. SemaRef.LookupQualifiedName(R, DC, SS); - if (!R.empty()) + if (!R.empty() || R.wasNotFoundInCurrentInstantiation()) return false; DeclarationName Typo = R.getLookupName(); @@ -824,6 +846,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, const TemplateArgumentListInfo *TemplateArgs, const Scope *S, ActOnMemberAccessExtraArgs *ExtraArgs) { + #if 0 if (BaseType->isDependentType() || (SS.isSet() && isDependentScopeSpecifier(SS)) || NameInfo.getName().isDependentName()) @@ -831,6 +854,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, IsArrow, OpLoc, SS, TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs); + #endif LookupResult R(*this, NameInfo, LookupMemberName); @@ -840,7 +864,7 @@ Sema::BuildMemberReferenceExpr(Expr *Base, QualType BaseType, QualType RecordTy = BaseType; if (IsArrow) RecordTy = RecordTy->castAs()->getPointeeType(); if (LookupMemberExprInRecord( - *this, R, nullptr, RecordTy->castAs(), OpLoc, IsArrow, + *this, R, nullptr, RecordTy, OpLoc, IsArrow, SS, TemplateArgs != nullptr, TemplateKWLoc, TE)) return ExprError(); if (TE) @@ -1033,6 +1057,14 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, const Scope *S, bool SuppressQualifierCheck, ActOnMemberAccessExtraArgs *ExtraArgs) { + + if (R.wasNotFoundInCurrentInstantiation() || (SS.isValid() && !computeDeclContext(SS, false))) { + return ActOnDependentMemberExpr(BaseExpr, BaseExprType, + IsArrow, OpLoc, + SS, TemplateKWLoc, FirstQualifierInScope, + R.getLookupNameInfo(), TemplateArgs); + } + QualType BaseType = BaseExprType; if (IsArrow) { assert(BaseType->isPointerType()); @@ -1071,11 +1103,11 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, // Rederive where we looked up. DeclContext *DC = (SS.isSet() ? computeDeclContext(SS, false) - : BaseType->castAs()->getDecl()); + : BaseType->getAsRecordDecl()); if (ExtraArgs) { ExprResult RetryExpr; - if (!IsArrow && BaseExpr) { + if (!IsArrow && BaseExpr && !BaseExpr->isTypeDependent()) { SFINAETrap Trap(*this, true); ParsedType ObjectType; bool MayBePseudoDestructor = false; @@ -1098,9 +1130,16 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, } } - Diag(R.getNameLoc(), diag::err_no_member) - << MemberName << DC - << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); + if(DC) { + Diag(R.getNameLoc(), diag::err_no_member) + << MemberName << DC + << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); + } else { + // FIXME: Is this needed? + Diag(R.getNameLoc(), diag::err_no_member) + << MemberName << BaseExprType + << (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); + } return ExprError(); } @@ -1330,7 +1369,10 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, return ExprError(); QualType BaseType = BaseExpr.get()->getType(); + + #if 0 assert(!BaseType->isDependentType()); + #endif DeclarationName MemberName = R.getLookupName(); SourceLocation MemberLoc = R.getNameLoc(); @@ -1342,29 +1384,32 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, if (IsArrow) { if (const PointerType *Ptr = BaseType->getAs()) BaseType = Ptr->getPointeeType(); - else if (const ObjCObjectPointerType *Ptr + else if (!BaseType->isDependentType()) { + if (const ObjCObjectPointerType *Ptr = BaseType->getAs()) BaseType = Ptr->getPointeeType(); - else if (BaseType->isRecordType()) { - // Recover from arrow accesses to records, e.g.: - // struct MyRecord foo; - // foo->bar - // This is actually well-formed in C++ if MyRecord has an - // overloaded operator->, but that should have been dealt with - // by now--or a diagnostic message already issued if a problem - // was encountered while looking for the overloaded operator->. - if (!S.getLangOpts().CPlusPlus) { - S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) - << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() - << FixItHint::CreateReplacement(OpLoc, "."); + else if (BaseType->isRecordType()) { + // Recover from arrow accesses to records, e.g.: + // struct MyRecord foo; + // foo->bar + // This is actually well-formed in C++ if MyRecord has an + // overloaded operator->, but that should have been dealt with + // by now--or a diagnostic message already issued if a problem + // was encountered while looking for the overloaded operator->. + if (!S.getLangOpts().CPlusPlus) { + S.Diag(OpLoc, diag::err_typecheck_member_reference_suggestion) + << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange() + << FixItHint::CreateReplacement(OpLoc, "."); + } + IsArrow = false; + } else if (BaseType->isFunctionType()) { + goto fail; + } else { + S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) + << BaseType << BaseExpr.get()->getSourceRange(); + return ExprError(); } - IsArrow = false; - } else if (BaseType->isFunctionType()) { - goto fail; - } else { - S.Diag(MemberLoc, diag::err_typecheck_member_reference_arrow) - << BaseType << BaseExpr.get()->getSourceRange(); - return ExprError(); + } } @@ -1384,9 +1429,9 @@ static ExprResult LookupMemberExpr(Sema &S, LookupResult &R, } // Handle field access to simple records. - if (const RecordType *RTy = BaseType->getAs()) { + if (BaseType->getAsRecordDecl() || BaseType->isDependentType()) { TypoExpr *TE = nullptr; - if (LookupMemberExprInRecord(S, R, BaseExpr.get(), RTy, OpLoc, IsArrow, SS, + if (LookupMemberExprInRecord(S, R, BaseExpr.get(), BaseType, OpLoc, IsArrow, SS, HasTemplateArgs, TemplateKWLoc, TE)) return ExprError(); @@ -1824,12 +1869,14 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, if (Result.isInvalid()) return ExprError(); Base = Result.get(); + #if 0 if (Base->getType()->isDependentType() || Name.isDependentName() || isDependentScopeSpecifier(SS)) { return ActOnDependentMemberExpr(Base, Base->getType(), IsArrow, OpLoc, SS, TemplateKWLoc, FirstQualifierInScope, NameInfo, TemplateArgs); } + #endif ActOnMemberAccessExtraArgs ExtraArgs = {S, Id, ObjCImpDecl}; ExprResult Res = BuildMemberReferenceExpr( diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 04cd9e78739d2..27c3fd51422b6 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -5805,7 +5805,10 @@ static ImplicitConversionSequence TryObjectArgumentInitialization( return ICS; } + // FIXME: Should this check getAsRecordDecl instead? + #if 0 assert(FromType->isRecordType()); + #endif QualType ClassType = S.Context.getTypeDeclType(ActingContext); // C++98 [class.dtor]p2: diff --git a/clang/test/SemaTemplate/dependent-names.cpp b/clang/test/SemaTemplate/dependent-names.cpp index 641ec950054f5..a661f14af80d3 100644 --- a/clang/test/SemaTemplate/dependent-names.cpp +++ b/clang/test/SemaTemplate/dependent-names.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s typedef double A; template class B { @@ -334,7 +334,7 @@ int arr[sizeof(Sub)]; namespace PR11421 { template < unsigned > struct X { static const unsigned dimension = 3; - template + template struct Y: Y { }; // expected-error{{circular inheritance between 'Y' and 'Y'}} }; typedef X<3> X3; From 0438e872148470c2f63b905fdf8066c5bc1f3bbb Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Fri, 1 Mar 2024 11:54:23 -0500 Subject: [PATCH 02/27] [FOLD] update tests --- .../temp.res/temp.dep/temp.dep.type/p4.cpp | 110 ++++++++++++++++++ .../SemaTemplate/instantiate-function-1.cpp | 14 +-- 2 files changed, 117 insertions(+), 7 deletions(-) create mode 100644 clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp diff --git a/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp new file mode 100644 index 0000000000000..7b36e3ad3b013 --- /dev/null +++ b/clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p4.cpp @@ -0,0 +1,110 @@ +// RUN: %clang_cc1 -Wno-unused-value -verify %s + +namespace N0 { + template + struct A { + int x; + void f(); + using X = int; + + void not_instantiated(A *a, A &b) { + x; + f(); + new X; + + this->x; + this->f(); + this->A::x; + this->A::f(); + + a->x; + a->f(); + a->A::x; + a->A::f(); + + (*this).x; + (*this).f(); + (*this).A::x; + (*this).A::f(); + + b.x; + b.f(); + b.A::x; + b.A::f(); + + A::x; + A::f(); + new A::X; + + y; // expected-error{{use of undeclared identifier 'y'}} + g(); // expected-error{{use of undeclared identifier 'g'}} + new Y; // expected-error{{unknown type name 'Y'}} + + this->y; // expected-error{{no member named 'y' in 'A'}} + this->g(); // expected-error{{no member named 'g' in 'A'}} + this->A::y; // expected-error{{no member named 'y' in 'A'}} + this->A::g(); // expected-error{{no member named 'g' in 'A'}} + + a->y; // expected-error{{no member named 'y' in 'A'}} + a->g(); // expected-error{{no member named 'g' in 'A'}} + a->A::y; // expected-error{{no member named 'y' in 'A'}} + a->A::g(); // expected-error{{no member named 'g' in 'A'}} + + // FIXME: An overloaded unary 'operator*' is built for these + // even though the operand is a pointer (to a dependent type). + // Type::isOverloadableType should return false for such cases. + (*this).y; + (*this).g(); + (*this).A::y; + (*this).A::g(); + + b.y; // expected-error{{no member named 'y' in 'A'}} + b.g(); // expected-error{{no member named 'g' in 'A'}} + b.A::y; // expected-error{{no member named 'y' in 'A'}} + b.A::g(); // expected-error{{no member named 'g' in 'A'}} + + A::y; // expected-error{{no member named 'y' in 'A'}} + A::g(); // expected-error{{no member named 'g' in 'A'}} + new A::Y; // expected-error{{no type named 'Y' in 'A'}} + } + }; +} // namespace N0 + +namespace N1 { + struct A { + template + void f(); + }; + + template + struct B { + template + void f(); + + A x; + A g(); + + void not_instantiated(B *a, B &b) { + f<0>(); + this->f<0>(); + a->f<0>(); + // FIXME: This should not require 'template'! + (*this).f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + b.f<0>(); + + x.f<0>(); + this->x.f<0>(); + a->x.f<0>(); + // FIXME: This should not require 'template'! + (*this).x.f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + b.x.f<0>(); + + // FIXME: None of these should require 'template'! + g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + this->g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + a->g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + (*this).g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + b.g().f<0>(); // expected-error{{missing 'template' keyword prior to dependent template name 'f'}} + } + }; +} // namespace N1 diff --git a/clang/test/SemaTemplate/instantiate-function-1.cpp b/clang/test/SemaTemplate/instantiate-function-1.cpp index ceef274377480..a4967264c654b 100644 --- a/clang/test/SemaTemplate/instantiate-function-1.cpp +++ b/clang/test/SemaTemplate/instantiate-function-1.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s template struct X0 { - void f(T x, U y) { + void f(T x, U y) { (void)(x + y); // expected-error{{invalid operands}} } }; @@ -41,7 +41,7 @@ template struct X4 { T f() const { return; // expected-error{{non-void function 'f' should return a value}} } - + T g() const { return 1; // expected-error{{void function 'g' should not return a value}} } @@ -64,7 +64,7 @@ template struct X6 { // IfStmt if (t > 0) return u; - else { + else { if (t < 0) return v; // expected-error{{cannot initialize return object of type}} } @@ -131,12 +131,12 @@ template struct Member0 { t; t.f; t->f; - + T* tp; tp.f; // expected-error{{member reference base type 'T *' is not a structure or union}} tp->f; - this->f; + this->f; // expected-error{{reference to non-static member function must be called}} this.f; // expected-error{{member reference base type 'Member0 *' is not a structure or union}} } }; @@ -239,11 +239,11 @@ namespace PR9880 { static yes_tag check(char[sizeof(&U::luaIndex)]); enum { value = sizeof(check(0)) == sizeof(yes_tag) }; }; - + class SomeClass { public: int luaIndex(lua_State* L); }; - + int i = HasIndexMetamethod::value; } From 91f09205c520498e4969a79fec1bb147df025a86 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Mon, 4 Mar 2024 06:59:58 -0500 Subject: [PATCH 03/27] [FOLD] build DependentMemberExpr for LookupResult::FoundUnresolved --- clang/lib/Sema/SemaExprMember.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 850f182facf2d..1e5e05b0e60c3 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -719,7 +719,6 @@ static bool LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, CXXScopeSpec &SS, bool HasTemplateArgs, SourceLocation TemplateKWLoc, TypoExpr *&TE) { - RecordDecl *RDecl = RTy->getAsRecordDecl(); DeclContext *DC = SemaRef.computeDeclContext(RTy); // If the object expression is dependent and isn't the current instantiation, // lookup will not find anything and we must defer until instantiation. @@ -1058,7 +1057,9 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, bool SuppressQualifierCheck, ActOnMemberAccessExtraArgs *ExtraArgs) { - if (R.wasNotFoundInCurrentInstantiation() || (SS.isValid() && !computeDeclContext(SS, false))) { + if (R.wasNotFoundInCurrentInstantiation() || + (SS.isValid() && !computeDeclContext(SS, false)) || + (R.isUnresolvableResult() && R.isClassLookup() && R.getNamingClass()->isDependentContext())) { return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS, TemplateKWLoc, FirstQualifierInScope, From 8f01497f29ffb6a88bb9925224d20158fdba133d Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 5 Mar 2024 10:03:05 -0500 Subject: [PATCH 04/27] [FOLD] TransformOverloadExprDecls filters template names --- clang/lib/Sema/SemaExprMember.cpp | 3 +-- clang/lib/Sema/TreeTransform.h | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 1e5e05b0e60c3..28939e0166bff 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -1058,8 +1058,7 @@ Sema::BuildMemberReferenceExpr(Expr *BaseExpr, QualType BaseExprType, ActOnMemberAccessExtraArgs *ExtraArgs) { if (R.wasNotFoundInCurrentInstantiation() || - (SS.isValid() && !computeDeclContext(SS, false)) || - (R.isUnresolvableResult() && R.isClassLookup() && R.getNamingClass()->isDependentContext())) { + (SS.isValid() && !computeDeclContext(SS, false))) { return ActOnDependentMemberExpr(BaseExpr, BaseExprType, IsArrow, OpLoc, SS, TemplateKWLoc, FirstQualifierInScope, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 1d30ba31e1794..e3f48a6573e3a 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -13204,6 +13204,26 @@ bool TreeTransform::TransformOverloadExprDecls(OverloadExpr *Old, // Resolve a kind, but don't do any further analysis. If it's // ambiguous, the callee needs to deal with it. R.resolveKind(); + + if (Old->hasTemplateKeyword() && !R.empty()) { + NamedDecl *FoundDecl = R.getRepresentativeDecl()->getUnderlyingDecl(); + getSema().FilterAcceptableTemplateNames(R, + /*AllowFunctionTemplates=*/true, + /*AllowDependent=*/true); + if (R.empty()) { + // If a 'template' keyword was used, a lookup that finds only non-template + // names is an error. + getSema().Diag(R.getNameLoc(), diag::err_template_kw_refers_to_non_template) + << R.getLookupName() + << Old->getQualifierLoc().getSourceRange() + << Old->hasTemplateKeyword() + << Old->getTemplateKeywordLoc(); + getSema().Diag(FoundDecl->getLocation(), diag::note_template_kw_refers_to_non_template) + << R.getLookupName(); + return true; + } + } + return false; } From 04fdae1ce5daeee065ce5bc55e37fdfe1b631407 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Tue, 5 Mar 2024 10:50:53 -0500 Subject: [PATCH 05/27] [FOLD] update tests --- clang/test/AST/HLSL/this-reference-template.hlsl | 2 +- clang/test/CodeGenCXX/mangle.cpp | 8 -------- clang/test/Index/annotate-nested-name-specifier.cpp | 4 ++-- clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp | 4 ++-- 4 files changed, 5 insertions(+), 13 deletions(-) diff --git a/clang/test/AST/HLSL/this-reference-template.hlsl b/clang/test/AST/HLSL/this-reference-template.hlsl index 60e057986ebf8..d427e73044b78 100644 --- a/clang/test/AST/HLSL/this-reference-template.hlsl +++ b/clang/test/AST/HLSL/this-reference-template.hlsl @@ -24,7 +24,7 @@ void main() { // CHECK: -CXXMethodDecl 0x{{[0-9A-Fa-f]+}} line:8:5 getFirst 'K ()' implicit-inline // CHECK-NEXT:-CompoundStmt 0x{{[0-9A-Fa-f]+}} // CHECK-NEXT:-ReturnStmt 0x{{[0-9A-Fa-f]+}} -// CHECK-NEXT:-CXXDependentScopeMemberExpr 0x{{[0-9A-Fa-f]+}} '' lvalue .First +// CHECK-NEXT:-MemberExpr 0x{{[0-9A-Fa-f]+}} 'K' lvalue .First 0x{{[0-9A-Fa-f]+}} // CHECK-NEXT:-CXXThisExpr 0x{{[0-9A-Fa-f]+}} 'Pair' lvalue this // CHECK-NEXT:-CXXMethodDecl 0x{{[0-9A-Fa-f]+}} line:12:5 getSecond 'V ()' implicit-inline // CHECK-NEXT:-CompoundStmt 0x{{[0-9A-Fa-f]+}} diff --git a/clang/test/CodeGenCXX/mangle.cpp b/clang/test/CodeGenCXX/mangle.cpp index 31467d943840e..d0800af55c87e 100644 --- a/clang/test/CodeGenCXX/mangle.cpp +++ b/clang/test/CodeGenCXX/mangle.cpp @@ -1032,10 +1032,6 @@ namespace test51 { template decltype(S1().~S1(), S1().~S1()) fun4() {}; template - decltype(S1().~S1()) fun5(){}; - template