hazohelet created this revision. hazohelet added reviewers: aaron.ballman, tbaeder, cjdb. Herald added a project: All. hazohelet requested review of this revision. Herald added a project: clang.
BEFORE this patch, compound assignment operator against uninitialized object such as `uninit += 1` was diagnosed as `subexpression not valid` This patch clarifies the reason for the error by saying that `uninit` is an uninitialized object. Fixes https://github.com/llvm/llvm-project/issues/51536 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D157855 Files: clang/docs/ReleaseNotes.rst clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/constant-expression-cxx2a.cpp 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)'}} +} 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/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 <https://github.com/llvm/llvm-project/issues/51536>_`) Bug Fixes in This Version -------------------------
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)'}} +} 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/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 <https://github.com/llvm/llvm-project/issues/51536>_`) Bug Fixes in This Version -------------------------
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits