[cfe-commits] r131395 - in /cfe/trunk: lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/new.cpp
John McCall
rjmccall at apple.com
Sun May 15 18:05:12 PDT 2011
Author: rjmccall
Date: Sun May 15 20:05:12 2011
New Revision: 131395
URL: http://llvm.org/viewvc/llvm-project?rev=131395&view=rev
Log:
Don't actually emit calls to the reserved global placement new and delete
operators; their semantics are guaranteed by the language.
If someone wants to argue that freestanding compiles shouldn't recognize
this, I might be convinceable.
Modified:
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/test/CodeGenCXX/new.cpp
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=131395&r1=131394&r2=131395&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Sun May 15 20:05:12 2011
@@ -444,33 +444,14 @@
E->arg_begin(), E->arg_end());
}
-/// Check whether the given operator new[] is the global placement
-/// operator new[].
-static bool IsPlacementOperatorNewArray(ASTContext &Ctx,
- const FunctionDecl *Fn) {
- // Must be in global scope. Note that allocation functions can't be
- // declared in namespaces.
- if (!Fn->getDeclContext()->getRedeclContext()->isFileContext())
- return false;
-
- // Signature must be void *operator new[](size_t, void*).
- // The size_t is common to all operator new[]s.
- if (Fn->getNumParams() != 2)
- return false;
-
- CanQualType ParamType = Ctx.getCanonicalType(Fn->getParamDecl(1)->getType());
- return (ParamType == Ctx.VoidPtrTy);
-}
-
static CharUnits CalculateCookiePadding(CodeGenFunction &CGF,
const CXXNewExpr *E) {
if (!E->isArray())
return CharUnits::Zero();
- // No cookie is required if the new operator being used is
- // ::operator new[](size_t, void*).
- const FunctionDecl *OperatorNew = E->getOperatorNew();
- if (IsPlacementOperatorNewArray(CGF.getContext(), OperatorNew))
+ // No cookie is required if the operator new[] being used is the
+ // reserved placement operator new[].
+ if (E->getOperatorNew()->isReservedGlobalPlacementOperator())
return CharUnits::Zero();
return CGF.CGM.getCXXABI().GetArrayCookieSize(E);
@@ -1073,11 +1054,19 @@
EmitCallArg(allocatorArgs, *placementArg, placementArg->getType());
}
- // Emit the allocation call.
- RValue RV =
- EmitCall(CGM.getTypes().getFunctionInfo(allocatorArgs, allocatorType),
- CGM.GetAddrOfFunction(allocator), ReturnValueSlot(),
- allocatorArgs, allocator);
+ // Emit the allocation call. If the allocator is a global placement
+ // operator, just "inline" it directly.
+ RValue RV;
+ if (allocator->isReservedGlobalPlacementOperator()) {
+ assert(allocatorArgs.size() == 2);
+ RV = allocatorArgs[1].RV;
+ // TODO: kill any unnecessary computations done for the size
+ // argument.
+ } else {
+ RV = EmitCall(CGM.getTypes().getFunctionInfo(allocatorArgs, allocatorType),
+ CGM.GetAddrOfFunction(allocator), ReturnValueSlot(),
+ allocatorArgs, allocator);
+ }
// Emit a null check on the allocation result if the allocation
// function is allowed to return null (because it has a non-throwing
@@ -1122,7 +1111,8 @@
// If there's an operator delete, enter a cleanup to call it if an
// exception is thrown.
EHScopeStack::stable_iterator operatorDeleteCleanup;
- if (E->getOperatorDelete()) {
+ if (E->getOperatorDelete() &&
+ !E->getOperatorDelete()->isReservedGlobalPlacementOperator()) {
EnterNewDeleteCleanup(*this, E, allocation, allocSize, allocatorArgs);
operatorDeleteCleanup = EHStack.stable_begin();
}
Modified: cfe/trunk/test/CodeGenCXX/new.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/new.cpp?rev=131395&r1=131394&r2=131395&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/new.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/new.cpp Sun May 15 20:05:12 2011
@@ -1,12 +1,16 @@
// RUN: %clang_cc1 -triple x86_64-unknown-unknown %s -emit-llvm -o - | FileCheck %s
-#include <stddef.h>
+
+typedef __typeof__(sizeof(0)) size_t;
void t1() {
int* a = new int;
}
-// Placement.
-void* operator new(size_t, void*) throw();
+// Declare the reserved placement operators.
+void *operator new(size_t, void*) throw();
+void operator delete(void*, void*) throw();
+void *operator new[](size_t, void*) throw();
+void operator delete[](void*, void*) throw();
void t2(int* a) {
int* b = new (a) int;
@@ -163,3 +167,45 @@
delete new bool;
// CHECK: ret void
}
+
+namespace test15 {
+ struct A { A(); ~A(); };
+
+ // CHECK: define void @_ZN6test155test0EPv(
+ // CHECK: [[P:%.*]] = load i8*
+ // CHECK-NEXT: icmp eq i8* [[P]], null
+ // CHECK-NEXT: br i1
+ // CHECK: [[T0:%.*]] = bitcast i8* [[P]] to [[A:%.*]]*
+ // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[T0]])
+ void test0(void *p) {
+ new (p) A();
+ }
+
+ // CHECK: define void @_ZN6test155test1EPv(
+ // CHECK: [[P:%.*]] = load i8*
+ // CHECK-NEXT: icmp eq i8* [[P]], null
+ // CHECK-NEXT: br i1
+ // CHECK: [[T0:%.*]] = bitcast i8* [[P]] to [[A:%.*]]*
+ // CHECK: [[T1:%.*]] = getelementptr inbounds [[A]]* [[T0]],
+ // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[T1]])
+ void test1(void *p) {
+ new (p) A[5];
+ }
+
+ // TODO: it's okay if all these size calculations get dropped.
+ // FIXME: maybe we should try to throw on overflow?
+ // CHECK: define void @_ZN6test155test2EPvi(
+ // CHECK: [[N:%.*]] = load i32*
+ // CHECK-NEXT: [[T0:%.*]] = sext i32 [[N]] to i64
+ // CHECK-NEXT: [[T1:%.*]] = icmp slt i64 [[T0]], 0
+ // CHECK-NEXT: [[T2:%.*]] = select i1 [[T1]], i64 -1, i64 [[T0]]
+ // CHECK-NEXT: [[P:%.*]] = load i8*
+ // CHECK-NEXT: icmp eq i8* [[P]], null
+ // CHECK-NEXT: br i1
+ // CHECK: [[T0:%.*]] = bitcast i8* [[P]] to [[A:%.*]]*
+ // CHECK: [[T1:%.*]] = getelementptr inbounds [[A]]* [[T0]],
+ // CHECK-NEXT: call void @_ZN6test151AC1Ev([[A]]* [[T1]])
+ void test2(void *p, int n) {
+ new (p) A[n];
+ }
+}
More information about the cfe-commits
mailing list