]> granicus.if.org Git - clang/commitdiff
[ms-abi] Always generate complete constructors in the Microsoft C++ ABI
authorReid Kleckner <reid@kleckner.net>
Mon, 13 Jan 2014 22:57:31 +0000 (22:57 +0000)
committerReid Kleckner <reid@kleckner.net>
Mon, 13 Jan 2014 22:57:31 +0000 (22:57 +0000)
Fixes PR18435, where we generated a base ctor instead of a complete
ctor, and so failed to construct virtual bases when constructing the
complete object.

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

lib/CodeGen/CGCXX.cpp
lib/CodeGen/CGClass.cpp
test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp

index a17b5132a862b0dd673b0217f2e090b38b795084..ed8c80500b83f75831c9e2a5d6ce4f23c070e93a 100644 (file)
@@ -190,11 +190,13 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
 
 void CodeGenModule::EmitCXXConstructor(const CXXConstructorDecl *ctor,
                                        CXXCtorType ctorType) {
-  // The complete constructor is equivalent to the base constructor
-  // for classes with no virtual bases.  Try to emit it as an alias.
-  if (getTarget().getCXXABI().hasConstructorVariants() &&
-      !ctor->getParent()->getNumVBases() &&
-      (ctorType == Ctor_Complete || ctorType == Ctor_Base)) {
+  if (!getTarget().getCXXABI().hasConstructorVariants()) {
+    // If there are no constructor variants, always emit the complete destructor.
+    ctorType = Ctor_Complete;
+  } else if (!ctor->getParent()->getNumVBases() &&
+             (ctorType == Ctor_Complete || ctorType == Ctor_Base)) {
+    // The complete constructor is equivalent to the base constructor
+    // for classes with no virtual bases.  Try to emit it as an alias.
     bool ProducedAlias =
         !TryEmitDefinitionAsAlias(GlobalDecl(ctor, Ctor_Complete),
                                   GlobalDecl(ctor, Ctor_Base), true);
index 701a7d341d12dde9b7838c9957ad7033e987a6c4..8143fb9ca5d83921d64b7f957276d9850441e625 100644 (file)
@@ -699,6 +699,10 @@ void CodeGenFunction::EmitConstructorBody(FunctionArgList &Args) {
   const CXXConstructorDecl *Ctor = cast<CXXConstructorDecl>(CurGD.getDecl());
   CXXCtorType CtorType = CurGD.getCtorType();
 
+  assert((CGM.getTarget().getCXXABI().hasConstructorVariants() ||
+          CtorType == Ctor_Complete) &&
+         "can only generate complete ctor for this ABI");
+
   // Before we go any further, try the complete->base constructor
   // delegation optimization.
   if (CtorType == Ctor_Complete && IsConstructorDelegationValid(Ctor) &&
index 7c223ca0a7723fe6d4761442e143b4e3e7b5b34e..1014ae402f36e79d72602328471e033e7df5a0e5 100644 (file)
@@ -312,3 +312,30 @@ D::~D() {
 }
 
 }
+
+namespace test2 {
+struct A { A(); };
+struct B : virtual A { B() {} };
+struct C : B, A { C() {} };
+
+// PR18435: Order mattered here.  We were generating code for the delegating
+// call to B() from C().
+void callC() { C x; }
+
+// CHECK-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::C"* @"\01??0C@test2@@QAE@XZ"
+// CHECK:           (%"struct.test2::C"* returned %this, i32 %is_most_derived)
+// CHECK: br i1
+//   Virtual bases
+// CHECK: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK: br label
+//   Non-virtual bases
+// CHECK: call x86_thiscallcc %"struct.test2::B"* @"\01??0B@test2@@QAE@XZ"(%"struct.test2::B"* %{{.*}}, i32 0)
+// CHECK: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK: ret
+
+// CHECK2-LABEL: define linkonce_odr x86_thiscallcc %"struct.test2::B"* @"\01??0B@test2@@QAE@XZ"
+// CHECK2:           (%"struct.test2::B"* returned %this, i32 %is_most_derived)
+// CHECK2: call x86_thiscallcc %"struct.test2::A"* @"\01??0A@test2@@QAE@XZ"(%"struct.test2::A"* %{{.*}})
+// CHECK2: ret
+
+}