From 1094641bc029b7ca6ac9f18c5ff5b028037e1a6f Mon Sep 17 00:00:00 2001 From: "Oleksandr T." Date: Mon, 9 Dec 2024 18:47:38 +0200 Subject: [PATCH] [Clang] allow usage of placement new operator in [[msvc::constexpr]] context outside of the std namespace (#119153) Fixes #74924 --- clang/docs/ReleaseNotes.rst | 3 +++ clang/lib/AST/ExprConstant.cpp | 4 +++- clang/test/AST/ms-constexpr-new.cpp | 13 +++++++++++++ clang/test/SemaCXX/ms-constexpr-new.cpp | 11 +++++++++-- 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 clang/test/AST/ms-constexpr-new.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 7d846f1d447d..c040a0d80d0d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -527,6 +527,9 @@ Attribute Changes in Clang - The ``target_version`` attribute is now only supported for AArch64 and RISC-V architectures. +- Clang now permits the usage of the placement new operator in ``[[msvc::constexpr]]`` + context outside of the std namespace. (#GH74924) + Improvements to Clang's diagnostics ----------------------------------- diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index 86313fbde0b4..eed277deb4ac 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -10172,7 +10172,9 @@ bool PointerExprEvaluator::VisitCXXNewExpr(const CXXNewExpr *E) { return false; IsNothrow = true; } else if (OperatorNew->isReservedGlobalPlacementOperator()) { - if (Info.CurrentCall->isStdFunction() || Info.getLangOpts().CPlusPlus26) { + if (Info.CurrentCall->isStdFunction() || Info.getLangOpts().CPlusPlus26 || + (Info.CurrentCall->CanEvalMSConstexpr && + OperatorNew->hasAttr())) { if (!EvaluatePointer(E->getPlacementArg(0), Result, Info)) return false; if (Result.Designator.Invalid) diff --git a/clang/test/AST/ms-constexpr-new.cpp b/clang/test/AST/ms-constexpr-new.cpp new file mode 100644 index 000000000000..4b534cf02076 --- /dev/null +++ b/clang/test/AST/ms-constexpr-new.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fms-compatibility -fms-compatibility-version=19.33 -std=c++20 -ast-dump %s | FileCheck %s + +// CHECK: used operator new +// CHECK: MSConstexprAttr 0x{{[0-9a-f]+}} +[[nodiscard]] [[msvc::constexpr]] inline void* __cdecl operator new(decltype(sizeof(void*)), void* p) noexcept { return p; } + +// CHECK: used constexpr construct_at +// CHECK: AttributedStmt 0x{{[0-9a-f]+}} +// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} +// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} +constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new (p) int(v); } +constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 42; } +static_assert(check_construct_at()); diff --git a/clang/test/SemaCXX/ms-constexpr-new.cpp b/clang/test/SemaCXX/ms-constexpr-new.cpp index 30567740b2ec..096014be803e 100644 --- a/clang/test/SemaCXX/ms-constexpr-new.cpp +++ b/clang/test/SemaCXX/ms-constexpr-new.cpp @@ -12,5 +12,12 @@ namespace std { } } -constexpr bool check_construct_at() { int x; return *std::construct_at(&x, 42) == 42; } -static_assert(check_construct_at()); +constexpr bool check_std_construct_at() { int x; return *std::construct_at(&x, 42) == 42; } +static_assert(check_std_construct_at()); + +constexpr int* construct_at(int* p, int v) { [[msvc::constexpr]] return ::new (p) int(v); } // unsupported-error {{constexpr function never produces a constant expression}} \ + // unsupported-warning {{unknown attribute 'constexpr' ignored}} \ + // unsupported-note 2{{this placement new expression is not supported in constant expressions before C++2c}} +constexpr bool check_construct_at() { int x; return *construct_at(&x, 42) == 42; } // unsupported-note {{in call to 'construct_at(&x, 42)'}} +static_assert(check_construct_at()); // unsupported-error {{static assertion expression is not an integral constant expression}}\ + // unsupported-note {{in call to 'check_construct_at()'}}