diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 88844ad9b4c55..a06302531bc2e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -719,6 +719,8 @@ Bug Fixes in This Version points (i.e., uses function descriptor objects instead). - Fixes a ``clang-17`` regression where ``LLVM_UNREACHABLE_OPTIMIZE=OFF`` cannot be used with ``Release`` mode builds. (`#68237 `_). +- Fix crash from constexpr evaluator evaluating uninitialized arrays as rvalue. + Fixes (`#67317 `_) - No longer use C++ ``thread_local`` semantics in C23 when using ``thread_local`` instead of ``_Thread_local``. Fixes (`#70068 `_) and diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td b/clang/include/clang/Basic/DiagnosticASTKinds.td index 0794ed7ba6837..694e6a5840bcb 100644 --- a/clang/include/clang/Basic/DiagnosticASTKinds.td +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td @@ -69,7 +69,7 @@ def note_consteval_address_accessible : Note< "%select{pointer|reference}0 to a consteval declaration " "is not a constant expression">; def note_constexpr_uninitialized : Note< - "subobject %0 is not initialized">; + "subobject %select{of type |}0%1 is not initialized">; def note_constexpr_uninitialized_base : Note< "constructor of base class %0 is not called">; def note_constexpr_static_local : Note< diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index c62044f36194c..99ae88a6cd692 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -2379,10 +2379,15 @@ static bool CheckEvaluationResult(CheckEvaluationResultKind CERK, const FieldDecl *SubobjectDecl, CheckedTemporaries &CheckedTemps) { if (!Value.hasValue()) { - assert(SubobjectDecl && "SubobjectDecl shall be non-null"); - Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) << SubobjectDecl; - Info.Note(SubobjectDecl->getLocation(), - diag::note_constexpr_subobject_declared_here); + if (SubobjectDecl) { + Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) + << /*(name)*/ 1 << SubobjectDecl; + Info.Note(SubobjectDecl->getLocation(), + diag::note_constexpr_subobject_declared_here); + } else { + Info.FFDiag(DiagLoc, diag::note_constexpr_uninitialized) + << /*of type*/ 0 << Type; + } return false; } diff --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp index 4917f43f9512e..59108b8575774 100644 --- a/clang/lib/AST/Interp/Interp.cpp +++ b/clang/lib/AST/Interp/Interp.cpp @@ -382,7 +382,8 @@ bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD) { static void DiagnoseUninitializedSubobject(InterpState &S, const SourceInfo &SI, const FieldDecl *SubObjDecl) { assert(SubObjDecl && "Subobject declaration does not exist"); - S.FFDiag(SI, diag::note_constexpr_uninitialized) << SubObjDecl; + S.FFDiag(SI, diag::note_constexpr_uninitialized) + << /*(name)*/ 1 << SubObjDecl; S.Note(SubObjDecl->getLocation(), diag::note_constexpr_subobject_declared_here); } diff --git a/clang/test/SemaCXX/constant-expression-cxx2a.cpp b/clang/test/SemaCXX/constant-expression-cxx2a.cpp index 09f17d5b38949..e4d97dcb73562 100644 --- a/clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ b/clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -1492,3 +1492,9 @@ class B{ class D : B{}; // expected-error {{deleted function '~D' cannot override a non-deleted function}} // expected-note@-1 {{destructor of 'D' is implicitly deleted because base class 'B' has an inaccessible destructor}} } + +namespace GH67317 { + constexpr unsigned char a = // expected-error {{constexpr variable 'a' must be initialized by a constant expression}} \ + // expected-note {{subobject of type 'const unsigned char' is not initialized}} + __builtin_bit_cast(unsigned char, *new char[3][1]); +}; diff --git a/clang/test/SemaCXX/eval-crashes.cpp b/clang/test/SemaCXX/eval-crashes.cpp index 3e59ad31c559d..ac04b113f99b7 100644 --- a/clang/test/SemaCXX/eval-crashes.cpp +++ b/clang/test/SemaCXX/eval-crashes.cpp @@ -54,3 +54,10 @@ namespace pr33140_10 { int a(const int &n = 0); bool b() { return a() == a(); } } + +namespace GH67317 { +struct array { + int (&data)[2]; + array() : data(*new int[1][2]) {} +}; +}