]> granicus.if.org Git - clang/commitdiff
Emiting invariant.group.barrier for ctors bugfix
authorPiotr Padlewski <prazek@google.com>
Fri, 2 Oct 2015 22:12:40 +0000 (22:12 +0000)
committerPiotr Padlewski <prazek@google.com>
Fri, 2 Oct 2015 22:12:40 +0000 (22:12 +0000)
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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@249197 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGClass.cpp
test/CodeGenCXX/invariant.group-for-vptrs.cpp
test/CodeGenCXX/strict-vtable-pointers.cpp

index 6394d1ff17dd2ea333ba50ba14b2081d559bcc2d..5c08f67d4029db8b818e50d3064f17b0a4b7c39c 100644 (file)
@@ -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);
 
index 7e85fa20d5d491d73dd4699acda0d17fb2c8ed28..ca737ee23fb4b3c655d5b29e652792db59b8dda1 100644 (file)
@@ -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()
index 3120a581127e3d857a09666ad08475aaaa3fddb5..38cb2b488db98fcc62364693b1bc51bac08c098e 100644 (file)
@@ -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;