summaryrefslogtreecommitdiffstats
path: root/clang/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
commit7f9c92a9a0740c2e198ae3a38770b59150555ea0 (patch)
tree00928edca348bfd85e66495833d671c7cc77d299 /clang/test/CodeGenCXX/exceptions.cpp
parent2cc3f17a26417de82ccd8f3e381f30afff78afed (diff)
downloadbcm5719-llvm-7f9c92a9a0740c2e198ae3a38770b59150555ea0.tar.gz
bcm5719-llvm-7f9c92a9a0740c2e198ae3a38770b59150555ea0.zip
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. llvm-svn: 114145
Diffstat (limited to 'clang/test/CodeGenCXX/exceptions.cpp')
-rw-r--r--clang/test/CodeGenCXX/exceptions.cpp69
1 files changed, 60 insertions, 9 deletions
diff --git a/clang/test/CodeGenCXX/exceptions.cpp b/clang/test/CodeGenCXX/exceptions.cpp
index 2337eee071f..c60f2a1b45d 100644
--- a/clang/test/CodeGenCXX/exceptions.cpp
+++ b/clang/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);
}
-
}
OpenPOWER on IntegriCloud