https://github.com/LYP951018 created https://github.com/llvm/llvm-project/pull/69075
The dependence of a template argument is not only determined by the argument itself, but also by the type of the template parameter: > Furthermore, a non-type > [template-argument](https://eel.is/c++draft/temp.names#nt:template-argument) > is dependent if the corresponding non-type > [template-parameter](https://eel.is/c++draft/temp.param#nt:template-parameter) > is of reference or pointer type and the > [template-argument](https://eel.is/c++draft/temp.names#nt:template-argument) > designates or points to a member of the current instantiation or a member of > a dependent type[.](https://eel.is/c++draft/temp.dep#temp-3.sentence-1) For example: ```cpp struct A{}; template <const A& T> const A JoinStringViews = T; template <int V> class Builder { public: static constexpr A Equal{}; static constexpr auto Val = JoinStringViews<Equal>; }; ``` The constant expression `Equal` is not dependent, but because the type of the template parameter is a reference type and `Equal` is a member of the current instantiation, the template argument of `JoinStringViews<Equal>` is actually dependent, which makes `JoinStringViews<Equal>` dependent. When a template-id of a variable template is dependent, `CheckVarTemplateId` will return an `UnresolvedLookupExpr`, but `UnresolvedLookupExpr` calculates dependence by template arguments only (the `ConstantExpr` `Equal` here), which is not dependent. This causes type deduction to think that `JoinStringViews<Equal>` is `OverloadTy` and treat it as a function template, which is clearly wrong. This PR adds a `KnownDependent` parameter to the constructor of `UnresolvedLookupExpr`. After canonicalization, if `CanonicalConverted` contains any dependent argument, `KnownDependent` is set to `true`. This fixes the dependence calculation of `UnresolvedLookupExpr` for dependent variable templates. Fixes #65153 . From 5f3557e274cc2229133fe9d39f787ae8f6eb86c7 Mon Sep 17 00:00:00 2001 From: letrec <liuyupei951...@hotmail.com> Date: Sun, 8 Oct 2023 00:44:11 +0800 Subject: [PATCH] Fix dependence handling for variable templates --- clang/include/clang/AST/ExprCXX.h | 8 ++++++-- clang/lib/AST/ASTImporter.cpp | 5 ++++- clang/lib/AST/ExprCXX.cpp | 14 +++++++------- clang/lib/Sema/SemaDeclCXX.cpp | 5 +++-- clang/lib/Sema/SemaTemplate.cpp | 5 +++-- clang/test/SemaTemplate/dependent-expr.cpp | 15 +++++++++++++++ 6 files changed, 38 insertions(+), 14 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 17dbb5e888ebdd3..798c98cfcf2d4db 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -3191,7 +3191,8 @@ class UnresolvedLookupExpr final const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, - UnresolvedSetIterator Begin, UnresolvedSetIterator End); + UnresolvedSetIterator Begin, UnresolvedSetIterator End, + bool KnownDependent); UnresolvedLookupExpr(EmptyShell Empty, unsigned NumResults, bool HasTemplateKWAndArgsInfo); @@ -3211,12 +3212,15 @@ class UnresolvedLookupExpr final const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, UnresolvedSetIterator Begin, UnresolvedSetIterator End); + // After canonicalization, there may be dependent template arguments in + // CanonicalConverted But none of Args is dependent. When any of + // CanonicalConverted dependent, KnownDependent is true. static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, - UnresolvedSetIterator End); + UnresolvedSetIterator End, bool KnownDependent); static UnresolvedLookupExpr *CreateEmpty(const ASTContext &Context, unsigned NumResults, diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index c7c2aecc8b179a4..706bbfcadd58b75 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -8391,10 +8391,13 @@ ASTNodeImporter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { if (!ToTemplateKeywordLocOrErr) return ToTemplateKeywordLocOrErr.takeError(); + const bool KnownDependent = + (E->getDependence() & ExprDependence::TypeValue) == + ExprDependence::TypeValue; return UnresolvedLookupExpr::Create( Importer.getToContext(), *ToNamingClassOrErr, *ToQualifierLocOrErr, *ToTemplateKeywordLocOrErr, ToNameInfo, E->requiresADL(), &ToTAInfo, - ToDecls.begin(), ToDecls.end()); + ToDecls.begin(), ToDecls.end(), KnownDependent); } return UnresolvedLookupExpr::Create( diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index efb64842fb6d96d..c300ab641257f25 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -354,9 +354,9 @@ UnresolvedLookupExpr::UnresolvedLookupExpr( NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, bool Overloaded, const TemplateArgumentListInfo *TemplateArgs, UnresolvedSetIterator Begin, - UnresolvedSetIterator End) + UnresolvedSetIterator End, bool KnownDependent) : OverloadExpr(UnresolvedLookupExprClass, Context, QualifierLoc, - TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, false, + TemplateKWLoc, NameInfo, TemplateArgs, Begin, End, KnownDependent, false, false), NamingClass(NamingClass) { UnresolvedLookupExprBits.RequiresADL = RequiresADL; @@ -380,7 +380,7 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr)); return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc, SourceLocation(), NameInfo, RequiresADL, - Overloaded, nullptr, Begin, End); + Overloaded, nullptr, Begin, End, false); } UnresolvedLookupExpr *UnresolvedLookupExpr::Create( @@ -388,7 +388,7 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, const TemplateArgumentListInfo *Args, UnresolvedSetIterator Begin, - UnresolvedSetIterator End) { + UnresolvedSetIterator End, bool KnownDependent) { assert(Args || TemplateKWLoc.isValid()); unsigned NumResults = End - Begin; unsigned NumTemplateArgs = Args ? Args->size() : 0; @@ -396,9 +396,9 @@ UnresolvedLookupExpr *UnresolvedLookupExpr::Create( totalSizeToAlloc<DeclAccessPair, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc>(NumResults, 1, NumTemplateArgs); void *Mem = Context.Allocate(Size, alignof(UnresolvedLookupExpr)); - return new (Mem) UnresolvedLookupExpr(Context, NamingClass, QualifierLoc, - TemplateKWLoc, NameInfo, RequiresADL, - /*Overloaded*/ true, Args, Begin, End); + return new (Mem) UnresolvedLookupExpr( + Context, NamingClass, QualifierLoc, TemplateKWLoc, NameInfo, RequiresADL, + /*Overloaded*/ true, Args, Begin, End, KnownDependent); } UnresolvedLookupExpr *UnresolvedLookupExpr::CreateEmpty( diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 2b2b7391f88fd54..4080f1de29bf8de 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -1297,8 +1297,9 @@ static bool checkTupleLikeDecomposition(Sema &S, // in the associated namespaces. Expr *Get = UnresolvedLookupExpr::Create( S.Context, nullptr, NestedNameSpecifierLoc(), SourceLocation(), - DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/true, &Args, - UnresolvedSetIterator(), UnresolvedSetIterator()); + DeclarationNameInfo(GetDN, Loc), /*RequiresADL*/ true, &Args, + UnresolvedSetIterator(), UnresolvedSetIterator(), + /*KnownDependent*/ false); Expr *Arg = E.get(); E = S.BuildCallExpr(nullptr, Get, Loc, Arg, Loc); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 994d89e25b3848e..afa654e5c77c251 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4981,7 +4981,7 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, return ExprError(); } } - + bool KnownDependent = false; // In C++1y, check variable template ids. if (R.getAsSingle<VarTemplateDecl>()) { ExprResult Res = CheckVarTemplateId(SS, R.getLookupNameInfo(), @@ -4990,6 +4990,7 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, if (Res.isInvalid() || Res.isUsable()) return Res; // Result is dependent. Carry on to build an UnresolvedLookupEpxr. + KnownDependent = true; } if (R.getAsSingle<ConceptDecl>()) { @@ -5007,7 +5008,7 @@ ExprResult Sema::BuildTemplateIdExpr(const CXXScopeSpec &SS, TemplateKWLoc, R.getLookupNameInfo(), RequiresADL, TemplateArgs, - R.begin(), R.end()); + R.begin(), R.end(), KnownDependent); return ULE; } diff --git a/clang/test/SemaTemplate/dependent-expr.cpp b/clang/test/SemaTemplate/dependent-expr.cpp index 51bd375d7920eed..26a7984ccb2c268 100644 --- a/clang/test/SemaTemplate/dependent-expr.cpp +++ b/clang/test/SemaTemplate/dependent-expr.cpp @@ -165,3 +165,18 @@ namespace BindingInStmtExpr { using U = decltype(num_bindings<T>()); // expected-note {{previous}} using U = N<3>; // expected-error-re {{type alias redefinition with different types ('N<3>' vs {{.*}}N<2>}} } + +namespace PR65153 { +struct A{}; + +template <const A& T> +const A JoinStringViews = T; + +template <int V> +class Builder { +public: + static constexpr A Equal{}; + // no crash here + static constexpr auto Val = JoinStringViews<Equal>; +}; +} // namespace PR65153 \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits