[clang] 37b4df4 - [Clang] Remove the wrong assumption when rebuilding SizeOfPackExprs for constraint normalization (#115120)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 7 22:05:00 PST 2024
Author: Younan Zhang
Date: 2024-11-08T14:04:57+08:00
New Revision: 37b4df434d2cf82feb3672eeeb469e54ee8f7ff2
URL: https://github.com/llvm/llvm-project/commit/37b4df434d2cf82feb3672eeeb469e54ee8f7ff2
DIFF: https://github.com/llvm/llvm-project/commit/37b4df434d2cf82feb3672eeeb469e54ee8f7ff2.diff
LOG: [Clang] Remove the wrong assumption when rebuilding SizeOfPackExprs for constraint normalization (#115120)
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.
Fixes #115098
Added:
Modified:
clang/include/clang/AST/ExprCXX.h
clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/test/SemaTemplate/concepts-out-of-line-def.cpp
Removed:
################################################################################
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 b1b92c0333c976..9e76b60fd509c7 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1749,31 +1749,21 @@ namespace {
return inherited::TransformLambdaBody(E, Body);
}
- ExprResult RebuildSizeOfPackExpr(SourceLocation OperatorLoc,
- NamedDecl *Pack, SourceLocation PackLoc,
- 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();
-
- return inherited::RebuildSizeOfPackExpr(OperatorLoc,
- cast<NamedDecl>(NewPack), PackLoc,
- RParenLoc, Length, PartialArgs);
+ 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 &&
+ TransformedExpr->getPack() == E->getPack()) {
+ Decl *NewPack =
+ TransformDecl(E->getPackLoc(), TransformedExpr->getPack());
+ if (!NewPack)
+ return ExprError();
+ TransformedExpr->setPack(cast<NamedDecl>(NewPack));
+ }
+ return TransformedExpr;
}
ExprResult TransformRequiresExpr(RequiresExpr *E) {
@@ -1899,6 +1889,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 dd518d283c83c8..7cb5cfc10b9a7b 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -703,6 +703,25 @@ 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
+
namespace GH114685 {
template <typename T> struct ptr {
More information about the cfe-commits
mailing list