Author: DaanishD20 Date: 2026-07-07T08:55:48Z New Revision: 81e317971d50396fc68a602a505eb85572c51373
URL: https://github.com/llvm/llvm-project/commit/81e317971d50396fc68a602a505eb85572c51373 DIFF: https://github.com/llvm/llvm-project/commit/81e317971d50396fc68a602a505eb85572c51373.diff LOG: [clang] Fix constant-evaluator crash on array new with no size (#207730) An array new-expression whose bound is neither specified nor deducible from its initializer (for example `new int[]()`) is ill-formed and is already diagnosed by Sema with `error: cannot determine allocated array size from initializer`. However, the constant evaluator still tried to evaluate the recovery expression. In `PointerExprEvaluator::VisitCXXNewExpr` the array size is unavailable (`E->getArraySize()` is `nullopt`), so the allocation fell through to the scalar-new path, producing an array `APValue` stored under a scalar type. Reading that object later asserted in `Type::castAsArrayTypeUnsafe()` (`isa<ArrayType>(CanonicalType)`) from `CheckEvaluationResult`. This patch detects an array new-expression whose size could not be determined and bails out of constant evaluation. Fixes #200139 Added: Modified: clang/docs/ReleaseNotes.md clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/constant-expression-cxx2a.cpp Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index a37e1be5862b3..cc85604343da9 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -773,6 +773,7 @@ latest release, please see the [Clang Web Site](https://clang.llvm.org) or the - Fixed an assertion where we improperly handled implicit conversions to integral types from an atomic-type with a conversion function. (#GH201770) - Fixed assertion failures involving code completion with delayed default arguments and exception specifications. (#GH200879) - Fixed a regression where calling a function that takes a class-type parameter by value inside `decltype` of a concept could be incorrectly rejected when used as a non-type template argument. (#GH175831) +- Fixed a crash in the constant evaluator when an ill-formed array new-expression whose bound could not be determined (e.g. `new int[]()`) was used in a constant expression. (#GH200139) #### Bug Fixes to Compiler Builtins diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 109dc627133f2..28772a574e60a 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -10913,6 +10913,13 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { AllocType = Info.Ctx.getConstantArrayType(AllocType, ArrayBound, nullptr, ArraySizeModifier::Normal, 0); + } else if (E->isArray()) { + // We have an array new-expression whose array size could not be + // determined, e.g. 'new int[]()', where the bound is neither given nor + // deducible from the initializer. This is ill-formed and already + // diagnosed, so bail out rather than mis-evaluating a scalar allocation + // as an array (which would later crash the evaluator). + return false; } else { assert(!AllocType->isArrayType() && "array allocation with non-array new"); diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index 396a8df21a3e3..94ecafc081302 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -898,6 +898,12 @@ namespace dynamic_alloc { static_assert(erroneous_array_bound(-1)); // expected-error {{constant expression}} expected-note {{in call}} static_assert(erroneous_array_bound(1LL << 62)); // expected-error {{constant expression}} expected-note {{in call}} + // An array new-expression whose bound is neither given nor deducible from the + // initializer is ill-formed; the constant evaluator must reject it gracefully + // rather than crash. See GH200139. + static_assert((new int[]())[0] == 0); // expected-error {{cannot determine allocated array size from initializer}} \ + // expected-error {{static assertion expression is not an integral constant expression}} + constexpr bool erroneous_array_bound_nothrow(long long n) { int *p = new (std::nothrow) int[n]; bool result = p != 0; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
