[clang] [clang] Fix `static_cast` to array of unknown bound (PR #96041)

Mariya Podchishchaeva via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 19 01:29:16 PDT 2024


https://github.com/Fznamznon created https://github.com/llvm/llvm-project/pull/96041

Per P1975R0 an expression like static_cast<U[]>(...) defines the type of the expression as U[1].

Fixes https://github.com/llvm/llvm-project/issues/62863

>From df58be94be017265b16999525bed8eb75d4d94d8 Mon Sep 17 00:00:00 2001
From: "Podchishchaeva, Mariya" <mariya.podchishchaeva at intel.com>
Date: Wed, 19 Jun 2024 01:27:18 -0700
Subject: [PATCH] [clang] Fix `static_cast` to array of unknown bound

Per P1975R0 an expression like static_cast<U[]>(...) defines the type
of the expression as U[1].

Fixes https://github.com/llvm/llvm-project/issues/62863
---
 clang/docs/ReleaseNotes.rst                |  2 ++
 clang/lib/Sema/SemaType.cpp                | 14 ++++++++++++++
 clang/test/SemaCXX/paren-list-agg-init.cpp | 21 +++++++++++++++++++++
 3 files changed, 37 insertions(+)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7112d1f889fef..d0e5e67651364 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -695,6 +695,8 @@ Bug Fixes in This Version
 - Correctly reject declarations where a statement is required in C.
   Fixes #GH92775
 
+- Fixed `static_cast` to array of unknown bound. Fixes (#GH62863).
+
 Bug Fixes to Compiler Builtins
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 441fdcca0758f..9bb12c6aa7b12 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -8771,6 +8771,20 @@ void Sema::completeExprArrayBound(Expr *E) {
       }
     }
   }
+  if (const auto CastE = dyn_cast<ExplicitCastExpr>(E)) {
+    QualType DestType = CastE->getTypeAsWritten();
+    if (const auto *IAT = Context.getAsIncompleteArrayType(DestType)) {
+      // C++20 [expr.static.cast]p.4: ... If T is array of unknown bound,
+      // this direct-initialization defines the type of the expression
+      // as U[1]
+      QualType ResultType = Context.getConstantArrayType(
+          IAT->getElementType(),
+          llvm::APInt(Context.getTypeSize(Context.getSizeType()), 1),
+          /*SizeExpr=*/nullptr, ArraySizeModifier::Normal,
+          /*IndexTypeQuals=*/0);
+      E->setType(ResultType);
+    }
+  }
 }
 
 QualType Sema::getCompletedType(Expr *E) {
diff --git a/clang/test/SemaCXX/paren-list-agg-init.cpp b/clang/test/SemaCXX/paren-list-agg-init.cpp
index c1964a5a9eb00..efc1e955d4ed8 100644
--- a/clang/test/SemaCXX/paren-list-agg-init.cpp
+++ b/clang/test/SemaCXX/paren-list-agg-init.cpp
@@ -313,3 +313,24 @@ namespace GH63903 {
   constexpr S s(0); // beforecxx20-warning {{aggregate initialization of type 'const S' from a parenthesized list of values is a C++20 extension}} \
                     // expected-error {{constexpr variable 's' must be initialized by a constant expression}}
 }
+
+
+namespace gh62863 {
+int (&&arr)[] = static_cast<int[]>(42);
+// beforecxx20-warning at -1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
+int (&&arr1)[1] = static_cast<int[]>(42);
+// beforecxx20-warning at -1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
+int (&&arr2)[2] = static_cast<int[]>(42); // expected-error {{reference to type 'int[2]' could not bind to an rvalue of type 'int[1]'}}
+// beforecxx20-warning at -1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
+int (&&arr3)[3] = static_cast<int[3]>(42);
+// beforecxx20-warning at -1 {{aggregate initialization of type 'int[3]' from a parenthesized list of values is a C++20 extension}}
+
+int (&&arr4)[] = (int[])(42);
+// beforecxx20-warning at -1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
+int (&&arr5)[1] = (int[])(42);
+// beforecxx20-warning at -1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
+int (&&arr6)[2] = (int[])(42); // expected-error {{reference to type 'int[2]' could not bind to an rvalue of type 'int[1]'}}
+// beforecxx20-warning at -1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
+int (&&arr7)[3] = (int[3])(42);
+// beforecxx20-warning at -1 {{aggregate initialization of type 'int[3]' from a parenthesized list of values is a C++20 extension}}
+}



More information about the cfe-commits mailing list