aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYounan Zhang <zyn7109@gmail.com>2024-05-01 11:52:14 +0800
committerGitHub <noreply@github.com>2024-05-01 11:52:14 +0800
commit410d6350eda322de213941b36adcdab13a0b557b (patch)
treedac571fb3f78d843a2dc374e59ab0bb43a4c45f3
parent306ae14face205e1bf2557ca2443c781b1d862f5 (diff)
downloadllvm-410d6350eda322de213941b36adcdab13a0b557b.zip
llvm-410d6350eda322de213941b36adcdab13a0b557b.tar.gz
llvm-410d6350eda322de213941b36adcdab13a0b557b.tar.bz2
[Sema] Avoid an undesired pack expansion while transforming PackIndexingType (#90195)
A pack indexing type can appear in a larger pack expansion, e.g `Pack...[pack_of_indexes]...` so we need to temporarily disable substitution of pack elements. Besides, this patch also fixes an assertion failure in `PackIndexingExpr::classify`: dependent `PackIndexingExpr`s are always LValues and thus we don't need to consider their `IndexExpr`s. Fixes https://github.com/llvm/llvm-project/issues/88925 --------- Co-authored-by: cor3ntin <corentinjabot@gmail.com>
-rw-r--r--clang/lib/AST/ExprClassification.cpp7
-rw-r--r--clang/lib/Sema/TreeTransform.h4
-rw-r--r--clang/test/SemaCXX/cxx2c-pack-indexing.cpp34
3 files changed, 44 insertions, 1 deletions
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index 2bb8f9a..390000e3 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -216,8 +216,13 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
return ClassifyInternal(Ctx,
cast<SubstNonTypeTemplateParmExpr>(E)->getReplacement());
- case Expr::PackIndexingExprClass:
+ case Expr::PackIndexingExprClass: {
+ // A pack-index-expression always expands to an id-expression.
+ // Consider it as an LValue expression.
+ if (cast<PackIndexingExpr>(E)->isInstantiationDependent())
+ return Cl::CL_LValue;
return ClassifyInternal(Ctx, cast<PackIndexingExpr>(E)->getSelectedExpr());
+ }
// C, C++98 [expr.sub]p1: The result is an lvalue of type "T".
// C++11 (DR1213): in the case of an array operand, the result is an lvalue
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index ababb5d..dff7e9d 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -6657,6 +6657,10 @@ TreeTransform<Derived>::TransformPackIndexingType(TypeLocBuilder &TLB,
}
}
+ // A pack indexing type can appear in a larger pack expansion,
+ // e.g. `Pack...[pack_of_indexes]...`
+ // so we need to temporarily disable substitution of pack elements
+ Sema::ArgumentPackSubstitutionIndexRAII SubstIndex(getSema(), -1);
QualType Result = getDerived().TransformType(TLB, TL.getPatternLoc());
QualType Out = getDerived().RebuildPackIndexingType(
diff --git a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp
index 606715e..a3e5a09 100644
--- a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp
+++ b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp
@@ -160,3 +160,37 @@ namespace GH88929 {
using E = P...[0]; // expected-error {{unknown type name 'P'}} \
// expected-error {{expected ';' after alias declaration}}
}
+
+namespace GH88925 {
+template <typename...> struct S {};
+
+template <auto...> struct W {};
+
+template <int...> struct sequence {};
+
+template <typename... args, int... indices> auto f(sequence<indices...>) {
+ return S<args...[indices]...>(); // #use
+}
+
+template <auto... args, int... indices> auto g(sequence<indices...>) {
+ return W<args...[indices]...>(); // #nttp-use
+}
+
+void h() {
+ static_assert(__is_same(decltype(f<int>(sequence<0, 0>())), S<int, int>));
+ static_assert(__is_same(decltype(f<int, long>(sequence<0, 0>())), S<int, int>));
+ static_assert(__is_same(decltype(f<int, long>(sequence<0, 1>())), S<int, long>));
+ f<int, long>(sequence<3>());
+ // expected-error@#use {{invalid index 3 for pack 'args' of size 2}}}
+ // expected-note-re@-2 {{function template specialization '{{.*}}' requested here}}
+
+ struct foo {};
+ struct bar {};
+ struct baz {};
+
+ static_assert(__is_same(decltype(g<foo{}, bar{}, baz{}>(sequence<0, 2, 1>())), W<foo{}, baz{}, bar{}>));
+ g<foo{}>(sequence<4>());
+ // expected-error@#nttp-use {{invalid index 4 for pack args of size 1}}
+ // expected-note-re@-2 {{function template specialization '{{.*}}' requested here}}
+}
+}