https://github.com/offsetof updated https://github.com/llvm/llvm-project/pull/131295
>From 78b3095b0e3ca4af1cd015bacd6173d3f4ab1777 Mon Sep 17 00:00:00 2001 From: offsetof <offse...@mailo.com> Date: Fri, 14 Mar 2025 08:38:58 +0000 Subject: [PATCH 1/2] [clang] Fix handling of certain new-expression corner cases * Fix array bound not being deduced from the initializer when the new-expression does not directly contain the array declarator (e.g. because a typedef is used) * Fix initialization of character arrays from parenthesized string literals not working before C++20 --- clang/lib/Sema/SemaExprCXX.cpp | 33 ++++++++++++-------- clang/test/SemaCXX/P1009R2.cpp | 55 ++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 clang/test/SemaCXX/P1009R2.cpp diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 34219e0235a74..638f5dd9e9c2d 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1939,7 +1939,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, return ExprError(Diag(Chunk.Loc, diag::err_array_new_needs_size) << D.getSourceRange()); - ArraySize = static_cast<Expr*>(Chunk.Arr.NumElts); + ArraySize = Chunk.Arr.NumElts; D.DropFirstTypeObject(); } @@ -1950,7 +1950,7 @@ Sema::ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, break; DeclaratorChunk::ArrayTypeInfo &Array = D.getTypeObject(I).Arr; - if (Expr *NumElts = (Expr *)Array.NumElts) { + if (Expr *NumElts = Array.NumElts) { if (!NumElts->isTypeDependent() && !NumElts->isValueDependent()) { // FIXME: GCC permits constant folding here. We should either do so consistently // or not do so at all, rather than changing behavior in C++14 onwards. @@ -1996,13 +1996,15 @@ static bool isLegalArrayNewInitializer(CXXNewInitializationStyle Style, if (!Init) return true; if (ParenListExpr *PLE = dyn_cast<ParenListExpr>(Init)) - return IsCPlusPlus20 || PLE->getNumExprs() == 0; + return IsCPlusPlus20 || PLE->getNumExprs() == 0 || + (PLE->getNumExprs() == 1 && + isa<StringLiteral>(PLE->getExpr(0)->IgnoreParens())); if (isa<ImplicitValueInitExpr>(Init)) return true; - else if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) + if (CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(Init)) return !CCE->isListInitialization() && CCE->getConstructor()->isDefaultConstructor(); - else if (Style == CXXNewInitializationStyle::Braces) { + if (Style == CXXNewInitializationStyle::Braces) { assert(isa<InitListExpr>(Init) && "Shouldn't create list CXXConstructExprs for arrays."); return true; @@ -2159,12 +2161,15 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // typedef of an array type. // Dependent case will be handled separately. if (!ArraySize && !AllocType->isDependentType()) { - if (const ConstantArrayType *Array - = Context.getAsConstantArrayType(AllocType)) { - ArraySize = IntegerLiteral::Create(Context, Array->getSize(), - Context.getSizeType(), - TypeRange.getEnd()); - AllocType = Array->getElementType(); + if (auto *Array = Context.getAsArrayType(AllocType)) { + auto *CAT = dyn_cast<ConstantArrayType>(Array); + if (CAT || isa<IncompleteArrayType>(Array)) { + ArraySize = CAT ? IntegerLiteral::Create(Context, CAT->getSize(), + Context.getSizeType(), + TypeRange.getEnd()) + : nullptr; + AllocType = Array->getElementType(); + } } } @@ -2497,8 +2502,10 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, // initializer is no greater than that constant value. if (ArraySize && !*ArraySize) { - auto *CAT = Context.getAsConstantArrayType(Initializer->getType()); - if (CAT) { + if (!Initializer) + Diag(TypeRange.getEnd(), diag::err_array_new_needs_size) << TypeRange; + else if (auto *CAT = + Context.getAsConstantArrayType(Initializer->getType())) { // FIXME: Track that the array size was inferred rather than explicitly // specified. ArraySize = IntegerLiteral::Create( diff --git a/clang/test/SemaCXX/P1009R2.cpp b/clang/test/SemaCXX/P1009R2.cpp new file mode 100644 index 0000000000000..c89d912b29149 --- /dev/null +++ b/clang/test/SemaCXX/P1009R2.cpp @@ -0,0 +1,55 @@ +// RUN: %clang_cc1 %s -fsyntax-only -std=c++11 -verify=expected,until-cxx20 +// RUN: %clang_cc1 %s -fsyntax-only -std=c++20 -verify + +void f() { + new int[]; // expected-error {{array size must be specified in new expression with no initializer}} + new int[](); // expected-error {{cannot determine allocated array size from initializer}} + int* a = new int[](1, 2); // until-cxx20-error {{array 'new' cannot have initialization arguments}} + int* b = new int[] {}; + int* c = new int[] {1, 2}; + + int* d = new (int[])(1, 2); // until-cxx20-error {{array 'new' cannot have initialization arguments}} + int* e = new (int[]) {1, 2}; + + using IA = int[]; + new IA; // expected-error {{array size must be specified in new expression with no initializer}} + new IA(); // expected-error {{cannot determine allocated array size from initializer}} + int* f = new IA(1, 2); // until-cxx20-error {{array 'new' cannot have initialization arguments}} + int* g = new IA {}; + int* h = new IA {1, 2}; + + extern int ia[]; + int* i = new decltype(ia)(1, 2); // until-cxx20-error {{array 'new' cannot have initialization arguments}} + int* j = new decltype(ia) {1, 2}; + + char* k = new char[]("hello"); + char* l = new char[] {"hello"}; + + using C = char; + char* m = new C[]("hello"); + char* n = new C[] {"hello"}; + + using CA = char[]; + char* o = new CA("hello"); + char* p = new CA {"hello"}; + + extern wchar_t wa[]; + wchar_t* q = new decltype(wa)(L"hello"); + wchar_t* r = new decltype(wa) {L"hello"}; +} + +template<class IA = int[], class C = char, class CA = char[]> +void g() { + new IA; // expected-error {{array size must be specified in new expression with no initializer}} + new IA(); // expected-error {{cannot determine allocated array size from initializer}} + int* a = new IA(1, 2); // until-cxx20-error {{array 'new' cannot have initialization arguments}} + int* b = new IA {1, 2}; + + char* c = new C[]("hello"); + char* d = new C[] {"hello"}; + + char* e = new CA("hello"); + char* f = new CA {"hello"}; +} + +template void g(); // expected-note {{in instantiation of function template specialization}} >From 26e731c959b072c76103c6dadc9a7872ac060693 Mon Sep 17 00:00:00 2001 From: offsetof <offse...@mailo.com> Date: Mon, 24 Mar 2025 16:34:55 +0000 Subject: [PATCH 2/2] fixup! [clang] Fix handling of certain new-expression corner cases Add a release note --- clang/docs/ReleaseNotes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 86495e80eb188..c21875c82f85f 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -310,6 +310,7 @@ Bug Fixes to C++ Support - Clang now correctly parses ``if constexpr`` expressions in immediate function context. (#GH123524) - Fixed an assertion failure affecting code that uses C++23 "deducing this". (#GH130272) - Clang now properly instantiates destructors for initialized members within non-delegating constructors. (#GH93251) +- Fixed some valid forms of ``new[]``-expressions being rejected. (#GH131295) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits