]> granicus.if.org Git - clang/commitdiff
Improve irgen of 'new' further.
authorAnders Carlsson <andersca@mac.com>
Sun, 31 May 2009 21:53:59 +0000 (21:53 +0000)
committerAnders Carlsson <andersca@mac.com>
Sun, 31 May 2009 21:53:59 +0000 (21:53 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72677 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Type.h
lib/CodeGen/CGCXX.cpp
test/CodeGenCXX/new.cpp

index 15c6b6654f68abfe0a92f5496754ffa2b415a144..2bdea34a5f2da810f72e0ae5c7bca40ca0e8b788 100644 (file)
@@ -1225,6 +1225,9 @@ public:
     assert(i < NumExceptions && "Invalid exception number!");
     return exception_begin()[i];
   }
+  bool hasEmptyExceptionSpec() const { 
+    return hasExceptionSpec() && getNumExceptions() == 0;
+  }
 
   bool isVariadic() const { return getSubClassData(); }
   unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
index febfbacf7cc9b84f7c2c096d5ce3eb799bd56ac2..2cc9d0390f3c4ec3e1d255edd18a600096f158f4 100644 (file)
@@ -285,11 +285,23 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
              CGM.GetAddrOfFunction(GlobalDecl(NewFD)),
              NewArgs, NewFD);
 
-  llvm::Value *NewPtr = Builder.CreateBitCast(RV.getScalarVal(), 
-                                              ConvertType(E->getType()));
-
+  // If an allocation function is declared with an empty exception specification
+  // it returns null to indicate failure to allocate storage. [expr.new]p13.
+  // (We don't need to check for null when there's no new initializer and
+  // we're allocating a POD type).
+  bool NullCheckResult = NewFTy->hasEmptyExceptionSpec() &&
+    !(AllocType->isPODType() && !E->hasInitializer());
+
+  if (NullCheckResult) {
+    ErrorUnsupported(E, "new expr that needs to be null checked");
+    return llvm::UndefValue::get(ConvertType(E->getType()));
+  }
+  
+  llvm::Value *NewPtr = 
+    Builder.CreateBitCast(RV.getScalarVal(), ConvertType(E->getType()));
+  
   if (AllocType->isPODType()) {
-    if (E->getNumConstructorArgs() != 0) {
+    if (E->hasInitializer()) {
       assert(E->getNumConstructorArgs() == 1 && 
              "Can only have one argument to initializer of POD type.");
 
@@ -302,12 +314,16 @@ llvm::Value *CodeGenFunction::EmitCXXNewExpr(const CXXNewExpr *E) {
       else
         EmitAggExpr(Init, NewPtr, AllocType.isVolatileQualified());
     }
+  } else {
+    // Call the constructor.    
+    CXXConstructorDecl *Ctor = E->getConstructor();
     
-    return NewPtr;
+    EmitCXXConstructorCall(Ctor, Ctor_Complete, NewPtr, 
+                           E->constructor_arg_begin(), 
+                           E->constructor_arg_end());
   }
-  
-  ErrorUnsupported(E, "new expression with non-POD type");
-  return llvm::UndefValue::get(ConvertType(E->getType()));
+
+  return NewPtr;
 }
 
 static bool canGenerateCXXstructor(const CXXRecordDecl *RD, 
index bf959c95c851dfce47e73592dd8a4b668858d2af..e3d1ec1df6c9ba6267b0c05d3c55f89eba5e1144 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: clang-cc %s -emit-llvm -o %t
+// RUN: clang-cc %s -emit-llvm -o %t &&
 
 void t1() {
   int* a = new int;
@@ -15,6 +15,7 @@ struct S {
   int a;
 };
 
+// POD types.
 void t3() {
   int *a = new int(10);
   _Complex int* b = new _Complex int(10i);
@@ -23,3 +24,24 @@ void t3() {
   s.a = 10;
   S *sp = new S(s);
 }
+
+// Non-POD
+struct T {
+  T();
+  int a;
+};
+
+void t4() {
+  // RUN: grep "call void @_ZN1TC1Ev" %t | count 1 &&
+  T *t = new T;
+}
+
+struct T2 {
+  int a;
+  T2(int, int);
+};
+
+void t5() { 
+  // RUN: grep "call void @_ZN2T2C1Eii" %t | count 1 
+  T2 *t2 = new T2(10, 10);
+}