[clang] 4067581 - [clang] Placement new error when modifying consts (#132460)

via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 25 12:39:15 PDT 2025


Author: marius doerner
Date: 2025-03-25T20:39:12+01:00
New Revision: 4067581aea299692d37866183b0a535f561892ad

URL: https://github.com/llvm/llvm-project/commit/4067581aea299692d37866183b0a535f561892ad
DIFF: https://github.com/llvm/llvm-project/commit/4067581aea299692d37866183b0a535f561892ad.diff

LOG: [clang] Placement new error when modifying consts (#132460)

Raise an error when placement new is used to modify a const-qualified
variable in a constexpr function.

Fixes #131432

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/ExprConstant.cpp
    clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c73f4fd446ac8..04ec2cfef679c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -362,6 +362,8 @@ Bug Fixes to C++ Support
 - Fixed a Clang regression in C++20 mode where unresolved dependent call expressions were created inside non-dependent contexts (#GH122892)
 - Clang now emits the ``-Wunused-variable`` warning when some structured bindings are unused
   and the ``[[maybe_unused]]`` attribute is not applied. (#GH125810)
+- Clang now issues an error when placement new is used to modify a const-qualified variable 
+  in a ``constexpr`` function. (#GH131432)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 8b40cdfbd2f1f..95da7b067b459 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -10420,7 +10420,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/SemaCXX/cxx2c-constexpr-placement-new.cpp b/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp
index a29fb981cedbf..6f6f9b04aa392 100644
--- a/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp
+++ b/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp
@@ -114,3 +114,42 @@ constexpr bool bleh() {
 }
 static_assert(bleh()); // expected-error {{not an integral constant expression}} \
                         // expected-note {{in call to 'bleh()'}}
+
+constexpr int modify_const_variable() {
+  const int a = 10;
+  new ((int *)&a) int(12); // expected-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}}
+  return a;
+}
+static_assert(modify_const_variable()); // expected-error {{not an integral constant expression}} \
+                                        // expected-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); // expected-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()); // expected-error {{not an integral constant expression}} \
+                                           // expected-note {{in call to}}
+
+template<typename T>
+constexpr T modify_const_variable_tmpl() {
+  T a = 10;
+  new ((int *)&a) int(12); // expected-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>()); // expected-error {{not an integral constant expression}} \
+                                                        // expected-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);
+}


        


More information about the cfe-commits mailing list