summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorPiotr Padlewski <prazek@google.com>2015-10-02 22:12:40 +0000
committerPiotr Padlewski <prazek@google.com>2015-10-02 22:12:40 +0000
commit276a78d860cbe376202d3251a1f490b0da7f2f7e (patch)
treeef6ac2f6a4e0b0b69d1d75731586decdb58f5fc4 /clang
parentdc9b2cfc5013684456ec7d632eaa2edf7c030f2b (diff)
downloadbcm5719-llvm-276a78d860cbe376202d3251a1f490b0da7f2f7e.tar.gz
bcm5719-llvm-276a78d860cbe376202d3251a1f490b0da7f2f7e.zip
Emiting invariant.group.barrier for ctors bugfix
Ensure that the vptr store in the most-derived constructor is not behind an invariant group barrier. Previously, the base-most vptr store would be the one behind no barrier, and that could result in the creator of the object thinking it had the base-most vtable. This bug caused clang call pure virtual functions when called from constructor body. http://reviews.llvm.org/D13373 llvm-svn: 249197
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/CodeGen/CGClass.cpp21
-rw-r--r--clang/test/CodeGenCXX/invariant.group-for-vptrs.cpp3
-rw-r--r--clang/test/CodeGenCXX/strict-vtable-pointers.cpp45
3 files changed, 43 insertions, 26 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 6394d1ff17d..5c08f67d402 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1375,13 +1375,14 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
assert(BaseCtorContinueBB);
}
- bool BaseVPtrsInitialized = false;
+ llvm::Value *const OldThis = CXXThisValue;
// Virtual base initializers first.
for (; B != E && (*B)->isBaseInitializer() && (*B)->isBaseVirtual(); B++) {
- CXXCtorInitializer *BaseInit = *B;
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ isInitializerOfDynamicClass(*B))
+ CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
EmitBaseInitializer(*this, ClassDecl, *B, CtorType);
- BaseVPtrsInitialized |= BaseInitializerUsesThis(getContext(),
- BaseInit->getInit());
}
if (BaseCtorContinueBB) {
@@ -1393,15 +1394,15 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
// Then, non-virtual base initializers.
for (; B != E && (*B)->isBaseInitializer(); B++) {
assert(!(*B)->isBaseVirtual());
+
+ if (CGM.getCodeGenOpts().StrictVTablePointers &&
+ CGM.getCodeGenOpts().OptimizationLevel > 0 &&
+ isInitializerOfDynamicClass(*B))
+ CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
EmitBaseInitializer(*this, ClassDecl, *B, CtorType);
- BaseVPtrsInitialized |= isInitializerOfDynamicClass(*B);
}
- // Pointer to this requires to be passed through invariant.group.barrier
- // only if we've initialized any base vptrs.
- if (CGM.getCodeGenOpts().StrictVTablePointers &&
- CGM.getCodeGenOpts().OptimizationLevel > 0 && BaseVPtrsInitialized)
- CXXThisValue = Builder.CreateInvariantGroupBarrier(LoadCXXThis());
+ CXXThisValue = OldThis;
InitializeVTablePointers(ClassDecl);
diff --git a/clang/test/CodeGenCXX/invariant.group-for-vptrs.cpp b/clang/test/CodeGenCXX/invariant.group-for-vptrs.cpp
index 7e85fa20d5d..ca737ee23fb 100644
--- a/clang/test/CodeGenCXX/invariant.group-for-vptrs.cpp
+++ b/clang/test/CodeGenCXX/invariant.group-for-vptrs.cpp
@@ -56,9 +56,8 @@ void testInternallyVisible(bool p) {
// Checking D::D()
// CHECK-LABEL: define linkonce_odr void @_ZN1DC2Ev(
-
-// CHECK: call void @_ZN1AC2Ev(%struct.A*
// CHECK: = call i8* @llvm.invariant.group.barrier(i8*
+// CHECK: call void @_ZN1AC2Ev(%struct.A*
// CHECK: store {{.*}} !invariant.group ![[D_MD]]
// Checking B::B()
diff --git a/clang/test/CodeGenCXX/strict-vtable-pointers.cpp b/clang/test/CodeGenCXX/strict-vtable-pointers.cpp
index 3120a581127..38cb2b488db 100644
--- a/clang/test/CodeGenCXX/strict-vtable-pointers.cpp
+++ b/clang/test/CodeGenCXX/strict-vtable-pointers.cpp
@@ -136,26 +136,43 @@ struct DynamicBase1;
struct DynamicDerived;
+
// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN14DynamicDerivedC2Ev(
-// CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(
-// CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[DynamicDerived:.*]]* %[[THIS0:.*]] to i8*
+// CHECK-CTORS: %[[THIS0:.*]] = load %[[DynamicDerived:.*]]*, %[[DynamicDerived]]** {{.*}}
+// CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[DynamicDerived:.*]]* %[[THIS0]] to i8*
// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS1:.*]])
-// CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2:.*]] to %[[DynamicDerived]]*
-// CHECK-CTORS: %[[THIS4:.*]] = bitcast %struct.DynamicDerived* %[[THIS3:.*]] to i32 (...)***
-// CHECK-CTORS: store {{.*}} %[[THIS4:.*]]
+// CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2]] to %[[DynamicDerived]]*
+// CHECK-CTORS: %[[THIS4:.*]] = bitcast %[[DynamicDerived]]* %2 to %[[DynamicBase:.*]]*
+// CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(%[[DynamicBase]]* %[[THIS4]])
+
+// CHECK-CTORS: %[[THIS5:.*]] = bitcast %struct.DynamicDerived* %[[THIS0]] to i32 (...)***
+// CHECK-CTORS: store {{.*}} %[[THIS5]]
// CHECK-CTORS-LABEL: }
struct DynamicDerivedMultiple;
-// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleC2Ev
-// CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(
+// CHECK-CTORS-LABEL: define linkonce_odr void @_ZN22DynamicDerivedMultipleC2Ev(
+
+// CHECK-CTORS: %[[THIS0:.*]] = load %[[CLASS:.*]]*, %[[CLASS]]** {{.*}}
+// CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[CLASS:.*]]* %[[THIS0]] to i8*
+// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS1]])
+// CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2]] to %[[CLASS]]*
+// CHECK-CTORS: %[[THIS4:.*]] = bitcast %[[CLASS]]* %[[THIS3]] to %[[BASE_CLASS:.*]]*
+// CHECK-CTORS: call void @_ZN12DynamicBase1C2Ev(%[[BASE_CLASS]]* %[[THIS4]])
+
+// CHECK-CTORS: call i8* @llvm.invariant.group.barrier(
+
+// CHECK-CTORS: call void @_ZN12DynamicBase2C2Ev(
// CHECK-CTORS-NOT: @llvm.invariant.group.barrier
-// CHECK-CTORS-LABEL: call void @_ZN12DynamicBase2C2Ev(
-// CHECK-CTORS: %[[THIS1:.*]] = bitcast %[[CLASS:.*]]* %[[THIS0:.*]] to i8*
-// CHECK-CTORS: %[[THIS2:.*]] = call i8* @llvm.invariant.group.barrier(i8* %[[THIS1:.*]])
-// CHECK-CTORS: %[[THIS3:.*]] = bitcast i8* %[[THIS2:.*]] to %[[CLASS]]*
-// CHECK-CTORS-NOT: invariant.group.barrier
-// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i64 0, i64 2)
-// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i64 0, i64 6)
+
+
+// CHECK-CTORS: %[[THIS10:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i32 (...)***
+// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i64 0, i64 2) {{.*}} %[[THIS10]]
+// CHECK-CTORS: %[[THIS11:.*]] = bitcast %struct.DynamicDerivedMultiple* %[[THIS0]] to i8*
+// CHECK-CTORS: %[[THIS_ADD:.*]] = getelementptr inbounds i8, i8* %[[THIS11]], i64 16
+// CHECK-CTORS: %[[THIS12:.*]] = bitcast i8* %[[THIS_ADD]] to i32 (...)***
+
+
+// CHECK-CTORS: store {{.*}} @_ZTV22DynamicDerivedMultiple, i64 0, i64 6) {{.*}} %[[THIS12]]
// CHECK-CTORS-LABEL: }
struct DynamicFromStatic;
OpenPOWER on IntegriCloud