diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index b4f964fb5c..64568d2e6f 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -431,6 +431,37 @@ void CodeGenFunction::EmitClassAggrCopyAssignment(llvm::Value *Dest, EmitBlock(AfterFor, true); } +/// GetVTTParameter - Return the VTT parameter that should be passed to a +/// base constructor/destructor with virtual bases. +static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD) { + if (!CGVtableInfo::needsVTTParameter(GD)) { + // This constructor/destructor does not need a VTT parameter. + return 0; + } + + const CXXRecordDecl *RD = cast(CGF.CurFuncDecl)->getParent(); + const CXXRecordDecl *Base = cast(GD.getDecl())->getParent(); + + llvm::Value *VTT; + + uint64_t SubVTTIndex = + CGF.CGM.getVtableInfo().getSubVTTIndex(RD, Base); + assert(SubVTTIndex != 0 && "Sub-VTT index must be greater than zero!"); + + if (CGVtableInfo::needsVTTParameter(CGF.CurGD)) { + // A VTT parameter was passed to the constructor, use it. + VTT = CGF.LoadCXXVTT(); + VTT = CGF.Builder.CreateConstInBoundsGEP1_64(VTT, SubVTTIndex); + } else { + // We're the complete constructor, so get the VTT by name. + VTT = CGF.CGM.getVtableInfo().getVTT(RD); + VTT = CGF.Builder.CreateConstInBoundsGEP2_64(VTT, 0, SubVTTIndex); + } + + return VTT; +} + + /// EmitClassMemberwiseCopy - This routine generates code to copy a class /// object from SrcValue to DestValue. Copying can be either a bitwise copy /// or via a copy constructor call. @@ -438,11 +469,16 @@ void CodeGenFunction::EmitClassMemberwiseCopy( llvm::Value *Dest, llvm::Value *Src, const CXXRecordDecl *ClassDecl, const CXXRecordDecl *BaseClassDecl, QualType Ty) { + CXXCtorType CtorType = Ctor_Complete; + if (ClassDecl) { Dest = GetAddressOfBaseClass(Dest, ClassDecl, BaseClassDecl, /*NullCheckValue=*/false); Src = GetAddressOfBaseClass(Src, ClassDecl, BaseClassDecl, /*NullCheckValue=*/false); + + // We want to call the base constructor. + CtorType = Ctor_Base; } if (BaseClassDecl->hasTrivialCopyConstructor()) { EmitAggregateCopy(Dest, Src, Ty); @@ -451,13 +487,19 @@ void CodeGenFunction::EmitClassMemberwiseCopy( if (CXXConstructorDecl *BaseCopyCtor = BaseClassDecl->getCopyConstructor(getContext(), 0)) { - llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, - Ctor_Complete); + llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(BaseCopyCtor, CtorType); CallArgList CallArgs; // Push the this (Dest) ptr. CallArgs.push_back(std::make_pair(RValue::get(Dest), BaseCopyCtor->getThisType(getContext()))); + // Push the VTT parameter, if necessary. + if (llvm::Value *VTT = + GetVTTParameter(*this, GlobalDecl(BaseCopyCtor, CtorType))) { + QualType T = getContext().getPointerType(getContext().VoidPtrTy); + CallArgs.push_back(std::make_pair(RValue::get(VTT), T)); + } + // Push the Src ptr. CallArgs.push_back(std::make_pair(RValue::get(Src), BaseCopyCtor->getParamDecl(0)->getType())); @@ -787,10 +829,8 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, V = CGF.Builder.CreateConstInBoundsGEP1_64(V, Offset/8); V = CGF.Builder.CreateBitCast(V, BaseClassType->getPointerTo()); - // FIXME: This should always use Ctor_Base as the ctor type! (But that - // causes crashes in tests.) CGF.EmitCXXConstructorCall(BaseInit->getConstructor(), - CtorType, V, + Ctor_Base, V, BaseInit->const_arg_begin(), BaseInit->const_arg_end()); } @@ -1248,6 +1288,7 @@ CodeGenFunction::GenerateCXXAggrDestructorHelper(const CXXDestructorDecl *D, return m; } + void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, @@ -1271,35 +1312,19 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, return; } + llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(D, Type)); llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type); - EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, ArgBeg, ArgEnd); + EmitCXXMemberCall(D, Callee, ReturnValueSlot(), This, VTT, ArgBeg, ArgEnd); } void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD, CXXDtorType Type, llvm::Value *This) { + llvm::Value *VTT = GetVTTParameter(*this, GlobalDecl(DD, Type)); llvm::Value *Callee = CGM.GetAddrOfCXXDestructor(DD, Type); - CallArgList Args; - - // Push the this ptr. - Args.push_back(std::make_pair(RValue::get(This), - DD->getThisType(getContext()))); - - // Add a VTT parameter if necessary. - // FIXME: This should not be a dummy null parameter! - if (Type == Dtor_Base && DD->getParent()->getNumVBases() != 0) { - QualType T = getContext().getPointerType(getContext().VoidPtrTy); - - Args.push_back(std::make_pair(RValue::get(CGM.EmitNullConstant(T)), T)); - } - - // FIXME: We should try to share this code with EmitCXXMemberCall. - - QualType ResultType = DD->getType()->getAs()->getResultType(); - EmitCall(CGM.getTypes().getFunctionInfo(ResultType, Args), Callee, - ReturnValueSlot(), Args, DD); + EmitCXXMemberCall(DD, Callee, ReturnValueSlot(), This, VTT, 0, 0); } llvm::Value * @@ -1395,3 +1420,11 @@ void CodeGenFunction::InitializeVtablePtrsRecursive( // Store address point Builder.CreateStore(VtableAddressPoint, VtableField); } + +llvm::Value *CodeGenFunction::LoadCXXVTT() { + assert((isa(CurFuncDecl) || + isa(CurFuncDecl)) && + "Must be in a C++ ctor or dtor to load the vtt parameter"); + + return Builder.CreateLoad(LocalDeclMap[CXXVTTDecl], "vtt"); +} diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index a36e92559b..e264109f02 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -19,6 +19,7 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, llvm::Value *Callee, ReturnValueSlot ReturnValue, llvm::Value *This, + llvm::Value *VTT, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd) { assert(MD->isInstance() && @@ -32,6 +33,12 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, Args.push_back(std::make_pair(RValue::get(This), MD->getThisType(getContext()))); + // If there is a VTT parameter, emit it. + if (VTT) { + QualType T = getContext().getPointerType(getContext().VoidPtrTy); + Args.push_back(std::make_pair(RValue::get(VTT), T)); + } + // And the rest of the call args EmitCallArgs(Args, FPT, ArgBeg, ArgEnd); @@ -129,7 +136,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, Callee = CGM.GetAddrOfFunction(MD, Ty); } - return EmitCXXMemberCall(MD, Callee, ReturnValue, This, + return EmitCXXMemberCall(MD, Callee, ReturnValue, This, /*VTT=*/0, CE->arg_begin(), CE->arg_end()); } @@ -275,7 +282,7 @@ CodeGenFunction::EmitCXXOperatorMemberCallExpr(const CXXOperatorCallExpr *E, else Callee = CGM.GetAddrOfFunction(MD, Ty); - return EmitCXXMemberCall(MD, Callee, ReturnValue, This, + return EmitCXXMemberCall(MD, Callee, ReturnValue, This, /*VTT=*/0, E->arg_begin() + 1, E->arg_end()); } @@ -726,7 +733,8 @@ void CodeGenFunction::EmitCXXDeleteExpr(const CXXDeleteExpr *E) { /*isVariadic=*/false); llvm::Value *Callee = BuildVirtualCall(Dtor, Dtor_Deleting, Ptr, Ty); - EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, 0, 0); + EmitCXXMemberCall(Dtor, Callee, ReturnValueSlot(), Ptr, /*VTT=*/0, + 0, 0); // The dtor took care of deleting the object. ShouldCallDelete = false; diff --git a/lib/CodeGen/CGVtable.cpp b/lib/CodeGen/CGVtable.cpp index 98fb60a3de..98f3907a67 100644 --- a/lib/CodeGen/CGVtable.cpp +++ b/lib/CodeGen/CGVtable.cpp @@ -211,7 +211,7 @@ public: return VtableComponents; } - llvm::DenseMap &getVBIndex() + llvm::DenseMap &getVBIndex() { return VBIndex; } SavedAdjustmentsVectorTy &getSavedAdjustments() @@ -1209,6 +1209,10 @@ class VTTBuilder { llvm::Constant *ClassVtbl; llvm::LLVMContext &VMContext; + llvm::DenseMap SubVTTIndicies; + + bool GenerateDefinition; + /// BuildVtablePtr - Build up a referene to the given secondary vtable llvm::Constant *BuildVtablePtr(llvm::Constant *Vtable, const CXXRecordDecl *VtableClass, @@ -1268,14 +1272,17 @@ class VTTBuilder { // FIXME: Slightly too many of these for __ZTT8test8_B2 llvm::Constant *init; if (BaseMorallyVirtual) - init = BuildVtablePtr(vtbl, VtblClass, RD, Offset); + init = GenerateDefinition ? + BuildVtablePtr(vtbl, VtblClass, RD, Offset) : 0; else { - init = CGM.getVtableInfo().getCtorVtable(Class, Base, BaseOffset); + init = GenerateDefinition ? + CGM.getVtableInfo().getCtorVtable(Class, Base, BaseOffset) : 0; subvtbl = init; subVtblClass = Base; - init = BuildVtablePtr(init, Class, Base, BaseOffset); + init = GenerateDefinition ? + BuildVtablePtr(init, Class, Base, BaseOffset) : 0; } Inits.push_back(init); } @@ -1294,14 +1301,16 @@ class VTTBuilder { // First comes the primary virtual table pointer... if (MorallyVirtual) { - Vtable = ClassVtbl; + Vtable = GenerateDefinition ? ClassVtbl : 0; VtableClass = Class; } else { - Vtable = CGM.getVtableInfo().getCtorVtable(Class, RD, Offset); + Vtable = GenerateDefinition ? + CGM.getVtableInfo().getCtorVtable(Class, RD, Offset) : 0; VtableClass = RD; } - llvm::Constant *Init = BuildVtablePtr(Vtable, VtableClass, RD, Offset); + llvm::Constant *Init = GenerateDefinition ? + BuildVtablePtr(Vtable, VtableClass, RD, Offset) : 0; Inits.push_back(Init); // then the secondary VTTs.... @@ -1324,6 +1333,10 @@ class VTTBuilder { continue; const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD); uint64_t BaseOffset = Offset + Layout.getBaseClassOffset(Base); + + // Remember the sub-VTT index. + SubVTTIndicies[Base] = Inits.size(); + BuildVTT(Base, BaseOffset, MorallyVirtual); } } @@ -1336,6 +1349,9 @@ class VTTBuilder { const CXXRecordDecl *Base = cast(i->getType()->getAs()->getDecl()); if (i->isVirtual() && !SeenVBase.count(Base)) { + // Remember the sub-VTT index. + SubVTTIndicies[Base] = Inits.size(); + SeenVBase.insert(Base); uint64_t BaseOffset = BLayout.getVBaseClassOffset(Base); BuildVTT(Base, BaseOffset, true); @@ -1346,15 +1362,18 @@ class VTTBuilder { public: VTTBuilder(std::vector &inits, const CXXRecordDecl *c, - CodeGenModule &cgm) + CodeGenModule &cgm, bool GenerateDefinition) : Inits(inits), Class(c), CGM(cgm), BLayout(cgm.getContext().getASTRecordLayout(c)), AddressPoints(*cgm.AddressPoints[c]), - VMContext(cgm.getModule().getContext()) { + VMContext(cgm.getModule().getContext()), + GenerateDefinition(GenerateDefinition) { // First comes the primary virtual table pointer for the complete class... ClassVtbl = CGM.getVtableInfo().getVtable(Class); - Inits.push_back(BuildVtablePtr(ClassVtbl, Class, Class, 0)); + llvm::Constant *Init = GenerateDefinition ? + BuildVtablePtr(ClassVtbl, Class, Class, 0) : 0; + Inits.push_back(Init); // then the secondary VTTs... SecondaryVTTs(Class); @@ -1365,11 +1384,16 @@ public: // and last, the virtual VTTs. VirtualVTTs(Class); } + + llvm::DenseMap &getSubVTTIndicies() { + return SubVTTIndicies; + } }; } llvm::GlobalVariable * CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage, + bool GenerateDefinition, const CXXRecordDecl *RD) { // Only classes that have virtual bases need a VTT. if (RD->getNumVBases() == 0) @@ -1379,23 +1403,36 @@ CGVtableInfo::GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage, CGM.getMangleContext().mangleCXXVTT(RD, OutName); llvm::StringRef Name = OutName.str(); - D1(printf("vtt %s\n", RD->getNameAsCString())); - std::vector inits; - VTTBuilder b(inits, RD, CGM); + llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name); + if (GV == 0 || GV->isDeclaration()) { + const llvm::Type *Int8PtrTy = + llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); - const llvm::Type *Int8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); - const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size()); + std::vector inits; + VTTBuilder b(inits, RD, CGM, GenerateDefinition); + + const llvm::ArrayType *Type = llvm::ArrayType::get(Int8PtrTy, inits.size()); + llvm::Constant *Init = 0; + if (GenerateDefinition) + Init = llvm::ConstantArray::get(Type, inits); + + llvm::GlobalVariable *OldGV = GV; + GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true, + Linkage, Init, Name); + CGM.setGlobalVisibility(GV, RD); + + if (OldGV) { + GV->takeName(OldGV); + llvm::Constant *NewPtr = + llvm::ConstantExpr::getBitCast(GV, OldGV->getType()); + OldGV->replaceAllUsesWith(NewPtr); + OldGV->eraseFromParent(); + } + } - llvm::Constant *Init = llvm::ConstantArray::get(Type, inits); - - llvm::GlobalVariable *VTT = - new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true, - Linkage, Init, Name); - CGM.setGlobalVisibility(VTT, RD); - - return VTT; + return GV; } void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, @@ -1407,7 +1444,7 @@ void CGVtableInfo::GenerateClassData(llvm::GlobalVariable::LinkageTypes Linkage, } Vtable = GenerateVtable(Linkage, /*GenerateDefinition=*/true, RD, RD, 0); - GenerateVTT(Linkage, RD); + GenerateVTT(Linkage, /*GenerateDefinition=*/true, RD); } llvm::GlobalVariable *CGVtableInfo::getVtable(const CXXRecordDecl *RD) { @@ -1428,6 +1465,13 @@ CGVtableInfo::getCtorVtable(const CXXRecordDecl *LayoutClass, LayoutClass, RD, Offset); } +llvm::GlobalVariable *CGVtableInfo::getVTT(const CXXRecordDecl *RD) { + return GenerateVTT(llvm::GlobalValue::ExternalLinkage, + /*GenerateDefinition=*/false, RD); + +} + + void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) { const CXXMethodDecl *MD = cast(GD.getDecl()); const CXXRecordDecl *RD = MD->getParent(); @@ -1443,16 +1487,6 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) { // We don't have the right key function. if (KeyFunction->getCanonicalDecl() != MD->getCanonicalDecl()) return; - - // If the key function is a destructor, we only want to emit the vtable - // once, so do it for the complete destructor. - if (isa(MD) && GD.getDtorType() != Dtor_Complete) - return; - } else { - // If there is no key function, we only want to emit the vtable if we are - // emitting a constructor. - if (!isa(MD) || GD.getCtorType() != Ctor_Complete) - return; } llvm::GlobalVariable::LinkageTypes Linkage; @@ -1479,3 +1513,47 @@ void CGVtableInfo::MaybeEmitVtable(GlobalDecl GD) { } } +bool CGVtableInfo::needsVTTParameter(GlobalDecl GD) { + const CXXMethodDecl *MD = cast(GD.getDecl()); + + // We don't have any virtual bases, just return early. + if (!MD->getParent()->getNumVBases()) + return false; + + // Check if we have a base constructor. + if (isa(MD) && GD.getCtorType() == Ctor_Base) + return true; + + // Check if we have a base destructor. + if (isa(MD) && GD.getDtorType() == Dtor_Base) + return true; + + return false; +} + +uint64_t CGVtableInfo::getSubVTTIndex(const CXXRecordDecl *RD, + const CXXRecordDecl *Base) { + ClassPairTy ClassPair(RD, Base); + + SubVTTIndiciesTy::iterator I = + SubVTTIndicies.find(ClassPair); + if (I != SubVTTIndicies.end()) + return I->second; + + std::vector inits; + VTTBuilder Builder(inits, RD, CGM, /*GenerateDefinition=*/false); + + for (llvm::DenseMap::iterator I = + Builder.getSubVTTIndicies().begin(), + E = Builder.getSubVTTIndicies().end(); I != E; ++I) { + // Insert all indices. + ClassPairTy ClassPair(RD, I->first); + + SubVTTIndicies.insert(std::make_pair(ClassPair, I->second)); + } + + I = SubVTTIndicies.find(ClassPair); + assert(I != SubVTTIndicies.end() && "Did not find index!"); + + return I->second; +} diff --git a/lib/CodeGen/CGVtable.h b/lib/CodeGen/CGVtable.h index eed5b64085..b1b48236e3 100644 --- a/lib/CodeGen/CGVtable.h +++ b/lib/CodeGen/CGVtable.h @@ -93,6 +93,9 @@ private: SavedAdjustmentsTy SavedAdjustments; llvm::DenseSet SavedAdjustmentRecords; + typedef llvm::DenseMap SubVTTIndiciesTy; + SubVTTIndiciesTy SubVTTIndicies; + /// getNumVirtualFunctionPointers - Return the number of virtual function /// pointers in the vtable for a given record decl. uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD); @@ -113,12 +116,22 @@ private: const CXXRecordDecl *RD, uint64_t Offset); llvm::GlobalVariable *GenerateVTT(llvm::GlobalVariable::LinkageTypes Linkage, + bool GenerateDefinition, const CXXRecordDecl *RD); public: CGVtableInfo(CodeGenModule &CGM) : CGM(CGM) { } + /// needsVTTParameter - Return whether the given global decl needs a VTT + /// parameter, which it does if it's a base constructor or destructor with + /// virtual bases. + static bool needsVTTParameter(GlobalDecl GD); + + /// getSubVTTIndex - Return the index of the sub-VTT for the base class of the + /// given record decl. + uint64_t getSubVTTIndex(const CXXRecordDecl *RD, const CXXRecordDecl *Base); + /// getMethodVtableIndex - Return the index (relative to the vtable address /// point) where the function pointer for the given virtual function is /// stored. @@ -144,6 +157,7 @@ public: const CXXRecordDecl *Class, uint64_t Offset); + llvm::GlobalVariable *getVTT(const CXXRecordDecl *RD); void MaybeEmitVtable(GlobalDecl GD); }; diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index f904f043ca..7999721e2c 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -230,26 +230,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, } } -static bool NeedsVTTParameter(GlobalDecl GD) { - const CXXMethodDecl *MD = cast(GD.getDecl()); - - // We don't have any virtual bases, just return early. - if (!MD->getParent()->getNumVBases()) - return false; - - // Check if we have a base constructor. - if (isa(MD) && GD.getCtorType() == Ctor_Base) - return true; - - // Check if we have a base destructor. - if (isa(MD) && GD.getDtorType() == Dtor_Base) - return true; - - return false; -} - -void CodeGenFunction::GenerateCode(GlobalDecl GD, - llvm::Function *Fn) { +void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn) { const FunctionDecl *FD = cast(GD.getDecl()); // Check if we should generate debug info for this function. @@ -271,7 +252,7 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, Args.push_back(std::make_pair(CXXThisDecl, CXXThisDecl->getType())); // Check if we need a VTT parameter as well. - if (NeedsVTTParameter(GD)) { + if (CGVtableInfo::needsVTTParameter(GD)) { // FIXME: The comment about using a fake decl above applies here too. QualType T = getContext().getPointerType(getContext().VoidPtrTy); CXXVTTDecl = diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 273ddcac79..fadb38fcb9 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -728,6 +728,10 @@ public: /// generating code for an C++ member function. llvm::Value *LoadCXXThis(); + /// LoadCXXVTT - Load the VTT parameter to base constructors/destructors have + /// virtual bases. + llvm::Value *LoadCXXVTT(); + /// GetAddressOfBaseClass - This function will add the necessary delta to the /// load of 'this' and returns address of the base class. // FIXME. This currently only does a derived to non-virtual base conversion. @@ -1057,6 +1061,7 @@ public: llvm::Value *Callee, ReturnValueSlot ReturnValue, llvm::Value *This, + llvm::Value *VTT, CallExpr::const_arg_iterator ArgBeg, CallExpr::const_arg_iterator ArgEnd); RValue EmitCXXMemberCallExpr(const CXXMemberCallExpr *E, diff --git a/test/CodeGenCXX/constructor-template.cpp b/test/CodeGenCXX/constructor-template.cpp index a3576fdc72..a3f38a6984 100644 --- a/test/CodeGenCXX/constructor-template.cpp +++ b/test/CodeGenCXX/constructor-template.cpp @@ -44,10 +44,10 @@ int main() { delete node; } -// CHECK-LP64: __ZN4NodeIP12BinomialNodeIiEEC1Ev: +// CHECK-LP64: __ZN4NodeIP12BinomialNodeIiEEC2Ev: // CHECK-LP64: __ZN4ListIP12BinomialNodeIiEEC1Ev: // CHECK-LP64: __ZN4ListIP12BinomialNodeIiEED1Ev: -// CHECK-LP32: __ZN4NodeIP12BinomialNodeIiEEC1Ev: +// CHECK-LP32: __ZN4NodeIP12BinomialNodeIiEEC2Ev: // CHECK-LP32: __ZN4ListIP12BinomialNodeIiEEC1Ev: // CHECK-LP32: __ZN4ListIP12BinomialNodeIiEED1Ev: diff --git a/test/CodeGenCXX/default-constructor-default-argument.cpp b/test/CodeGenCXX/default-constructor-default-argument.cpp index 971757d241..f2c7f6d12a 100644 --- a/test/CodeGenCXX/default-constructor-default-argument.cpp +++ b/test/CodeGenCXX/default-constructor-default-argument.cpp @@ -5,4 +5,4 @@ struct A { A(int x = 2); }; struct B : public A {}; B x; -// CHECK: call void @_ZN1AC1Ei +// CHECK: call void @_ZN1AC2Ei diff --git a/test/CodeGenCXX/virtual-destructor-calls.cpp b/test/CodeGenCXX/virtual-destructor-calls.cpp index ecfcad2320..01ca1442f2 100644 --- a/test/CodeGenCXX/virtual-destructor-calls.cpp +++ b/test/CodeGenCXX/virtual-destructor-calls.cpp @@ -8,15 +8,15 @@ struct B : A { virtual ~B(); }; +// Complete dtor. +// CHECK: define void @_ZN1BD1Ev +// CHECK: call void @_ZN1AD2Ev + // Deleting dtor. // CHECK: define void @_ZN1BD0Ev // CHECK: call void @_ZN1AD2Ev // check: call void @_ZdlPv -// Complete dtor. -// CHECK: define void @_ZN1BD1Ev -// CHECK: call void @_ZN1AD2Ev - // Base dtor. // CHECK: define void @_ZN1BD2Ev // CHECK: call void @_ZN1AD2Ev