https://github.com/andykaylor created 
https://github.com/llvm/llvm-project/pull/169436

This upstreams the code to support reserved placement new calls.

>From 884f4e5a09d6c28ae84eb95764acd61154d69f56 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <[email protected]>
Date: Mon, 24 Nov 2025 16:57:55 -0800
Subject: [PATCH] [CIR] Upstream reserved placement new handling

This upstreams the code to support reserved placement new calls.
---
 clang/lib/CIR/CodeGen/Address.h          |  6 ++++
 clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp  | 23 ++++++++++++--
 clang/test/CIR/CodeGen/placement-new.cpp | 40 ++++++++++++++++++++++++
 3 files changed, 67 insertions(+), 2 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/placement-new.cpp

diff --git a/clang/lib/CIR/CodeGen/Address.h b/clang/lib/CIR/CodeGen/Address.h
index c8ce530a7b0d3..a425eebe99082 100644
--- a/clang/lib/CIR/CodeGen/Address.h
+++ b/clang/lib/CIR/CodeGen/Address.h
@@ -77,6 +77,12 @@ class Address {
     return Address(newPtr, getElementType(), getAlignment());
   }
 
+  /// Return address with different alignment, but same pointer and element
+  /// type.
+  Address withAlignment(clang::CharUnits newAlignment) const {
+    return Address(getPointer(), getElementType(), newAlignment);
+  }
+
   /// Return address with different element type, a bitcast pointer, and
   /// the same alignment.
   Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const;
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
index dbf20db8bfb8d..81fd8ee106107 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprCXX.cpp
@@ -806,8 +806,27 @@ mlir::Value CIRGenFunction::emitCXXNewExpr(const 
CXXNewExpr *e) {
   Address allocation = Address::invalid();
   CallArgList allocatorArgs;
   if (allocator->isReservedGlobalPlacementOperator()) {
-    cgm.errorNYI(e->getSourceRange(),
-                 "emitCXXNewExpr: reserved global placement operator");
+    // If the allocator is a global placement operator, just
+    // "inline" it directly.
+    assert(e->getNumPlacementArgs() == 1);
+    const Expr *arg = *e->placement_arguments().begin();
+
+    LValueBaseInfo baseInfo;
+    allocation = emitPointerWithAlignment(arg, &baseInfo);
+
+    // The pointer expression will, in many cases, be an opaque void*.
+    // In these cases, discard the computed alignment and use the
+    // formal alignment of the allocated type.
+    if (baseInfo.getAlignmentSource() != AlignmentSource::Decl)
+      allocation = allocation.withAlignment(allocAlign);
+
+    // Set up allocatorArgs for the call to operator delete if it's not
+    // the reserved global operator.
+    if (e->getOperatorDelete() &&
+        !e->getOperatorDelete()->isReservedGlobalPlacementOperator()) {
+      cgm.errorNYI(e->getSourceRange(),
+                   "emitCXXNewExpr: reserved placement new with delete");
+    }
   } else {
     const FunctionProtoType *allocatorType =
         allocator->getType()->castAs<FunctionProtoType>();
diff --git a/clang/test/CIR/CodeGen/placement-new.cpp 
b/clang/test/CIR/CodeGen/placement-new.cpp
new file mode 100644
index 0000000000000..7ceaa0a359e1f
--- /dev/null
+++ b/clang/test/CIR/CodeGen/placement-new.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -fclangir 
-emit-cir -o %t.cir
+// RUN: FileCheck --input-file=%t.cir -check-prefix=CIR %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -fclangir 
-emit-llvm -o %t-cir.ll
+// RUN: FileCheck --input-file=%t-cir.ll -check-prefix=LLVM %s
+// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu %s -emit-llvm 
-o %t.ll
+// RUN: FileCheck --input-file=%t.ll -check-prefix=OGCG %s
+
+typedef __typeof__(sizeof(0)) size_t;
+
+// Declare the reserved placement operators.
+void *operator new(size_t, void*) throw();
+
+struct A { A(); ~A(); };
+
+void test_reserved_placement_new(void *p) {
+  new (p) A();
+}
+
+// CIR-LABEL:   cir.func dso_local @_Z27test_reserved_placement_newPv(
+// CIR-SAME:                                   %[[ARG0:.*]]: !cir.ptr<!void>
+// CIR:           %[[P:.*]] = cir.alloca !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>, ["p", init]
+// CIR:           cir.store %[[ARG0]], %[[P]] : !cir.ptr<!void>, 
!cir.ptr<!cir.ptr<!void>>
+// CIR:           %[[SIZE:.*]] = cir.const #cir.int<1> : !u64i
+// CIR:           %[[PTR:.*]] = cir.load{{.*}} %[[P]] : 
!cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
+// CIR:           %[[PTR_A:.*]] = cir.cast bitcast %[[PTR]] : !cir.ptr<!void> 
-> !cir.ptr<!rec_A>
+// CIR:           cir.call @_ZN1AC1Ev(%[[PTR_A]]) : (!cir.ptr<!rec_A>) -> ()
+
+// LLVM-LABEL: define dso_local void @_Z27test_reserved_placement_newPv(
+// LLVM-SAME:                                   ptr %[[ARG0:.*]]
+// LLVM:         %[[P:.*]] = alloca ptr
+// LLVM:         store ptr %[[ARG0:.*]], ptr %[[P]]
+// LLVM:         %[[PTR:.*]] = load ptr, ptr %[[P]]
+// LLVM:         call void @_ZN1AC1Ev(ptr %[[PTR]])
+
+// OGCG-LABEL: define dso_local void @_Z27test_reserved_placement_newPv(
+// OGCG-SAME:                                   ptr {{.*}} %[[ARG0:.*]]
+// OGCG:         %[[P:.*]] = alloca ptr
+// OGCG:         store ptr %[[ARG0:.*]], ptr %[[P]]
+// OGCG:         %[[PTR:.*]] = load ptr, ptr %[[P]]
+// OGCG:         call void @_ZN1AC1Ev(ptr {{.*}} %[[PTR]])

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to