llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: marius doerner (mariusdr) <details> <summary>Changes</summary> Closes #<!-- -->131432 Raise an error when placement new is used to modify a const-qualified variable in a constexpr function. Note that diag::note_constexpr_modify_const_type is used since the it is also raised when the sample program is compiled with '-fexperimental-new-constant-interpreter'. --- Full diff: https://github.com/llvm/llvm-project/pull/132460.diff 2 Files Affected: - (modified) clang/lib/AST/ExprConstant.cpp (+9) - (modified) clang/test/AST/ByteCode/placement-new.cpp (+39) ``````````diff diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 92a28897cf3ee..b4fc3d4471064 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -10415,7 +10415,16 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { typedef bool result_type; bool failed() { return false; } + bool checkConst(QualType QT) { + if (QT.isConstQualified()) { + Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT; + return false; + } + return true; + } bool found(APValue &Subobj, QualType SubobjType) { + if (!checkConst(SubobjType)) + return false; // FIXME: Reject the cases where [basic.life]p8 would not permit the // old name of the object to be used to name the new object. unsigned SubobjectSize = 1; diff --git a/clang/test/AST/ByteCode/placement-new.cpp b/clang/test/AST/ByteCode/placement-new.cpp index c353162a7aab0..9b12c9f2b1714 100644 --- a/clang/test/AST/ByteCode/placement-new.cpp +++ b/clang/test/AST/ByteCode/placement-new.cpp @@ -376,3 +376,42 @@ constexpr int N = [] // expected-error {{must be initialized by a constant expre return s.a[0]; }(); #endif + +constexpr int modify_const_variable() { + const int a = 10; + new ((int *)&a) int(12); // both-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}} + return a; +} +static_assert(modify_const_variable()); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + +typedef const int T0; +typedef T0 T1; +constexpr T1 modify_const_variable_td() { + T1 a = 10; + new ((int *)&a) int(12); // both-note {{modification of object of const-qualified type 'T1' (aka 'const int') is not allowed in a constant expression}} + return a; +} +static_assert(modify_const_variable_td()); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + +template<typename T> +constexpr T modify_const_variable_tmpl() { + T a = 10; + new ((int *)&a) int(12); // both-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}} + return a; +} +static_assert(modify_const_variable_tmpl<const int>()); // both-error {{not an integral constant expression}} \ + // both-note {{in call to}} + +namespace ModifyMutableMember { + struct S { + mutable int a {10}; + }; + constexpr int modify_mutable_member() { + const S s; + new ((int *)&s.a) int(12); + return s.a; + } + static_assert(modify_mutable_member() == 12); +} `````````` </details> https://github.com/llvm/llvm-project/pull/132460 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits