https://github.com/nga888 created https://github.com/llvm/llvm-project/pull/102514
…ializations instantiation dependent (#100392) Cherry pick of 55ea36002bd364518c20b3ce282640c920697bf7 >From c7377a35fc99b537a5198335c5aabc5d142a3972 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski <sdkryst...@gmail.com> Date: Tue, 6 Aug 2024 12:40:44 -0400 Subject: [PATCH] [Clang][Sema] Make UnresolvedLookupExprs in class scope explicit specializations instantiation dependent (#100392) A class member named by an expression in a member function that may instantiate to a static _or_ non-static member is represented by a `UnresolvedLookupExpr` in order to defer the implicit transformation to a class member access expression until instantiation. Since `ASTContext::getDecltypeType` only creates a `DecltypeType` that has a `DependentDecltypeType` as its canonical type when the operand is instantiation dependent, and since we do not transform types unless they are instantiation dependent, we need to mark the `UnresolvedLookupExpr` as instantiation dependent in order to correctly build a `DecltypeType` using the expression as its operand with a `DependentDecltypeType` canonical type. Fixes #99873. (cherry picked from commit 55ea36002bd364518c20b3ce282640c920697bf7) --- clang/include/clang/AST/ExprCXX.h | 7 ++++--- clang/lib/AST/ASTImporter.cpp | 6 ++++-- clang/lib/AST/ExprCXX.cpp | 19 +++++++++++-------- clang/lib/Sema/SemaCoroutine.cpp | 3 ++- clang/lib/Sema/SemaDecl.cpp | 2 +- clang/lib/Sema/SemaDeclCXX.cpp | 2 +- clang/lib/Sema/SemaExpr.cpp | 2 +- clang/lib/Sema/SemaExprMember.cpp | 3 ++- clang/lib/Sema/SemaOpenMP.cpp | 6 ++++-- clang/lib/Sema/SemaOverload.cpp | 6 +++--- clang/lib/Sema/SemaTemplate.cpp | 3 ++- clang/lib/Sema/TreeTransform.h | 8 ++++---- clang/test/SemaCXX/decltype.cpp | 25 +++++++++++++++++++++++++ 13 files changed, 64 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index c2feac525c1ea6..45cfd7bfb7f92c 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -3229,7 +3229,7 @@ class UnresolvedLookupExpr final const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent); + bool KnownDependent, bool KnownInstantiationDependent); UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults, bool HasTemplateKWAndArgsInfo); @@ -3248,7 +3248,7 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent); + bool KnownDependent, bool KnownInstantiationDependent); // After canonicalization, there may be dependent template arguments in // CanonicalConverted But none of Args is dependent. When any of @@ -3258,7 +3258,8 @@ class UnresolvedLookupExpr final NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, - UnresolvedSetIterator End, bool KnownDependent); + UnresolvedSetIterator End, bool KnownDependent, + bool KnownInstantiationDependent); static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context, unsigned NumResults, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 08ef09d353afc9..e95992b99f7e9d 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8578,13 +8578,15 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, - ToDecls.begin(), ToDecls.end(), KnownDependent); + ToDecls.begin(), ToDecls.end(), KnownDependent, + /*KnownInstantiationDependent=*/E->isInstantiationDependent()); } return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, ToNameInfo, E->requiresADL(), ToDecls.begin(), ToDecls.end(), - /*KnownDependent=*/E->isTypeDependent()); + /*KnownDependent=*/E->isTypeDependent(), + /*KnownInstantiationDependent=*/E->isInstantiationDependent()); } ExpectedStmt diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 8d2a1b5611ccc6..45e2badf2ddd4a 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -402,10 +402,11 @@ UnresolvedLookupExpr::UnresolvedLookupExpr( NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, - UnresolvedSetIterator End, bool KnownDependent) + UnresolvedSetIterator End, bool KnownDependent, + bool KnownInstantiationDependent) : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc, TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, - KnownDependent, false, false), + KnownDependent, KnownInstantiationDependent, false), NamingClass(NamingClass) { UnresolvedLookupExprBits.RequiresADL = RequiresADL; } @@ -420,7 +421,7 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, - bool KnownDependent) { + bool KnownDependent, bool KnownInstantiationDependent) { unsigned NumResults = End - Begin; unsigned Size = totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(NumResults, 0, 0); @@ -428,7 +429,8 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( return new (Mem) UnresolvedLookupExpr( Context, NamingClass, QualifierLoc, /*TemplateKWLoc=*/SourceLocation(), NameInfo, RequiresADL, - /*TemplateArgs=*/nullptr, Begin, End, KnownDependent); + /*TemplateArgs=*/nullptr, Begin, End, KnownDependent, + KnownInstantiationDependent); } UnresolvedLookupExpr *UnresolvedLookupExpr::Create( @@ -436,7 +438,8 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, - UnresolvedSetIterator End, bool KnownDependent) { + UnresolvedSetIterator End, bool KnownDependent, + bool KnownInstantiationDependent) { unsigned NumResults = End - Begin; bool HasTemplateKWAndArgsInfo = Args || TemplateKWLoc.isValid(); unsigned NumTemplateArgs = Args ? Args->size() : 0; @@ -444,9 +447,9 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( TemplateArgumentLoc>( NumResults, HasTemplateKWAndArgsInfo, NumTemplateArgs); void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr)); - return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc, - TemplateKWLoc, NameInfo, RequiresADL, - Args, Begin, End, KnownDependent); + return new (Mem) UnresolvedLookupExpr( + Context, NamingClass, QualifierLoc, TemplateKWLoc, NameInfo, RequiresADL, + Args, Begin, End, KnownDependent, KnownInstantiationDependent); } UnresolvedLookupExpr *UnresolvedLookupExpr::CreateEmpty( diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 81334c817b2af2..4e180d648cd826 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -820,7 +820,8 @@ ExprResult Sema::BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc) { Expr *CoawaitOp = UnresolvedLookupExpr::Create( Context, /*NamingClass*/ nullptr, NestedNameSpecifierLoc(), DeclarationNameInfo(OpName, Loc), /*RequiresADL*/ true, Functions.begin(), - Functions.end(), /*KnownDependent=*/false); + Functions.end(), /*KnownDependent=*/false, + /*KnownInstantiationDependent=*/false); assert(CoawaitOp); return CoawaitOp; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 01231f8e385ef1..fa4bfe13053d8e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1219,7 +1219,7 @@ Sema::NameClassification Sema::ClassifyName(Scope *S, CXXScopeSpec &SS, return NameClassification::OverloadSet(UnresolvedLookupExpr::Create( Context, Result.getNamingClass(), SS.getWithLocInContext(Context), Result.getLookupNameInfo(), ADL, Result.begin(), Result.end(), - /*KnownDependent=*/false)); + /*KnownDependent=*/false, /*KnownInstantiationDependent=*/false)); } ExprResult diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 04b8d88cae217b..66ca62f5d7c4cd 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1289,7 +1289,7 @@ static bool checkTupleLikeDecomposition(Sema &S, S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(), DeclarationNameInfo(GetDN, Loc), /*RequiresADL=*/true, &Args, UnresolvedSetIterator(), UnresolvedSetIterator(), - /*KnownDependent=*/false); + /*KnownDependent=*/false, /*KnownInstantiationDependent=*/false); Expr *Arg = E.get(); E = S.BuildCallExpr(nullptr, Get, Loc, Arg, Loc); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 74c0e017059055..edb8b79a2220ba 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -3188,7 +3188,7 @@ ExprResult Sema::BuildDeclarationNameExpr(const CXXScopeSpec &SS, UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create( Context, R.getNamingClass(), SS.getWithLocInContext(Context), R.getLookupNameInfo(), NeedsADL, R.begin(), R.end(), - /*KnownDependent=*/false); + /*KnownDependent=*/false, /*KnownInstantiationDependent=*/false); return ULE; } diff --git a/clang/lib/Sema/SemaExprMember.cpp b/clang/lib/Sema/SemaExprMember.cpp index 2070f3b7bb3a2f..f1ba26f38520a9 100644 --- a/clang/lib/Sema/SemaExprMember.cpp +++ b/clang/lib/Sema/SemaExprMember.cpp @@ -331,7 +331,8 @@ ExprResult Sema::BuildPossibleImplicitMemberExpr( return UnresolvedLookupExpr::Create( Context, R.getNamingClass(), SS.getWithLocInContext(Context), TemplateKWLoc, R.getLookupNameInfo(), /*RequiresADL=*/false, - TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true); + TemplateArgs, R.begin(), R.end(), /*KnownDependent=*/true, + /*KnownInstantiationDependent=*/true); case IMA_Error_StaticOrExplicitContext: case IMA_Error_Unrelated: diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 67e3c1d9067f37..6cbc075302eb55 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -17968,7 +17968,8 @@ buildDeclareReductionRef(Sema &SemaRef, SourceLocation Loc, SourceRange Range, return UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), ReductionId, - /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false); + /*ADL=*/true, ResSet.begin(), ResSet.end(), /*KnownDependent=*/false, + /*KnownInstantiationDependent=*/false); } // Lookup inside the classes. // C++ [over.match.oper]p3: @@ -20834,7 +20835,8 @@ static ExprResult buildUserDefinedMapperRef(Sema &SemaRef, Scope *S, return UnresolvedLookupExpr::Create( SemaRef.Context, /*NamingClass=*/nullptr, MapperIdScopeSpec.getWithLocInContext(SemaRef.Context), MapperId, - /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false); + /*ADL=*/false, URS.begin(), URS.end(), /*KnownDependent=*/false, + /*KnownInstantiationDependent=*/false); } SourceLocation Loc = MapperId.getLoc(); // [OpenMP 5.0], 2.19.7.3 declare mapper Directive, Restrictions diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 554a2df14bea65..28fd3b06156b9b 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -14083,9 +14083,9 @@ ExprResult Sema::CreateUnresolvedLookupExpr(CXXRecordDecl *NamingClass, DeclarationNameInfo DNI, const UnresolvedSetImpl &Fns, bool PerformADL) { - return UnresolvedLookupExpr::Create(Context, NamingClass, NNSLoc, DNI, - PerformADL, Fns.begin(), Fns.end(), - /*KnownDependent=*/false); + return UnresolvedLookupExpr::Create( + Context, NamingClass, NNSLoc, DNI, PerformADL, Fns.begin(), Fns.end(), + /*KnownDependent=*/false, /*KnownInstantiationDependent=*/false); } ExprResult Sema::BuildCXXMemberCallExpr(Expr *E, NamedDecl *FoundDecl, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 87b1f98bbe5ac9..ca71542d886fa1 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4436,7 +4436,8 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, UnresolvedLookupExpr *ULE = UnresolvedLookupExpr::Create( Context, R.getNamingClass(), SS.getWithLocInContext(Context), TemplateKWLoc, R.getLookupNameInfo(), RequiresADL, TemplateArgs, - R.begin(), R.end(), KnownDependent); + R.begin(), R.end(), KnownDependent, + /*KnownInstantiationDependent=*/false); // Model the templates with UnresolvedTemplateTy. The expression should then // either be transformed in an instantiation or be diagnosed in diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 84e846356e4378..51e6a4845bf6fd 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -10541,7 +10541,7 @@ TreeTransform<Derived>::TransformOMPReductionClause(OMPReductionClause *C) { SemaRef.Context, /*NamingClass=*/nullptr, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo, /*ADL=*/true, Decls.begin(), Decls.end(), - /*KnownDependent=*/false)); + /*KnownDependent=*/false, /*KnownInstantiationDependent=*/false)); } else UnresolvedReductions.push_back(nullptr); } @@ -10588,7 +10588,7 @@ OMPClause *TreeTransform<Derived>::TransformOMPTaskReductionClause( SemaRef.Context, /*NamingClass=*/nullptr, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo, /*ADL=*/true, Decls.begin(), Decls.end(), - /*KnownDependent=*/false)); + /*KnownDependent=*/false, /*KnownInstantiationDependent=*/false)); } else UnresolvedReductions.push_back(nullptr); } @@ -10634,7 +10634,7 @@ TreeTransform<Derived>::TransformOMPInReductionClause(OMPInReductionClause *C) { SemaRef.Context, /*NamingClass=*/nullptr, ReductionIdScopeSpec.getWithLocInContext(SemaRef.Context), NameInfo, /*ADL=*/true, Decls.begin(), Decls.end(), - /*KnownDependent=*/false)); + /*KnownDependent=*/false, /*KnownInstantiationDependent=*/false)); } else UnresolvedReductions.push_back(nullptr); } @@ -10816,7 +10816,7 @@ bool transformOMPMappableExprListClause( TT.getSema().Context, /*NamingClass=*/nullptr, MapperIdScopeSpec.getWithLocInContext(TT.getSema().Context), MapperIdInfo, /*ADL=*/true, Decls.begin(), Decls.end(), - /*KnownDependent=*/false)); + /*KnownDependent=*/false, /*KnownInstantiationDependent=*/false)); } else { UnresolvedMappers.push_back(nullptr); } diff --git a/clang/test/SemaCXX/decltype.cpp b/clang/test/SemaCXX/decltype.cpp index 96abb60836e400..a37b89939565d3 100644 --- a/clang/test/SemaCXX/decltype.cpp +++ b/clang/test/SemaCXX/decltype.cpp @@ -139,6 +139,31 @@ namespace GH58674 { } } +namespace GH99873 { +struct B { + int x; +}; + +template<typename T> +struct A { + template<typename U> + constexpr int f() const { + return 1; + } + + template<> + constexpr int f<int>() const { + return decltype(B::x)(); + } +}; + +// This shouldn't crash. +static_assert(A<int>().f<int>() == 0, ""); +// The result should not be dependent. +static_assert(A<int>().f<int>() != 0, ""); // expected-error {{static assertion failed due to requirement 'GH99873::A<int>().f<int>() != 0'}} + // expected-note@-1 {{expression evaluates to '0 != 0'}} +} + template<typename> class conditional { }; _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits