Skip to content

Commit 5c4225b

Browse files
committed
Address Aarons's feedback
1 parent f8a15eb commit 5c4225b

File tree

6 files changed

+66
-22
lines changed

6 files changed

+66
-22
lines changed

clang/include/clang/Basic/DiagnosticASTKinds.td

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,9 +333,10 @@ def note_constexpr_new : Note<
333333
def note_constexpr_new_non_replaceable : Note<
334334
"call to %select{placement|class-specific}0 %1">;
335335
def note_constexpr_new_placement : Note<
336-
"this placement new expression is not yet supported in constant expressions">;
336+
"this placement new expression is not supported in constant expressions "
337+
"%select{|before C++2c}0">;
337338
def note_constexpr_placement_new_wrong_type : Note<
338-
"placement new would change type of storage from %0 to %1">;
339+
"placement new would change type of storage from %0 to %1">;
339340
def note_constexpr_new_negative : Note<
340341
"cannot allocate array; evaluated array bound %0 is negative">;
341342
def note_constexpr_new_too_large : Note<

clang/lib/AST/ExprConstant.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10009,7 +10009,7 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
1000910009
bool IsNothrow = false;
1001010010
bool IsPlacement = false;
1001110011

10012-
if (E->getNumPlacementArgs() && E->getNumPlacementArgs() == 1 &&
10012+
if (E->getNumPlacementArgs() == 1 &&
1001310013
E->getPlacementArg(0)->getType()->isNothrowT()) {
1001410014
// The only new-placement list we support is of the form (std::nothrow).
1001510015
//
@@ -10025,17 +10025,23 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) {
1002510025
if (!EvaluateLValue(E->getPlacementArg(0), Nothrow, Info))
1002610026
return false;
1002710027
IsNothrow = true;
10028-
} else if (OperatorNew->isReservedGlobalPlacementOperator() &&
10029-
(Info.CurrentCall->isStdFunction() ||
10030-
Info.getLangOpts().CPlusPlus26)) {
10031-
if (!EvaluatePointer(E->getPlacementArg(0), Result, Info))
10032-
return false;
10033-
if (Result.Designator.Invalid)
10028+
} else if (OperatorNew->isReservedGlobalPlacementOperator()) {
10029+
if (Info.CurrentCall->isStdFunction() || Info.getLangOpts().CPlusPlus26) {
10030+
if (!EvaluatePointer(E->getPlacementArg(0), Result, Info))
10031+
return false;
10032+
if (Result.Designator.Invalid)
10033+
return false;
10034+
TargetType = E->getPlacementArg(0)->getType();
10035+
IsPlacement = true;
10036+
} else {
10037+
Info.FFDiag(E, diag::note_constexpr_new_placement)
10038+
<< /*C++26 feature*/ 1 << E->getSourceRange();
1003410039
return false;
10035-
TargetType = E->getPlacementArg(0)->getType();
10036-
IsPlacement = true;
10040+
}
1003710041
} else if (E->getNumPlacementArgs()) {
10038-
return Error(E, diag::note_constexpr_new_placement);
10042+
Info.FFDiag(E, diag::note_constexpr_new_placement)
10043+
<< /*Unsupported*/ 0 << E->getSourceRange();
10044+
return false;
1003910045
} else if (!OperatorNew->isReplaceableGlobalAllocationFunction()) {
1004010046
Info.FFDiag(E, diag::note_constexpr_new_non_replaceable)
1004110047
<< isa<CXXMethodDecl>(OperatorNew) << OperatorNew;

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ namespace std {
245245
namespace PlacementNew {
246246
constexpr int foo() { // both-error {{never produces a constant expression}}
247247
char c[sizeof(int)];
248-
new (c) int{12}; // ref-note {{this placement new expression is not yet supported in constant expressions}} \
248+
new (c) int{12}; // ref-note {{this placement new expression is not supported in constant expressions}} \
249249
// expected-note {{subexpression not valid in a constant expression}}
250250
return 0;
251251
}
@@ -309,7 +309,7 @@ namespace placement_new_delete {
309309
constexpr bool bad(int which) {
310310
switch (which) {
311311
case 0:
312-
delete new (placement_new_arg{}) int; // ref-note {{this placement new expression is not yet supported in constant expression}} \
312+
delete new (placement_new_arg{}) int; // ref-note {{this placement new expression is not supported in constant expressions}} \
313313
// expected-note {{subexpression not valid in a constant expression}}
314314
break;
315315

@@ -328,7 +328,7 @@ namespace placement_new_delete {
328328
case 4:
329329
// FIXME: This technically follows the standard's rules, but it seems
330330
// unreasonable to expect implementations to support this.
331-
delete new (std::align_val_t{64}) Overaligned; // ref-note {{placement new expression is not yet supported}} \
331+
delete new (std::align_val_t{64}) Overaligned; // ref-note {{this placement new expression is not supported in constant expressions }} \
332332
// expected-note {{subexpression not valid in a constant expression}}
333333
break;
334334
}

clang/test/SemaCXX/constant-expression-cxx2a.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -994,7 +994,7 @@ namespace placement_new_delete {
994994
constexpr bool bad(int which) {
995995
switch (which) {
996996
case 0:
997-
delete new (placement_new_arg{}) int; // expected-note {{this placement new expression is not yet supported in constant expressions}}
997+
delete new (placement_new_arg{}) int; // expected-note {{this placement new expression is not supported in constant expressions}}
998998
break;
999999

10001000
case 1:
@@ -1012,7 +1012,7 @@ namespace placement_new_delete {
10121012
case 4:
10131013
// FIXME: This technically follows the standard's rules, but it seems
10141014
// unreasonable to expect implementations to support this.
1015-
delete new (std::align_val_t{64}) Overaligned; // expected-note {{placement new expression is not yet supported}}
1015+
delete new (std::align_val_t{64}) Overaligned; // expected-note {{this placement new expression is not supported in constant expressions}}
10161016
break;
10171017
}
10181018

clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ void *operator new(std::size_t, void *p) { return p; }
9494
void* operator new[] (std::size_t, void* p) {return p;}
9595
constexpr bool no_placement_new_in_user_code() { // cxx20-error {{constexpr function never produces a constant expression}}
9696
int a;
97-
new (&a) int(42); // cxx20-note {{this placement new expression is not yet supported in constant expressions}}
97+
new (&a) int(42); // cxx20-note {{this placement new expression is not supported in constant expressions before C++2c}}
9898
return a == 42;
9999
}
100100

clang/test/SemaCXX/cxx2c-constexpr-placement-new.cpp

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ consteval int ok() {
1717
return 0;
1818
}
1919

20-
consteval int conversion() { // expected-error {{consteval function never produces a constant expression}}
20+
consteval int conversion() {
2121
int i;
2222
new (static_cast<void*>(&i)) float(0);
2323
// expected-note@-1 {{placement new would change type of storage from 'int' to 'float'}}
@@ -41,7 +41,7 @@ consteval int array1() {
4141
return 0;
4242
}
4343

44-
consteval int array2() { // expected-error {{consteval function never produces a constant expression}}
44+
consteval int array2() {
4545
int i[1];
4646
new (&i) int[2];
4747
//expected-note@-1 {{placement new would change type of storage from 'int[1]' to 'int[2]'}}
@@ -71,8 +71,45 @@ consteval void alloc_err() {
7171

7272

7373
int a = ok();
74-
int c = indeterminate(); // expected-error {{call to consteval function 'placement_new::indeterminate' is not a constant expression}} \
74+
int b = conversion(); // expected-error {{call to consteval function 'conversion' is not a constant expression}} \
75+
// expected-note {{in call to 'conversion()'}}
76+
int c = indeterminate(); // expected-error {{call to consteval function 'indeterminate' is not a constant expression}} \
7577
// expected-note {{in call to 'indeterminate()'}}
7678
int d = array1();
79+
int e = array2(); // expected-error {{call to consteval function 'array2' is not a constant expression}} \
80+
// expected-note {{in call to 'array2()'}}
7781
int alloc1 = (alloc(), 0);
78-
int alloc2 = (alloc_err(), 0); // expected-error {{call to consteval function 'placement_new::alloc_err' is not a constant expression}}
82+
int alloc2 = (alloc_err(), 0); // expected-error {{call to consteval function 'alloc_err' is not a constant expression}}
83+
84+
constexpr int *intptr() {
85+
return new int;
86+
}
87+
88+
constexpr bool yay() {
89+
int *ptr = new (intptr()) int(42);
90+
bool ret = *ptr == 42;
91+
delete ptr;
92+
return ret;
93+
}
94+
static_assert(yay());
95+
96+
constexpr bool blah() {
97+
int *ptr = new (intptr()) int[3]{ 1, 2, 3 }; // expected-note {{placement new would change type of storage from 'int' to 'int[3]'}}
98+
bool ret = ptr[0] == 1 && ptr[1] == 2 && ptr[2] == 3;
99+
delete [] ptr;
100+
return ret;
101+
}
102+
static_assert(blah()); // expected-error {{not an integral constant expression}} \
103+
// expected-note {{in call to 'blah()'}}
104+
105+
constexpr int *get_indeterminate() {
106+
int *evil;
107+
return evil; // expected-note {{read of uninitialized object is not allowed in a constant expression}}
108+
}
109+
110+
constexpr bool bleh() {
111+
int *ptr = new (get_indeterminate()) int; // expected-note {{in call to 'get_indeterminate()'}}
112+
return true;
113+
}
114+
static_assert(bleh()); // expected-error {{not an integral constant expression}} \
115+
// expected-note {{in call to 'bleh()'}}

0 commit comments

Comments
 (0)