https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/102131
Fixes https://github.com/llvm/llvm-project/issues/101735 (I'll add a release note and some comments later) >From 0727e47124af564826a22a718a64a1da79e6131d Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Tue, 6 Aug 2024 20:08:43 +0800 Subject: [PATCH] [Clang][Concepts] Fix the constraint equivalence checking for TemplateTypeParmTypes --- clang/include/clang/Sema/Template.h | 2 ++ clang/lib/Sema/SemaConcept.cpp | 28 +++++++++++++++---- .../SemaTemplate/concepts-out-of-line-def.cpp | 23 +++++++++++++++ 3 files changed, 48 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Sema/Template.h b/clang/include/clang/Sema/Template.h index d616865afe807..7b3646f0fcc35 100644 --- a/clang/include/clang/Sema/Template.h +++ b/clang/include/clang/Sema/Template.h @@ -245,6 +245,8 @@ enum class TemplateSubstitutionKind : char { AssociatedDecl) && "Trying to change incorrect declaration?"); TemplateArgumentLists[0].Args = Args; + TemplateArgumentLists[0].AssociatedDeclAndFinal.setPointer( + AssociatedDecl); } else { --NumRetainedOuterLevels; TemplateArgumentLists.push_back({{AssociatedDecl, Final}, Args}); diff --git a/clang/lib/Sema/SemaConcept.cpp b/clang/lib/Sema/SemaConcept.cpp index d4c9d044985e3..855b145db9586 100644 --- a/clang/lib/Sema/SemaConcept.cpp +++ b/clang/lib/Sema/SemaConcept.cpp @@ -946,7 +946,8 @@ namespace { static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, - const Expr *ConstrExpr) { + const Expr *ConstrExpr, + const Decl *PreferredInnermostAssociatedDecl = nullptr) { MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, /*Innermost=*/std::nullopt, @@ -957,6 +958,13 @@ static const Expr *SubstituteConstraintExpressionWithoutSatisfaction( if (MLTAL.getNumSubstitutedLevels() == 0) return ConstrExpr; + if (PreferredInnermostAssociatedDecl) + if (MLTAL.getAssociatedDecl(MLTAL.getNumLevels() - 1).first != + PreferredInnermostAssociatedDecl) + MLTAL.replaceInnermostTemplateArguments( + const_cast<Decl *>(PreferredInnermostAssociatedDecl), + MLTAL.getInnermost()); + Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false); Sema::InstantiatingTemplate Inst( @@ -1006,15 +1014,25 @@ bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old, // C++ [temp.constr.decl]p4 if (Old && !New.isInvalid() && !New.ContainsDecl(Old) && Old->getLexicalDeclContext() != New.getLexicalDeclContext()) { + const Decl *PreferredInnermostAssociatedDecl = nullptr; + if (const NamedDecl *ND = New.getDecl(); + ND && Old->getDeclContext() == New.getDeclContext() && + Old->getDeclName() == ND->getDeclName() && + Old->getCanonicalDecl() != ND->getCanonicalDecl()) + PreferredInnermostAssociatedDecl = Old; if (const Expr *SubstConstr = - SubstituteConstraintExpressionWithoutSatisfaction(*this, Old, - OldConstr)) + SubstituteConstraintExpressionWithoutSatisfaction( + *this, Old, OldConstr, + /*PreferredInnermostAssociatedDecl=*/ + PreferredInnermostAssociatedDecl)) OldConstr = SubstConstr; else return false; if (const Expr *SubstConstr = - SubstituteConstraintExpressionWithoutSatisfaction(*this, New, - NewConstr)) + SubstituteConstraintExpressionWithoutSatisfaction( + *this, New, NewConstr, + /*PreferredInnermostAssociatedDecl=*/ + PreferredInnermostAssociatedDecl)) NewConstr = SubstConstr; else return false; diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp index 0142efcdc3ee8..333187b0d74ad 100644 --- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp +++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp @@ -599,3 +599,26 @@ template <class DerT> unsigned long DerivedCollection<DerTs...>::index() {} } // namespace GH72557 + +namespace GH101735 { + +template <class, class> +concept True = true; + +template <typename T> +class A { + template <typename... Ts> + void method(Ts&... ts) + requires requires (T t) { + { t.method(static_cast<Ts &&>(ts)...) } -> True<void>; + }; +}; + +template <typename T> +template <typename... Ts> +void A<T>::method(Ts&... ts) + requires requires (T t) { + { t.method(static_cast<Ts &&>(ts)...) } -> True<void>; + } {} + +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits