summaryrefslogtreecommitdiffstats
path: root/test/CodeGenCXX/static-init.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2012-03-30 04:25:14 +0000
committerJohn McCall <rjmccall@apple.com>2012-03-30 04:25:14 +0000
commit9993cc7b56b6bcb73914d707eb3afb29c2f85db8 (patch)
tree46ac281b8b532082545f34ef3b8ee433e722ab17 /test/CodeGenCXX/static-init.cpp
parent56ea377bc58a3a821da917599ed26c6b37b9727c (diff)
When emitting a static local variable in C++, handle
the case that the variable already exists. Partly this is just protection against people making crazy declarations with custom asm labels or extern "C" names that intentionally collide with the manglings of such variables, but the main reason is that we can actually emit a static local variable twice with the requirement that it match up. There may be other cases with (e.g.) the various nested functions, but the main exemplar is with constructor variants, where we can be forced into double-emitting the function body under certain circumstances like (currently) the presence of virtual bases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153723 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/static-init.cpp')
-rw-r--r--test/CodeGenCXX/static-init.cpp50
1 files changed, 50 insertions, 0 deletions
diff --git a/test/CodeGenCXX/static-init.cpp b/test/CodeGenCXX/static-init.cpp
index a96cb7ac8e..ca47428fe2 100644
--- a/test/CodeGenCXX/static-init.cpp
+++ b/test/CodeGenCXX/static-init.cpp
@@ -79,3 +79,53 @@ namespace union_static_local {
c::main();
}
}
+
+// rdar://problem/11091093
+// Static variables should be consistent across constructor
+// or destructor variants.
+namespace test2 {
+ struct A {
+ A();
+ ~A();
+ };
+
+ struct B : virtual A {
+ B();
+ ~B();
+ };
+
+ // If we ever implement this as a delegate ctor call, just change
+ // this to take variadic arguments or something.
+ extern int foo();
+ B::B() {
+ static int x = foo();
+ }
+ // CHECK: define void @_ZN5test21BC1Ev
+ // CHECK: load atomic i8* bitcast (i64* @_ZGVZN5test21BC1EvE1x to i8*) acquire,
+ // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZN5test21BC1EvE1x)
+ // CHECK: [[T0:%.*]] = call i32 @_ZN5test23fooEv()
+ // CHECK: store i32 [[T0]], i32* @_ZZN5test21BC1EvE1x,
+ // CHECK: call void @__cxa_guard_release(i64* @_ZGVZN5test21BC1EvE1x)
+
+ // CHECK: define void @_ZN5test21BC2Ev
+ // CHECK: load atomic i8* bitcast (i64* @_ZGVZN5test21BC1EvE1x to i8*) acquire,
+ // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZN5test21BC1EvE1x)
+ // CHECK: [[T0:%.*]] = call i32 @_ZN5test23fooEv()
+ // CHECK: store i32 [[T0]], i32* @_ZZN5test21BC1EvE1x,
+ // CHECK: call void @__cxa_guard_release(i64* @_ZGVZN5test21BC1EvE1x)
+
+ // This is just for completeness, because we actually emit this
+ // using a delegate dtor call.
+ B::~B() {
+ static int y = foo();
+ }
+ // CHECK: define void @_ZN5test21BD1Ev(
+ // CHECK: call void @_ZN5test21BD2Ev(
+
+ // CHECK: define void @_ZN5test21BD2Ev(
+ // CHECK: load atomic i8* bitcast (i64* @_ZGVZN5test21BD1EvE1y to i8*) acquire,
+ // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZN5test21BD1EvE1y)
+ // CHECK: [[T0:%.*]] = call i32 @_ZN5test23fooEv()
+ // CHECK: store i32 [[T0]], i32* @_ZZN5test21BD1EvE1y,
+ // CHECK: call void @__cxa_guard_release(i64* @_ZGVZN5test21BD1EvE1y)
+}