Skip to content

Commit b9ad0b6

Browse files
authored
[clang] Fix static_cast to array of unknown bound (#96041)
Per P1975R0 an expression like static_cast<U[]>(...) defines the type of the expression as U[1]. Fixes #62863
1 parent 7cf84d3 commit b9ad0b6

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,8 @@ Bug Fixes in This Version
695695
- Correctly reject declarations where a statement is required in C.
696696
Fixes #GH92775
697697

698+
- Fixed `static_cast` to array of unknown bound. Fixes (#GH62863).
699+
698700
Bug Fixes to Compiler Builtins
699701
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
700702

clang/lib/Sema/SemaType.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8771,6 +8771,20 @@ void Sema::completeExprArrayBound(Expr *E) {
87718771
}
87728772
}
87738773
}
8774+
if (const auto CastE = dyn_cast<ExplicitCastExpr>(E)) {
8775+
QualType DestType = CastE->getTypeAsWritten();
8776+
if (const auto *IAT = Context.getAsIncompleteArrayType(DestType)) {
8777+
// C++20 [expr.static.cast]p.4: ... If T is array of unknown bound,
8778+
// this direct-initialization defines the type of the expression
8779+
// as U[1]
8780+
QualType ResultType = Context.getConstantArrayType(
8781+
IAT->getElementType(),
8782+
llvm::APInt(Context.getTypeSize(Context.getSizeType()), 1),
8783+
/*SizeExpr=*/nullptr, ArraySizeModifier::Normal,
8784+
/*IndexTypeQuals=*/0);
8785+
E->setType(ResultType);
8786+
}
8787+
}
87748788
}
87758789

87768790
QualType Sema::getCompletedType(Expr *E) {

clang/test/SemaCXX/paren-list-agg-init.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,3 +313,24 @@ namespace GH63903 {
313313
constexpr S s(0); // beforecxx20-warning {{aggregate initialization of type 'const S' from a parenthesized list of values is a C++20 extension}} \
314314
// expected-error {{constexpr variable 's' must be initialized by a constant expression}}
315315
}
316+
317+
318+
namespace gh62863 {
319+
int (&&arr)[] = static_cast<int[]>(42);
320+
// beforecxx20-warning@-1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
321+
int (&&arr1)[1] = static_cast<int[]>(42);
322+
// beforecxx20-warning@-1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
323+
int (&&arr2)[2] = static_cast<int[]>(42); // expected-error {{reference to type 'int[2]' could not bind to an rvalue of type 'int[1]'}}
324+
// beforecxx20-warning@-1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
325+
int (&&arr3)[3] = static_cast<int[3]>(42);
326+
// beforecxx20-warning@-1 {{aggregate initialization of type 'int[3]' from a parenthesized list of values is a C++20 extension}}
327+
328+
int (&&arr4)[] = (int[])(42);
329+
// beforecxx20-warning@-1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
330+
int (&&arr5)[1] = (int[])(42);
331+
// beforecxx20-warning@-1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
332+
int (&&arr6)[2] = (int[])(42); // expected-error {{reference to type 'int[2]' could not bind to an rvalue of type 'int[1]'}}
333+
// beforecxx20-warning@-1 {{aggregate initialization of type 'int[1]' from a parenthesized list of values is a C++20 extension}}
334+
int (&&arr7)[3] = (int[3])(42);
335+
// beforecxx20-warning@-1 {{aggregate initialization of type 'int[3]' from a parenthesized list of values is a C++20 extension}}
336+
}

0 commit comments

Comments
 (0)