diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -9358,8 +9358,7 @@ bool IsNothrow = false; bool IsPlacement = false; if (OperatorNew->isReservedGlobalPlacementOperator() && - Info.CurrentCall->isStdFunction() && !E->isArray()) { - // FIXME Support array placement new. + Info.CurrentCall->isStdFunction()) { assert(E->getNumPlacementArgs() == 1); if (!EvaluatePointer(E->getPlacementArg(0), Result, Info)) return false; diff --git a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp --- a/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp +++ b/clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp @@ -96,14 +96,28 @@ return a == 42; } +void *operator new[](std::size_t, void *p) { return p; } +constexpr bool no_array_placement_new_in_user_code() { // expected-error {{never produces a constant expression}} + int a[3]; + new (&a) int[3](); // expected-note {{call to placement 'operator new[]'}} + return a[0] == 0 && a[1] == 0 && a[2] == 0; +} + namespace std { constexpr bool placement_new_in_stdlib() { int a; new (&a) int(42); return a == 42; } + + constexpr bool array_placement_new_in_stdlib() { + int a[3]; + new (&a) int[3]{42, 43, 44}; + return a[0] == 42 && a[1] == 43 && a[2] == 44; + } } static_assert(std::placement_new_in_stdlib()); +static_assert(std::array_placement_new_in_stdlib()); namespace std { template