diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 12 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 4 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp | 27 |
3 files changed, 38 insertions, 5 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index a17b5132a86..ed8c80500b8 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -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); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 701a7d341d1..8143fb9ca5d 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -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) && diff --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index 7c223ca0a77..1014ae402f3 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -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 + +} |