https://github.com/zyn0217 updated https://github.com/llvm/llvm-project/pull/115120
>From 0017e08259472b4397c8be5578da33448e3d82cd Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Wed, 6 Nov 2024 13:51:01 +0800 Subject: [PATCH 1/2] [Clang] Remove the wrong assumption when rebuilding SizeOfPackExprs for constraint normalization In 463a4f150, we assumed that all the template argument packs are of size 1 when normalizing a constraint expression because I mistakenly thought those packs were obtained from their injected template parameters. This was wrong because we might be checking constraints when instantiating a friend declaration within a class template specialization, where the parent class template is specialized with non-dependent template arguments. In that sense, we shouldn't assume any pack size nor expand anything in such a scenario. Moreover, there are no intermediate (substituted but unexpanded) AST nodes for template template parameters, so we have to special-case their transformations by looking into the instantiation scope instead of extracting anything from template arguments. --- clang/lib/Sema/SemaTemplateInstantiate.cpp | 33 +++++++++---------- .../SemaTemplate/concepts-out-of-line-def.cpp | 19 +++++++++++ 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index de0ec0128905ff..081873030a1a59 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1736,23 +1736,13 @@ namespace { SourceLocation RParenLoc, std::optional<unsigned> Length, ArrayRef<TemplateArgument> PartialArgs) { - if (SemaRef.CodeSynthesisContexts.back().Kind != - Sema::CodeSynthesisContext::ConstraintNormalization) - return inherited::RebuildSizeOfPackExpr(OperatorLoc, Pack, PackLoc, - RParenLoc, Length, PartialArgs); - -#ifndef NDEBUG - for (auto *Iter = TemplateArgs.begin(); Iter != TemplateArgs.end(); - ++Iter) - for (const TemplateArgument &TA : Iter->Args) - assert(TA.getKind() != TemplateArgument::Pack || TA.pack_size() == 1); -#endif - Sema::ArgumentPackSubstitutionIndexRAII SubstIndex( - SemaRef, /*NewSubstitutionIndex=*/0); - Decl *NewPack = TransformDecl(PackLoc, Pack); - if (!NewPack) - return ExprError(); - + Decl *NewPack = Pack; + if (SemaRef.CodeSynthesisContexts.back().Kind == + Sema::CodeSynthesisContext::ConstraintNormalization) { + NewPack = TransformDecl(PackLoc, Pack); + if (!NewPack) + return ExprError(); + } return inherited::RebuildSizeOfPackExpr(OperatorLoc, cast<NamedDecl>(NewPack), PackLoc, RParenLoc, Length, PartialArgs); @@ -1881,6 +1871,15 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation Loc, Decl *D) { TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition()); if (TTP->isParameterPack()) { + // We might not have an index for pack expansion when normalizing + // constraint expressions. In that case, resort to instantiation scopes + // for the transformed declarations. + if (SemaRef.ArgumentPackSubstitutionIndex == -1 && + SemaRef.CodeSynthesisContexts.back().Kind == + Sema::CodeSynthesisContext::ConstraintNormalization) { + return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), + TemplateArgs); + } assert(Arg.getKind() == TemplateArgument::Pack && "Missing argument pack"); Arg = getPackSubstitutedTemplateArgument(getSema(), Arg); diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp index fe8f74928fc370..d75df89f2a4234 100644 --- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp +++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp @@ -702,3 +702,22 @@ class TTP; C v; } // namespace GH93099 + +namespace GH115098 { + +template <typename... Ts> struct c { + template <typename T> + requires(sizeof...(Ts) > 0) + friend bool operator==(c, c); +}; + +template <typename... Ts> struct d { + template <typename T> + requires(sizeof...(Ts) > 0) + friend bool operator==(d, d); +}; + +template struct c<int>; +template struct d<int, int>; + +} // namespace GH115098 >From c34b91878ae03468777f19535b0e9382619dc8f6 Mon Sep 17 00:00:00 2001 From: Younan Zhang <zyn7...@gmail.com> Date: Thu, 7 Nov 2024 16:46:25 +0800 Subject: [PATCH 2/2] Avoid layering violation --- clang/include/clang/AST/ExprCXX.h | 2 ++ clang/lib/Sema/SemaTemplateInstantiate.cpp | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 57ab94bcb2010f..696a574833dad2 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -4326,6 +4326,8 @@ class SizeOfPackExpr final /// Retrieve the parameter pack. NamedDecl *getPack() const { return Pack; } + void setPack(NamedDecl *NewPack) { Pack = NewPack; } + /// Retrieve the length of the parameter pack. /// /// This routine may only be invoked when the expression is not diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index 081873030a1a59..9c98cf11e43dd0 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -1731,21 +1731,21 @@ namespace { return inherited::TransformLambdaBody(E, Body); } - ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc, - NamedDecl *Pack, SourceLocation PackLoc, - SourceLocation RParenLoc, - std::optional<unsigned> Length, - ArrayRef<TemplateArgument> PartialArgs) { - Decl *NewPack = Pack; + ExprResult TransformSizeOfPackExpr(SizeOfPackExpr *E) { + ExprResult Transformed = inherited::TransformSizeOfPackExpr(E); + if (!Transformed.isUsable()) + return Transformed; + auto *TransformedExpr = cast<SizeOfPackExpr>(Transformed.get()); if (SemaRef.CodeSynthesisContexts.back().Kind == - Sema::CodeSynthesisContext::ConstraintNormalization) { - NewPack = TransformDecl(PackLoc, Pack); + Sema::CodeSynthesisContext::ConstraintNormalization && + TransformedExpr->getPack() == E->getPack()) { + Decl *NewPack = + TransformDecl(E->getPackLoc(), TransformedExpr->getPack()); if (!NewPack) return ExprError(); + TransformedExpr->setPack(cast<NamedDecl>(NewPack)); } - return inherited::RebuildSizeOfPackExpr(OperatorLoc, - cast<NamedDecl>(NewPack), PackLoc, - RParenLoc, Length, PartialArgs); + return TransformedExpr; } ExprResult TransformRequiresExpr(RequiresExpr *E) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits