aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2009-05-31 21:53:59 +0000
committerAnders Carlsson <andersca@mac.com>2009-05-31 21:53:59 +0000
commitd3fd6bad1249d3f34d71b73e2333fab0db51cce4 (patch)
tree338f949f88e5c30bef2bacb1db0140c6bcf0cead
parent627a3e573f1d9f0429d62c7ceb742a21cdabfce0 (diff)
Improve irgen of 'new' further.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72677 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/Type.h3
-rw-r--r--lib/CodeGen/CGCXX.cpp32
-rw-r--r--test/CodeGenCXX/new.cpp24
3 files changed, 50 insertions, 9 deletions
diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h
index 15c6b6654f..2bdea34a5f 100644
--- a/include/clang/AST/Type.h
+++ b/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/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp
index febfbacf7c..2cc9d0390f 100644
--- a/lib/CodeGen/CGCXX.cpp
+++ b/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/test/CodeGenCXX/new.cpp b/test/CodeGenCXX/new.cpp
index bf959c95c8..e3d1ec1df6 100644
--- a/test/CodeGenCXX/new.cpp
+++ b/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);
+}