diff options
author | Anders Carlsson <andersca@mac.com> | 2009-05-31 21:53:59 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2009-05-31 21:53:59 +0000 |
commit | cba81fc4de83b0ffa430c94b9ad88b8cf7bb1622 (patch) | |
tree | 2ddec7164ec58fdf2fa005bd07735ad812304cff | |
parent | 96c012ff8b89dc0ae97db225ccee68e862caed59 (diff) | |
download | bcm5719-llvm-cba81fc4de83b0ffa430c94b9ad88b8cf7bb1622.tar.gz bcm5719-llvm-cba81fc4de83b0ffa430c94b9ad88b8cf7bb1622.zip |
Improve irgen of 'new' further.
llvm-svn: 72677
-rw-r--r-- | clang/include/clang/AST/Type.h | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 32 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/new.cpp | 24 |
3 files changed, 50 insertions, 9 deletions
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h index 15c6b6654f6..2bdea34a5f2 100644 --- a/clang/include/clang/AST/Type.h +++ b/clang/include/clang/AST/Type.h @@ -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(); } diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index febfbacf7cc..2cc9d0390f3 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -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, diff --git a/clang/test/CodeGenCXX/new.cpp b/clang/test/CodeGenCXX/new.cpp index bf959c95c85..e3d1ec1df6c 100644 --- a/clang/test/CodeGenCXX/new.cpp +++ b/clang/test/CodeGenCXX/new.cpp @@ -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); +} |