[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