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(); 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 +// CIR: %[[P:.*]] = cir.alloca !cir.ptr, !cir.ptr>, ["p", init] +// CIR: cir.store %[[ARG0]], %[[P]] : !cir.ptr, !cir.ptr> +// CIR: %[[SIZE:.*]] = cir.const #cir.int<1> : !u64i +// CIR: %[[PTR:.*]] = cir.load{{.*}} %[[P]] : !cir.ptr>, !cir.ptr +// CIR: %[[PTR_A:.*]] = cir.cast bitcast %[[PTR]] : !cir.ptr -> !cir.ptr +// CIR: cir.call @_ZN1AC1Ev(%[[PTR_A]]) : (!cir.ptr) -> () + +// 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]])