Author: Sirraide
Date: 2026-03-25T15:44:48Z
New Revision: 9c3105b1dd01750b86b1a038f720993eb6291290

URL: 
https://github.com/llvm/llvm-project/commit/9c3105b1dd01750b86b1a038f720993eb6291290
DIFF: 
https://github.com/llvm/llvm-project/commit/9c3105b1dd01750b86b1a038f720993eb6291290.diff

LOG: [Clang] [Sema] Improve handling of multidimensional subscript operator for 
builtin types (#187828)

This patch improves the diagnostic we issue when a multidimensional
subscript operator is applied to a builtin type. Additionally, this also
updates several code paths that were asserting that a subscript operator
always has 1 argument to handle multiple arguments properly.

Fixes #187800.

Added: 
    clang/test/SemaCXX/cxx23-builtin-subscript.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaExpr.cpp
    clang/test/OpenMP/target_update_messages.cpp
    clang/test/SemaCXX/cxx2b-overloaded-operator.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 03fffc4f7335f..59d66ecd678ed 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -356,6 +356,7 @@ Bug Fixes in This Version
 - Fixed a crash when normalizing constraints involving concept template 
parameters whose index coincided with non-concept template parameters in the 
same parameter mapping.
 - Fixed a crash caused by accessing dependent diagnostics of a non-dependent 
context.
 - Fixed a crash when substituting into a non-type template parameter that has 
a type containing an undeduced placeholder type.
+- Fixed several crashes and improved diagnostics when a multidimensional 
subscript operator is applied to a built-in type. (#GH187800)
 - Correctly diagnosing and no longer crashing when ``export module foo``
   (without a semicolon) are the final tokens in a module file. (#GH187771)
 - Fixed a crash in duplicate attribute checking caused by comparing constant 
arguments with 
diff erent integer signedness. (#GH188259)

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 63f24121f4178..32949666daafa 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -5432,6 +5432,10 @@ def err_ovl_no_viable_subscript :
     Error<"no viable overloaded operator[] for type %0">;
 def err_ovl_no_oper :
     Error<"type %0 does not provide a %select{subscript|call}1 operator">;
+def err_ovl_builtin_subscript_expects_single_arg : Error<
+  "built-in subscript operator for type %0 expects exactly one argument">;
+def err_ms_property_subscript_expects_single_arg : Error<
+  "property subscript expects exactly one argument">;
 def err_ovl_unresolvable : Error<
   "reference to %select{overloaded|multiversioned}1 function could not be "
   "resolved; did you mean to call it%select{| with no arguments}0?">;

diff  --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index fa1cd1ebb52de..cbbb4f791ee80 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -5040,8 +5040,11 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr 
*base,
   //
   // Helper to check for comma expressions, which are not allowed as indices 
for
   // matrix subscript expressions.
-  auto CheckAndReportCommaError = [this, base, rbLoc](Expr *E) {
-    if (isa<BinaryOperator>(E) && cast<BinaryOperator>(E)->isCommaOp()) {
+  //
+  // In C++23, we get multiple arguments instead of a comma expression.
+  auto CheckAndReportCommaError = [&](Expr *E) {
+    if (ArgExprs.size() > 1 ||
+        (isa<BinaryOperator>(E) && cast<BinaryOperator>(E)->isCommaOp())) {
       Diag(E->getExprLoc(), diag::err_matrix_subscript_comma)
           << SourceRange(base->getBeginLoc(), rbLoc);
       return true;
@@ -5061,7 +5064,6 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr 
*base,
   // MatrixSubscriptExpr.
   auto *matSubscriptE = dyn_cast<MatrixSubscriptExpr>(base);
   if (matSubscriptE) {
-    assert(ArgExprs.size() == 1);
     if (CheckAndReportCommaError(ArgExprs.front()))
       return ExprError();
 
@@ -5098,7 +5100,6 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr 
*base,
 
   // If the base is a matrix type, try to create a new MatrixSubscriptExpr.
   if (base->getType()->isMatrixType()) {
-    assert(ArgExprs.size() == 1);
     if (CheckAndReportCommaError(ArgExprs.front()))
       return ExprError();
 
@@ -5147,7 +5148,12 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr 
*base,
   // indices. In this case, i=p->x[a][b] will be turned into i=p->GetX(a, b),
   // and p->x[a][b] = i will be turned into p->PutX(a, b, i);
   if (IsMSPropertySubscript) {
-    assert(ArgExprs.size() == 1);
+    if (ArgExprs.size() > 1) {
+      Diag(base->getExprLoc(),
+           diag::err_ms_property_subscript_expects_single_arg);
+      return ExprError();
+    }
+
     // Build MS property subscript expression if base is MS property reference
     // or MS property subscript.
     return new (Context)
@@ -5163,6 +5169,17 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr 
*base,
   //
   // ObjC pointers have their own subscripting logic that is not tied
   // to overload resolution and so should not take this path.
+  //
+  // Issue a better diagnostic if we tried to pass multiple arguments to
+  // a builtin subscript operator rather than diagnosing this as a generic
+  // overload resolution failure.
+  if (ArgExprs.size() != 1 && !base->getType()->isRecordType() &&
+      !base->getType()->isObjCObjectPointerType()) {
+    Diag(base->getExprLoc(), 
diag::err_ovl_builtin_subscript_expects_single_arg)
+        << base->getType() << base->getSourceRange();
+    return ExprError();
+  }
+
   if (getLangOpts().CPlusPlus && !base->getType()->isObjCObjectPointerType() &&
       ((base->getType()->isRecordType() ||
         (ArgExprs.size() != 1 || isa<PackExpansionExpr>(ArgExprs[0]) ||

diff  --git a/clang/test/OpenMP/target_update_messages.cpp 
b/clang/test/OpenMP/target_update_messages.cpp
index 000cc80e513e6..1f6ecdbf344cb 100644
--- a/clang/test/OpenMP/target_update_messages.cpp
+++ b/clang/test/OpenMP/target_update_messages.cpp
@@ -241,7 +241,7 @@ void f() {
 
 #pragma omp target update to(test[1])
 
-#pragma omp target update to(test[1, 2]) // cxx23-error {{type 'int[10]' does 
not provide a subscript operator}} \
+#pragma omp target update to(test[1, 2]) // cxx23-error {{built-in subscript 
operator for type 'int[10]' expects exactly one argument}} \
                                          // cxx23-error {{expected at least 
one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 
 #pragma omp target update to(test [1:1:1])
@@ -255,7 +255,7 @@ void f() {
 #pragma omp target update to(test[1, 2 ::]) // cxx23-error {{expected ']'}} // 
expected-note {{'['}} \
                                             // cxx23-error {{expected at least 
one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
 
-#pragma omp target update to(test[]) // cxx23-error {{type 'int[10]' does not 
provide a subscript operator}} \
+#pragma omp target update to(test[]) // cxx23-error {{built-in subscript 
operator for type 'int[10]' expects exactly one argument}} \
                                             // cxx23-error {{expected at least 
one 'to' clause or 'from' clause specified to '#pragma omp target update'}}
   S s;
   (void)s[0];

diff  --git a/clang/test/SemaCXX/cxx23-builtin-subscript.cpp 
b/clang/test/SemaCXX/cxx23-builtin-subscript.cpp
new file mode 100644
index 0000000000000..8067663ded676
--- /dev/null
+++ b/clang/test/SemaCXX/cxx23-builtin-subscript.cpp
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -std=c++23 -verify -fenable-matrix -fdeclspec %s
+
+union U {};
+struct S {};
+enum E {};
+enum class EC {};
+
+using vec3 = int __attribute__((ext_vector_type(3)));
+using mat3 = int __attribute__((matrix_type(3, 3)));
+
+void f(int *p) {
+  int a[4]{};
+  vec3 v{};
+  mat3 m;
+  p[1, 2]; // expected-error {{built-in subscript operator for type 'int *' 
expects exactly one argument}}
+  p[1, p]; // expected-error {{built-in subscript operator for type 'int *' 
expects exactly one argument}}
+  1[1, 2]; // expected-error {{built-in subscript operator for type 'int' 
expects exactly one argument}}
+  1[p, 2]; // expected-error {{built-in subscript operator for type 'int' 
expects exactly one argument}}
+  1[p, 2]; // expected-error {{built-in subscript operator for type 'int' 
expects exactly one argument}}
+  p[U{}, U{}]; // expected-error {{built-in subscript operator for type 'int 
*' expects exactly one argument}}
+  p[E{}, 1]; // expected-error {{built-in subscript operator for type 'int *' 
expects exactly one argument}}
+  p[EC{}, 1]; // expected-error {{built-in subscript operator for type 'int *' 
expects exactly one argument}}
+  p[S{}, 1]; // expected-error {{built-in subscript operator for type 'int *' 
expects exactly one argument}}
+  p[1u, 1l]; // expected-error {{built-in subscript operator for type 'int *' 
expects exactly one argument}}
+  p[1, 2, 3]; // expected-error {{built-in subscript operator for type 'int *' 
expects exactly one argument}}
+  a[1, 2]; // expected-error {{built-in subscript operator for type 'int[4]' 
expects exactly one argument}}
+  a[1, p]; // expected-error {{built-in subscript operator for type 'int[4]' 
expects exactly one argument}}
+  a[S{}, p]; // expected-error {{built-in subscript operator for type 'int[4]' 
expects exactly one argument}}
+  a[1, 2, 3]; // expected-error {{built-in subscript operator for type 
'int[4]' expects exactly one argument}}
+  v[1, 2]; // expected-error {{built-in subscript operator for type 'vec3' 
(vector of 3 'int' values) expects exactly one argument}}
+  v[1, p]; // expected-error {{built-in subscript operator for type 'vec3' 
(vector of 3 'int' values) expects exactly one argument}}
+  v[S{}, p]; // expected-error {{built-in subscript operator for type 'vec3' 
(vector of 3 'int' values) expects exactly one argument}}
+  v[1, 2, 3]; // expected-error {{built-in subscript operator for type 'vec3' 
(vector of 3 'int' values) expects exactly one argument}}
+  E{}[2, 2]; // expected-error {{built-in subscript operator for type 'E' 
expects exactly one argument}}
+  EC{}[2, 2]; // expected-error {{built-in subscript operator for type 'EC' 
expects exactly one argument}}
+
+  m[1][3, 4]; // expected-error {{comma expressions are not allowed as indices 
in matrix subscript}}
+  m[1][2, 3]; // expected-error {{comma expressions are not allowed as indices 
in matrix subscript}}
+  m[1, 2][3, 4]; // expected-error {{comma expressions are not allowed as 
indices in matrix subscript}}
+
+  U{}[2, 2]; // expected-error {{type 'U' does not provide a subscript 
operator}}
+  S{}[2, 2]; // expected-error {{type 'S' does not provide a subscript 
operator}}
+}
+
+struct Prop {
+  constexpr int get_two(int a, int b);
+  constexpr int get_three(int a, int b, int c);
+  constexpr void put_two(int a, int b, int c);
+  constexpr void put_three(int a, int b, int c, int d);
+  __declspec(property(get = get_two, put = put_two)) int two[][];
+  __declspec(property(get = get_three, put = put_three)) int three[][][];
+};
+
+void f() {
+  Prop p;
+  p.two[1, 2]; // expected-error {{property subscript expects exactly one 
argument}}
+  p.three[1, 2, 3]; // expected-error {{property subscript expects exactly one 
argument}}
+  p.three[1, 2][3]; // expected-error {{property subscript expects exactly one 
argument}}
+  p.three[1][2, 3]; // expected-error {{property subscript expects exactly one 
argument}}
+  p.two[1, 2] = 3; // expected-error {{property subscript expects exactly one 
argument}}
+  p.three[1, 2, 3] = 4; // expected-error {{property subscript expects exactly 
one argument}}
+  p.three[1, 2][3] = 4; // expected-error {{property subscript expects exactly 
one argument}}
+  p.three[1][2, 3] = 4; // expected-error {{property subscript expects exactly 
one argument}}
+}

diff  --git a/clang/test/SemaCXX/cxx2b-overloaded-operator.cpp 
b/clang/test/SemaCXX/cxx2b-overloaded-operator.cpp
index c734b82987083..2ca72c8d39cc2 100644
--- a/clang/test/SemaCXX/cxx2b-overloaded-operator.cpp
+++ b/clang/test/SemaCXX/cxx2b-overloaded-operator.cpp
@@ -98,7 +98,7 @@ int cxx_subscript_unexpanded() {
 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}}
+  return arr[Is...]; // expected-error 2{{built-in subscript operator for type 
'int[3]' expects exactly one argument}}
 }
 
 template<int... Is>


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to