[clang] 1094641 - [Clang] allow usage of placement new operator in [[msvc::constexpr]] context outside of the std namespace (#119153)

via cfe-commits cfe-commits at lists.llvm.org
Mon Dec 9 08:47:42 PST 2024


Author: Oleksandr T.
Date: 2024-12-09T18:47:38+02:00
New Revision: 1094641bc029b7ca6ac9f18c5ff5b028037e1a6f

URL: https://github.com/llvm/llvm-project/commit/1094641bc029b7ca6ac9f18c5ff5b028037e1a6f
DIFF: https://github.com/llvm/llvm-project/commit/1094641bc029b7ca6ac9f18c5ff5b028037e1a6f.diff

LOG: [Clang] allow usage of placement new operator in [[msvc::constexpr]] context outside of the std namespace (#119153)

Fixes #74924

Added: 
    clang/test/AST/ms-constexpr-new.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/ExprConstant.cpp
    clang/test/SemaCXX/ms-constexpr-new.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 7d846f1d447d16..c040a0d80d0df3 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 86313fbde0b4a7..eed277deb4ac16 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<MSConstexprAttr>())) {
       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 00000000000000..4b534cf0207644
--- /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]+}} <col:17, col:23>
+[[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]+}} <col:46, col:88>
+// CHECK-NEXT: MSConstexprAttr 0x{{[0-9a-f]+}} <col:48, col:54>
+// CHECK-NEXT: ReturnStmt 0x{{[0-9a-f]+}} <col:66, col:88>
+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 30567740b2ecbb..096014be803e77 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()'}}


        


More information about the cfe-commits mailing list