]> granicus.if.org Git - clang/commitdiff
[MS ABI] Delegating constructors should not assume they are most derived
authorDavid Majnemer <david.majnemer@gmail.com>
Fri, 13 May 2016 20:05:09 +0000 (20:05 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Fri, 13 May 2016 20:05:09 +0000 (20:05 +0000)
A constructor needs to know whether or not it is most derived in order
to determine if it is responsible for virtual bases.  Delegating
constructors assumed they were most derived.

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

lib/CodeGen/MicrosoftCXXABI.cpp
test/CodeGenCXX/microsoft-abi-structors.cpp

index 0e15f5054d89f3445d7fcb973e42b2203c2ccebf..2e41f934a2b325c2709c3ab7201af038cd40d1d7 100644 (file)
@@ -1467,16 +1467,18 @@ unsigned MicrosoftCXXABI::addImplicitConstructorArgs(
 
   // Add the 'most_derived' argument second if we are variadic or last if not.
   const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>();
-  llvm::Value *MostDerivedArg =
-      llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete);
-  RValue RV = RValue::get(MostDerivedArg);
-  if (MostDerivedArg) {
-    if (FPT->isVariadic())
-      Args.insert(Args.begin() + 1,
-                  CallArg(RV, getContext().IntTy, /*needscopy=*/false));
-    else
-      Args.add(RV, getContext().IntTy);
+  llvm::Value *MostDerivedArg;
+  if (Delegating) {
+    MostDerivedArg = getStructorImplicitParamValue(CGF);
+  } else {
+    MostDerivedArg = llvm::ConstantInt::get(CGM.Int32Ty, Type == Ctor_Complete);
   }
+  RValue RV = RValue::get(MostDerivedArg);
+  if (FPT->isVariadic())
+    Args.insert(Args.begin() + 1,
+                CallArg(RV, getContext().IntTy, /*needscopy=*/false));
+  else
+    Args.add(RV, getContext().IntTy);
 
   return 1;  // Added one arg.
 }
index 3fb97b9a363228bbf79f1dd9f39a4212187bc3f0..a576f0c3d7e37c49aa837362b476ae57b76bfef4 100644 (file)
@@ -7,7 +7,7 @@
 // RUN: FileCheck --check-prefix DTORS3 %s < %t
 // RUN: FileCheck --check-prefix DTORS4 %s < %t
 //
-// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti | FileCheck --check-prefix DTORS-X64 %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -mconstructor-aliases -triple=x86_64-pc-win32 -fno-rtti -std=c++11 | FileCheck --check-prefix DTORS-X64 %s
 
 namespace basic {
 
@@ -443,6 +443,20 @@ void g() { new MoveOnly(f()); }
 // CHECK: store {{.*}} @"\01??_7MoveOnly@implicit_copy_vtable@@6B@"
 }
 
+namespace delegating_ctor {
+struct Y {};
+struct X : virtual Y {
+  X(int);
+  X();
+};
+X::X(int) : X() {}
+}
+// CHECK: define x86_thiscallcc %"struct.delegating_ctor::X"* @"\01??0X@delegating_ctor@@QAE@H@Z"(
+// CHECK:  %[[is_most_derived_addr:.*]] = alloca i32, align 4
+// CHECK:  store i32 %is_most_derived, i32* %[[is_most_derived_addr]]
+// CHECK:  %[[is_most_derived:.*]] = load i32, i32* %[[is_most_derived_addr]]
+// CHECK:  call x86_thiscallcc {{.*}}* @"\01??0X@delegating_ctor@@QAE@XZ"({{.*}} i32 %[[is_most_derived]])
+
 // Dtor thunks for classes in anonymous namespaces should be internal, not
 // linkonce_odr.
 namespace {
@@ -471,4 +485,3 @@ class G {
 extern void testG() {
   G g;
 }
-