[clang] [clang] Fix filler handling for new expression with unspecified bound. (PR #182203)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Feb 18 17:10:29 PST 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Eli Friedman (efriedma-quic)
<details>
<summary>Changes</summary>
Array new with a runtime bound requires an "array filler" to initialize elements which aren't explicitly initialized. Array new with an unspecified bound doesn't need this; the array length is a compile-time constant. Make sure SemaInit doesn't confuse the two cases.
Fixes #<!-- -->81157.
---
Full diff: https://github.com/llvm/llvm-project/pull/182203.diff
3 Files Affected:
- (modified) clang/include/clang/Sema/Initialization.h (+11-5)
- (modified) clang/lib/Sema/SemaExprCXX.cpp (+6-4)
- (modified) clang/test/SemaCXX/new-delete.cpp (+16)
``````````diff
diff --git a/clang/include/clang/Sema/Initialization.h b/clang/include/clang/Sema/Initialization.h
index 0e2891f1ff5c2..cd729aa16dc28 100644
--- a/clang/include/clang/Sema/Initialization.h
+++ b/clang/include/clang/Sema/Initialization.h
@@ -160,6 +160,10 @@ class alignas(8) InitializedEntity {
/// Whether the entity being initialized may end up using the
/// named return value optimization (NRVO).
bool NRVO;
+
+ /// When Kind == EK_New, whether this is initializing an array of runtime
+ /// size (which needs an array filler).
+ bool VariableLengthArrayNew;
};
struct VD {
@@ -227,11 +231,12 @@ class alignas(8) InitializedEntity {
/// function, throwing an object, performing an explicit cast, or
/// initializing a parameter for which there is no declaration.
InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type,
- bool NRVO = false)
+ bool NRVO = false, bool VariableLengthArrayNew = false)
: Kind(Kind), Type(Type) {
new (&LocAndNRVO) LN;
LocAndNRVO.Location = Loc;
LocAndNRVO.NRVO = NRVO;
+ LocAndNRVO.VariableLengthArrayNew = VariableLengthArrayNew;
}
/// Create the initialization entity for a member subobject.
@@ -335,8 +340,10 @@ class alignas(8) InitializedEntity {
}
/// Create the initialization entity for an object allocated via new.
- static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type) {
- return InitializedEntity(EK_New, NewLoc, Type);
+ static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type,
+ bool VariableLengthArrayNew) {
+ return InitializedEntity(EK_New, NewLoc, Type, /*NRVO*/ false,
+ VariableLengthArrayNew);
}
/// Create the initialization entity for a temporary.
@@ -506,8 +513,7 @@ class alignas(8) InitializedEntity {
/// Determine whether this is an array new with an unknown bound.
bool isVariableLengthArrayNew() const {
- return getKind() == EK_New && isa_and_nonnull<IncompleteArrayType>(
- getType()->getAsArrayTypeUnsafe());
+ return getKind() == EK_New && LocAndNRVO.VariableLengthArrayNew;
}
/// Is this the implicit initialization of a member of a class from
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 91967a7a9ff97..a1e95dbe676de 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2206,8 +2206,9 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
<< /*array*/ 2
<< (*ArraySize ? (*ArraySize)->getSourceRange() : TypeRange));
- InitializedEntity Entity
- = InitializedEntity::InitializeNew(StartLoc, AllocType);
+ InitializedEntity Entity =
+ InitializedEntity::InitializeNew(StartLoc, AllocType,
+ /*VariableLengthArrayNew*/ false);
AllocType = DeduceTemplateSpecializationFromInitializer(
AllocTypeInfo, Entity, Kind, Exprs);
if (AllocType.isNull())
@@ -2589,8 +2590,9 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
else
InitType = AllocType;
- InitializedEntity Entity
- = InitializedEntity::InitializeNew(StartLoc, InitType);
+ bool VariableLengthArrayNew = ArraySize && *ArraySize && !KnownArraySize;
+ InitializedEntity Entity = InitializedEntity::InitializeNew(
+ StartLoc, InitType, VariableLengthArrayNew);
InitializationSequence InitSeq(*this, Entity, Kind, Exprs);
ExprResult FullInit = InitSeq.Perform(*this, Entity, Kind, Exprs);
if (FullInit.isInvalid())
diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp
index 1adb993f46c8f..cda49a02098b0 100644
--- a/clang/test/SemaCXX/new-delete.cpp
+++ b/clang/test/SemaCXX/new-delete.cpp
@@ -725,3 +725,19 @@ int (*const_fold)[12] = new int[3][&const_fold + 12 - &const_fold];
// expected-error at -5 {{cannot allocate object of variably modified type}}
// expected-warning at -6 {{variable length arrays in C++ are a Clang extension}}
#endif
+
+#if __cplusplus >= 201103L
+namespace PR81157 {
+ struct C {
+ C(int);
+ };
+ int f(int n) {
+ C *ptr1{new C[]{1L}};
+ C *ptr2{new C[n]{1L}};
+ // expected-error at -1 {{no matching constructor}}
+ // expected-note at -6 {{candidate constructor}}
+ // expected-note at -8 2 {{candidate constructor}}
+ // expected-note at -4 {{in implicit initialization of trailing array elements in runtime-sized array new}}
+ }
+}
+#endif
``````````
</details>
https://github.com/llvm/llvm-project/pull/182203
More information about the cfe-commits
mailing list