diff options
author | John McCall <rjmccall@apple.com> | 2010-09-17 02:31:44 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-09-17 02:31:44 +0000 |
commit | 7e1dff7a68a4d00e71debafa7f5c259473091746 (patch) | |
tree | 42975cabf3daa3f75cc7a1c414b556af09d21889 /test/CodeGenCXX/constructor-init.cpp | |
parent | 7a16997c34c18212eb9166f88c6fdd4684b09c07 (diff) |
Currently we're initializing the vtable pointers of a class only after
the bases are completely initialized. This won't work --- base
initializer expressions can rely on the vtables having been set up.
Check for uses of 'this' in the initializers and force a vtable
initialization if found.
This might not be good enough; we might need to extend this to handle
the possibility of arbitrary code finding an external reference to this
(not yet completely-constructed!) object and accessing through it,
in which case we'll probably find ourselves doing a lot more unnecessary
stores.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@114153 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/constructor-init.cpp')
-rw-r--r-- | test/CodeGenCXX/constructor-init.cpp | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/test/CodeGenCXX/constructor-init.cpp b/test/CodeGenCXX/constructor-init.cpp index 284b8b5938..d610fd5ad8 100644 --- a/test/CodeGenCXX/constructor-init.cpp +++ b/test/CodeGenCXX/constructor-init.cpp @@ -81,6 +81,38 @@ void f() { // CHECK: ret void } +// Make sure we initialize the vtable pointer if it's required by a +// base initializer. +namespace InitVTable { + struct A { A(int); }; + struct B : A { + virtual int foo(); + B(); + B(int); + }; + + // CHECK: define void @_ZN10InitVTable1BC2Ev( + // CHECK: [[T0:%.*]] = bitcast [[B:%.*]]* [[THIS:%.*]] to i8*** + // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]] + // CHECK: [[VTBL:%.*]] = load i32 ([[B]]*)*** {{%.*}} + // CHECK-NEXT: [[FNP:%.*]] = getelementptr inbounds i32 ([[B]]*)** [[VTBL]], i64 0 + // CHECK-NEXT: [[FN:%.*]] = load i32 ([[B]]*)** [[FNP]] + // CHECK-NEXT: [[ARG:%.*]] = call i32 [[FN]]([[B]]* [[THIS]]) + // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* %1, i32 [[ARG]]) + // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* [[THIS]] to i8*** + // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]] + // CHECK-NEXT: ret void + B::B() : A(foo()) {} + + // CHECK: define void @_ZN10InitVTable1BC2Ei( + // CHECK: [[ARG:%.*]] = add nsw i32 {{%.*}}, 5 + // CHECK-NEXT: call void @_ZN10InitVTable1AC2Ei({{.*}}* {{%.*}}, i32 [[ARG]]) + // CHECK-NEXT: [[T0:%.*]] = bitcast [[B]]* {{%.*}} to i8*** + // CHECK-NEXT: store i8** getelementptr inbounds ([3 x i8*]* @_ZTVN10InitVTable1BE, i64 0, i64 2), i8*** [[T0]] + // CHECK-NEXT: ret void + B::B(int x) : A(x + 5) {} +} + template<typename T> struct X { X(const X &); |