Skip to content

Commit d4af25b

Browse files
committed
[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.
1 parent ebe5c66 commit d4af25b

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10415,7 +10415,16 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
1041510415

1041610416
typedef bool result_type;
1041710417
bool failed() { return false; }
10418+
bool checkConst(QualType QT) {
10419+
if (QT.isConstQualified()) {
10420+
Info.FFDiag(E, diag::note_constexpr_modify_const_type) << QT;
10421+
return false;
10422+
}
10423+
return true;
10424+
}
1041810425
bool found(APValue &Subobj, QualType SubobjType) {
10426+
if (!checkConst(SubobjType))
10427+
return false;
1041910428
// FIXME: Reject the cases where [basic.life]p8 would not permit the
1042010429
// old name of the object to be used to name the new object.
1042110430
unsigned SubobjectSize = 1;

clang/test/AST/ByteCode/placement-new.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,3 +376,42 @@ constexpr int N = [] // expected-error {{must be initialized by a constant expre
376376
return s.a[0];
377377
}();
378378
#endif
379+
380+
constexpr int modify_const_variable() {
381+
const int a = 10;
382+
new ((int *)&a) int(12); // both-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}}
383+
return a;
384+
}
385+
static_assert(modify_const_variable()); // both-error {{not an integral constant expression}} \
386+
// both-note {{in call to}}
387+
388+
typedef const int T0;
389+
typedef T0 T1;
390+
constexpr T1 modify_const_variable_td() {
391+
T1 a = 10;
392+
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}}
393+
return a;
394+
}
395+
static_assert(modify_const_variable_td()); // both-error {{not an integral constant expression}} \
396+
// both-note {{in call to}}
397+
398+
template<typename T>
399+
constexpr T modify_const_variable_tmpl() {
400+
T a = 10;
401+
new ((int *)&a) int(12); // both-note {{modification of object of const-qualified type 'const int' is not allowed in a constant expression}}
402+
return a;
403+
}
404+
static_assert(modify_const_variable_tmpl<const int>()); // both-error {{not an integral constant expression}} \
405+
// both-note {{in call to}}
406+
407+
namespace ModifyMutableMember {
408+
struct S {
409+
mutable int a {10};
410+
};
411+
constexpr int modify_mutable_member() {
412+
const S s;
413+
new ((int *)&s.a) int(12);
414+
return s.a;
415+
}
416+
static_assert(modify_mutable_member() == 12);
417+
}

0 commit comments

Comments
 (0)