[clang] 2528f1c - [Clang] Correctly expand pack in binary subscript expression.

Corentin Jabot via cfe-commits cfe-commits at lists.llvm.org
Tue May 2 12:22:09 PDT 2023


Author: Corentin Jabot
Date: 2023-05-02T21:22:03+02:00
New Revision: 2528f1c84588f4a549c12dd1435cbba4a502a077

URL: https://github.com/llvm/llvm-project/commit/2528f1c84588f4a549c12dd1435cbba4a502a077
DIFF: https://github.com/llvm/llvm-project/commit/2528f1c84588f4a549c12dd1435cbba4a502a077.diff

LOG: [Clang] Correctly expand pack in binary subscript expression.

When constructing an array expression where the index expression
was a pack expansion, we would construct an ArraySubscriptExpr
instead of an CreateOverloadedArraySubscriptExpr, and pack
expansion would not occur - leading a crash during code gen
or a failure during constant evaluation

Reviewed By: erichkeane, shafik

Differential Revision: https://reviews.llvm.org/D149637

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/Sema/SemaExpr.cpp
    clang/test/SemaCXX/cxx2b-overloaded-operator.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index d90a2b53eb616..8d0a9c96a9579 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -386,6 +386,7 @@ Bug Fixes to C++ Support
 - Fix overly aggressive lifetime checks for parenthesized aggregate
   initialization.
   (`#61567 <https://github.com/llvm/llvm-project/issues/61567>`_)
+- Fix a crash when expanding a pack as the index of a subscript expression.
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 4edaf6970a2d7..8789e4c3cb25f 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4924,7 +4924,8 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base,
   // Build an unanalyzed expression if either operand is type-dependent.
   if (getLangOpts().CPlusPlus && ArgExprs.size() == 1 &&
       (base->isTypeDependent() ||
-       Expr::hasAnyTypeDependentArguments(ArgExprs))) {
+       Expr::hasAnyTypeDependentArguments(ArgExprs)) &&
+      !isa<PackExpansionExpr>(ArgExprs[0])) {
     return new (Context) ArraySubscriptExpr(
         base, ArgExprs.front(),
         getDependentArraySubscriptType(base, ArgExprs.front(), getASTContext()),
@@ -4958,7 +4959,8 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base,
   // to overload resolution and so should not take this path.
   if (getLangOpts().CPlusPlus && !base->getType()->isObjCObjectPointerType() &&
       ((base->getType()->isRecordType() ||
-        (ArgExprs.size() != 1 || ArgExprs[0]->getType()->isRecordType())))) {
+        (ArgExprs.size() != 1 || isa<PackExpansionExpr>(ArgExprs[0]) ||
+         ArgExprs[0]->getType()->isRecordType())))) {
     return CreateOverloadedArraySubscriptExpr(lbLoc, rbLoc, base, ArgExprs);
   }
 

diff  --git a/clang/test/SemaCXX/cxx2b-overloaded-operator.cpp b/clang/test/SemaCXX/cxx2b-overloaded-operator.cpp
index f9a83c813dcf0..47218e1f2dab5 100644
--- a/clang/test/SemaCXX/cxx2b-overloaded-operator.cpp
+++ b/clang/test/SemaCXX/cxx2b-overloaded-operator.cpp
@@ -73,3 +73,47 @@ struct T2 {
 static_assert(T2{}[] == 1);
 static_assert(T2{}[1] == 2);
 static_assert(T2{}[1, 1] == 3);
+
+namespace test_packs {
+
+struct foo_t {
+template<typename... Ts>
+constexpr int operator[](Ts... idx) {
+    return (0 + ... + idx);
+}
+};
+
+template<int... Is>
+constexpr int cxx_subscript() {
+  foo_t foo;
+  return foo[Is...];
+}
+
+template<int... Is>
+int cxx_subscript_unexpanded() {
+  foo_t foo;
+  return foo[Is]; // expected-error {{expression contains unexpanded parameter pack 'Is'}}
+}
+
+template<int... Is>
+constexpr int c_array() {
+  int arr[] = {1, 2, 3};
+  return arr[Is...]; // expected-error 2{{type 'int[3]' does not provide a subscript operator}}
+}
+
+template<int... Is>
+int c_array_unexpanded() {
+  int arr[] = {1, 2, 3};
+  return arr[Is]; // expected-error {{expression contains unexpanded parameter pack 'Is'}}
+}
+
+void test() {
+  static_assert(cxx_subscript<1, 2, 3>() == 6);
+  static_assert(c_array<1>() == 2);
+
+  c_array<>(); // expected-note {{in instantiation}}
+  c_array<1>();
+  c_array<1, 2>(); // expected-note {{in instantiation}}
+}
+
+}


        


More information about the cfe-commits mailing list