aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenCXX/exceptions.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2010-09-17 00:50:28 +0000
committerJohn McCall <rjmccall@apple.com>2010-09-17 00:50:28 +0000
commit3019c444c672938c57f5573840071ecd73425ee7 (patch)
treeb638ccc0e22a7087da29add22019968b984491e5 /test/CodeGenCXX/exceptions.cpp
parente5a37f48388c7e4cc081f44d13a4910bfa56cd35 (diff)
When emitting a new-expression inside a conditional expression,
the cleanup might not be dominated by the allocation code. In this case, we have to store aside all the delete arguments in case we need them later. There's room for optimization here in cases where we end up not actually needing the cleanup in different branches (or being able to pop it after the initialization code). Also make sure we only call this operator delete along the path where we actually allocated something. Fixes rdar://problem/8439196. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114145 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/exceptions.cpp')
-rw-r--r--test/CodeGenCXX/exceptions.cpp69
1 files changed, 60 insertions, 9 deletions
diff --git a/test/CodeGenCXX/exceptions.cpp b/test/CodeGenCXX/exceptions.cpp
index 2337eee071..c60f2a1b45 100644
--- a/test/CodeGenCXX/exceptions.cpp
+++ b/test/CodeGenCXX/exceptions.cpp
@@ -164,26 +164,78 @@ namespace test2 {
namespace test3 {
struct A {
- A(int); A(int, int); ~A();
+ A(int); A(int, int); A(const A&); ~A();
void *p;
- void *operator new(size_t, void*, void*);
- void operator delete(void*, void*, void*);
+ void *operator new(size_t, void*, double);
+ void operator delete(void*, void*, double);
};
+ void *foo();
+ double bar();
+ A makeA(), *makeAPtr();
+
A *a() {
// CHECK: define [[A:%.*]]* @_ZN5test31aEv()
// CHECK: [[FOO:%.*]] = call i8* @_ZN5test33fooEv()
- // CHECK: [[BAR:%.*]] = call i8* @_ZN5test33barEv()
- // CHECK: [[NEW:%.*]] = call i8* @_ZN5test31AnwEmPvS1_(i64 8, i8* [[FOO]], i8* [[BAR]])
+ // CHECK: [[BAR:%.*]] = call double @_ZN5test33barEv()
+ // CHECK: [[NEW:%.*]] = call i8* @_ZN5test31AnwEmPvd(i64 8, i8* [[FOO]], double [[BAR]])
// CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
// CHECK-NEXT: invoke void @_ZN5test31AC1Ei([[A]]* [[CAST]], i32 5)
// CHECK: ret [[A]]* [[CAST]]
- // CHECK: invoke void @_ZN5test31AdlEPvS1_S1_(i8* [[NEW]], i8* [[FOO]], i8* [[BAR]])
+ // CHECK: invoke void @_ZN5test31AdlEPvS1_d(i8* [[NEW]], i8* [[FOO]], double [[BAR]])
// CHECK: call void @_ZSt9terminatev()
- extern void *foo(), *bar();
-
return new(foo(),bar()) A(5);
}
+
+ // rdar://problem/8439196
+ A *b(bool cond) {
+
+ // CHECK: define [[A:%.*]]* @_ZN5test31bEb(i1 zeroext
+ // CHECK: [[SAVED0:%.*]] = alloca i8*
+ // CHECK-NEXT: [[SAVED1:%.*]] = alloca i8*
+ // CHECK-NEXT: [[CLEANUPACTIVE:%.*]] = alloca i1
+ // CHECK-NEXT: [[TMP:%.*]] = alloca [[A]], align 8
+ // CHECK: [[TMPACTIVE:%.*]] = alloca i1
+ // CHECK-NEXT: store i1 false, i1* [[TMPACTIVE]]
+ // CHECK-NEXT: store i1 false, i1* [[CLEANUPACTIVE]]
+
+ // CHECK: [[COND:%.*]] = trunc i8 {{.*}} to i1
+ // CHECK-NEXT: br i1 [[COND]]
+ return (cond ?
+
+ // CHECK: [[FOO:%.*]] = call i8* @_ZN5test33fooEv()
+ // CHECK-NEXT: [[NEW:%.*]] = call i8* @_ZN5test31AnwEmPvd(i64 8, i8* [[FOO]], double [[CONST:.*]])
+ // CHECK-NEXT: store i8* [[NEW]], i8** [[SAVED0]]
+ // CHECK-NEXT: store i8* [[FOO]], i8** [[SAVED1]]
+ // CHECK-NEXT: store i1 true, i1* [[CLEANUPACTIVE]]
+ // CHECK-NEXT: [[CAST:%.*]] = bitcast i8* [[NEW]] to [[A]]*
+ // CHECK-NEXT: invoke void @_ZN5test35makeAEv([[A]]* sret [[TMP]])
+ // CHECK: store i1 true, i1* [[TMPACTIVE]]
+ // CHECK-NEXT: invoke void @_ZN5test31AC1ERKS0_([[A]]* [[CAST]], [[A]]* [[TMP]])
+ // CHECK: store i1 false, i1* [[CLEANUPACTIVE]]
+ // CHECK-NEXT: br label
+ // -> cond.end
+ new(foo(),10.0) A(makeA()) :
+
+ // CHECK: [[MAKE:%.*]] = invoke [[A]]* @_ZN5test38makeAPtrEv()
+ // CHECK: br label
+ // -> cond.end
+ makeAPtr());
+
+ // cond.end:
+ // CHECK: [[RESULT:%.*]] = phi [[A]]* {{.*}}[[CAST]]{{.*}}[[MAKE]]
+ // CHECK-NEXT: [[ISACTIVE:%.*]] = load i1* [[TMPACTIVE]]
+ // CHECK-NEXT: br i1 [[ISACTIVE]]
+ // CHECK: invoke void @_ZN5test31AD1Ev
+ // CHECK: ret [[A]]* [[RESULT]]
+
+ // in the EH path:
+ // CHECK: [[ISACTIVE:%.*]] = load i1* [[CLEANUPACTIVE]]
+ // CHECK-NEXT: br i1 [[ISACTIVE]]
+ // CHECK: [[V0:%.*]] = load i8** [[SAVED0]]
+ // CHECK-NEXT: [[V1:%.*]] = load i8** [[SAVED1]]
+ // CHECK-NEXT: invoke void @_ZN5test31AdlEPvS1_d(i8* [[V0]], i8* [[V1]], double [[CONST]])
+ }
}
namespace test4 {
@@ -206,5 +258,4 @@ namespace test4 {
return new(foo(),bar()) A(5);
}
-
}