Author: Younan Zhang
Date: 2024-05-01T11:52:14+08:00
New Revision: 410d6350eda322de213941b36adcdab13a0b557b
URL: 
https://github.com/llvm/llvm-project/commit/410d6350eda322de213941b36adcdab13a0b557b
DIFF: 
https://github.com/llvm/llvm-project/commit/410d6350eda322de213941b36adcdab13a0b557b.diff

LOG: [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 <corentinja...@gmail.com>

Added: 
    

Modified: 
    clang/lib/AST/ExprClassification.cpp
    clang/lib/Sema/TreeTransform.h
    clang/test/SemaCXX/cxx2c-pack-indexing.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ExprClassification.cpp 
b/clang/lib/AST/ExprClassification.cpp
index 2bb8f9aeedc7e2..390000e3ed3835 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 ababb5d02b5fdb..dff7e9df636b96 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 606715e6aacffd..a3e5a0931491b5 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}}
+}
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to