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
