https://github.com/mariusdr updated 
https://github.com/llvm/llvm-project/pull/132460

>From d4af25b14fb21f50c3771cce4595ca5c1bb920a7 Mon Sep 17 00:00:00 2001
From: marius doerner <mariu...@users.noreply.github.com>
Date: Fri, 21 Mar 2025 20:19:57 +0100
Subject: [PATCH 1/2] [clang] Placement new error when modifying consts

Raise an error when placement new is used to modify a const-qualified
variable in a constexpr function.
---
 clang/lib/AST/ExprConstant.cpp            |  9 ++++++
 clang/test/AST/ByteCode/placement-new.cpp | 39 +++++++++++++++++++++++
 2 files changed, 48 insertions(+)

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);
+}

>From b596108cb5f66f81bdc1a0809f91cfa9b4dad0a6 Mon Sep 17 00:00:00 2001
From: marius doerner <mariu...@users.noreply.github.com>
Date: Sun, 23 Mar 2025 09:21:34 +0100
Subject: [PATCH 2/2] Move tests from Ast/Bytecode to SemaCxx

---
 clang/test/AST/ByteCode/placement-new.cpp     | 39 -------------------
 .../SemaCXX/cxx2c-constexpr-placement-new.cpp | 39 +++++++++++++++++++
 2 files changed, 39 insertions(+), 39 deletions(-)

diff --git a/clang/test/AST/ByteCode/placement-new.cpp 
b/clang/test/AST/ByteCode/placement-new.cpp
index 9b12c9f2b1714..c353162a7aab0 100644
--- a/clang/test/AST/ByteCode/placement-new.cpp
+++ b/clang/test/AST/ByteCode/placement-new.cpp
@@ -376,42 +376,3 @@ 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);
-}
diff --git a/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp 
b/clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp
index a29fb981cedbf..053b42c837e53 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); // 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);
+}

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to