Index: clang/docs/ReleaseNotes.rst =================================================================== --- clang/docs/ReleaseNotes.rst +++ clang/docs/ReleaseNotes.rst @@ -129,6 +129,9 @@ of a base class is not called in the constructor of its derived class. - Clang no longer emits ``-Wmissing-variable-declarations`` for variables declared with the ``register`` storage class. +- Clang constexpr evaluator now diagnoses compound assignment operators against + uninitialized variables as a read of uninitialized object. + (`#51536 _`) Bug Fixes in This Version ------------------------- Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -4442,6 +4442,10 @@ return foundPointer(Subobj, SubobjType); case APValue::Vector: return foundVector(Subobj, SubobjType); + case APValue::Indeterminate: + Info.FFDiag(E, diag::note_constexpr_access_uninit) + << /*read of*/ 0 << /*uninitialized object*/ 1; + return false; default: // FIXME: can this happen? Info.FFDiag(E); Index: clang/test/SemaCXX/constant-expression-cxx2a.cpp =================================================================== --- clang/test/SemaCXX/constant-expression-cxx2a.cpp +++ clang/test/SemaCXX/constant-expression-cxx2a.cpp @@ -1492,3 +1492,33 @@ 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 UninitCompoundAssign { +constexpr int scalar(int a) { + int sum; + sum += a; // expected-note {{read of uninitialized object}}; + return 0; +} +static_assert(scalar(3)); // expected-error {{constant expression}} \ + // expected-note {{in call to 'scalar(3)'}} + +constexpr int array(int a) { + int arr[3]; + arr[1] += a; // expected-note {{read of uninitialized object}}; + return 0; +} +static_assert(array(3)); // expected-error {{constant expression}} \ + // expected-note {{in call to 'array(3)'}} + +struct Foo { + int val; + constexpr Foo() {} +}; +constexpr int field(int a) { + Foo f; + f.val += a; // expected-note {{read of uninitialized object}}; + return 0; +} +static_assert(field(3)); // expected-error {{constant expression}} \ + // expected-note {{in call to 'field(3)'}} +}