diff options
Diffstat (limited to 'clang/lib/CodeGen')
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 24 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 216 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGDecl.cpp | 1 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprAgg.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 59 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 83 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 9 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenTypes.h | 5 |
8 files changed, 337 insertions, 69 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index c562602d96b..d683b899022 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -244,6 +244,15 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) { return arrangeFreeFunctionType(prototype, MD); } +bool CodeGenTypes::inheritingCtorHasParams( + const InheritedConstructor &Inherited, CXXCtorType Type) { + // Parameters are unnecessary if we're constructing a base class subobject + // and the inherited constructor lives in a virtual base. + return Type == Ctor_Complete || + !Inherited.getShadowDecl()->constructsVirtualBase() || + !Target.getCXXABI().hasConstructorVariants(); + } + const CGFunctionInfo & CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, StructorType Type) { @@ -252,9 +261,16 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; argTypes.push_back(GetThisType(Context, MD->getParent())); + bool PassParams = true; + GlobalDecl GD; if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { GD = GlobalDecl(CD, toCXXCtorType(Type)); + + // A base class inheriting constructor doesn't get forwarded arguments + // needed to construct a virtual base (or base class thereof). + if (auto Inherited = CD->getInheritedConstructor()) + PassParams = inheritingCtorHasParams(Inherited, toCXXCtorType(Type)); } else { auto *DD = dyn_cast<CXXDestructorDecl>(MD); GD = GlobalDecl(DD, toCXXDtorType(Type)); @@ -263,12 +279,14 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, CanQual<FunctionProtoType> FTP = GetFormalType(MD); // Add the formal parameters. - appendParameterTypes(*this, argTypes, paramInfos, FTP, MD); + if (PassParams) + appendParameterTypes(*this, argTypes, paramInfos, FTP, MD); TheCXXABI.buildStructorSignature(MD, Type, argTypes); RequiredArgs required = - (MD->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All); + (PassParams && MD->isVariadic() ? RequiredArgs(argTypes.size()) + : RequiredArgs::All); FunctionType::ExtInfo extInfo = FTP->getExtInfo(); CanQualType resultType = TheCXXABI.HasThisReturn(GD) @@ -3186,10 +3204,10 @@ void CodeGenFunction::EmitCallArgs( size_t CallArgsStart = Args.size(); for (int I = ArgTypes.size() - 1; I >= 0; --I) { CallExpr::const_arg_iterator Arg = ArgRange.begin() + I; + MaybeEmitImplicitObjectSize(I, *Arg); EmitCallArg(Args, *Arg, ArgTypes[I]); EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(), CalleeDecl, ParamsToSkip + I); - MaybeEmitImplicitObjectSize(I, *Arg); } // Un-reverse the arguments we just evaluated so they match up with the LLVM diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 56e24840c82..7ed891f426a 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -2048,6 +2048,62 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, bool ForVirtualBase, bool Delegating, Address This, const CXXConstructExpr *E) { + CallArgList Args; + + // Push the this ptr. + Args.add(RValue::get(This.getPointer()), D->getThisType(getContext())); + + // If this is a trivial constructor, emit a memcpy now before we lose + // the alignment information on the argument. + // FIXME: It would be better to preserve alignment information into CallArg. + if (isMemcpyEquivalentSpecialMember(D)) { + assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor"); + + const Expr *Arg = E->getArg(0); + QualType SrcTy = Arg->getType(); + Address Src = EmitLValue(Arg).getAddress(); + QualType DestTy = getContext().getTypeDeclType(D->getParent()); + EmitAggregateCopyCtor(This, Src, DestTy, SrcTy); + return; + } + + // Add the rest of the user-supplied arguments. + const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); + EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor()); + + EmitCXXConstructorCall(D, Type, ForVirtualBase, Delegating, This, Args); +} + +static bool canEmitDelegateCallArgs(CodeGenFunction &CGF, + const CXXConstructorDecl *Ctor, + CXXCtorType Type, CallArgList &Args) { + // We can't forward a variadic call. + if (Ctor->isVariadic()) + return false; + + if (CGF.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { + // If the parameters are callee-cleanup, it's not safe to forward. + for (auto *P : Ctor->parameters()) + if (P->getType().isDestructedType()) + return false; + + // Likewise if they're inalloca. + const CGFunctionInfo &Info = + CGF.CGM.getTypes().arrangeCXXConstructorCall(Args, Ctor, Type, 0); + if (Info.usesInAlloca()) + return false; + } + + // Anything else should be OK. + return true; +} + +void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, + CXXCtorType Type, + bool ForVirtualBase, + bool Delegating, + Address This, + CallArgList &Args) { const CXXRecordDecl *ClassDecl = D->getParent(); // C++11 [class.mfct.non-static]p2: @@ -2058,7 +2114,7 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, This.getPointer(), getContext().getRecordType(ClassDecl)); if (D->isTrivial() && D->isDefaultConstructor()) { - assert(E->getNumArgs() == 0 && "trivial default ctor with args"); + assert(Args.size() == 1 && "trivial default ctor with args"); return; } @@ -2066,24 +2122,24 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, // union copy constructor, we must emit a memcpy, because the AST does not // model that copy. if (isMemcpyEquivalentSpecialMember(D)) { - assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor"); + assert(Args.size() == 2 && "unexpected argcount for trivial ctor"); - const Expr *Arg = E->getArg(0); - QualType SrcTy = Arg->getType(); - Address Src = EmitLValue(Arg).getAddress(); + QualType SrcTy = D->getParamDecl(0)->getType().getNonReferenceType(); + Address Src(Args[1].RV.getScalarVal(), getNaturalTypeAlignment(SrcTy)); QualType DestTy = getContext().getTypeDeclType(ClassDecl); EmitAggregateCopyCtor(This, Src, DestTy, SrcTy); return; } - CallArgList Args; - - // Push the this ptr. - Args.add(RValue::get(This.getPointer()), D->getThisType(getContext())); - - // Add the rest of the user-supplied arguments. - const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); - EmitCallArgs(Args, FPT, E->arguments(), E->getConstructor()); + // Check whether we can actually emit the constructor before trying to do so. + if (auto Inherited = D->getInheritedConstructor()) { + if (getTypes().inheritingCtorHasParams(Inherited, Type) && + !canEmitDelegateCallArgs(*this, D, Type, Args)) { + EmitInlinedInheritingCXXConstructorCall(D, Type, ForVirtualBase, + Delegating, Args); + return; + } + } // Insert any ABI-specific implicit constructor arguments. unsigned ExtraArgs = CGM.getCXXABI().addImplicitConstructorArgs( @@ -2113,6 +2169,95 @@ void CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D, EmitVTableAssumptionLoads(ClassDecl, This); } +void CodeGenFunction::EmitInheritedCXXConstructorCall( + const CXXConstructorDecl *D, bool ForVirtualBase, Address This, + bool InheritedFromVBase, const CXXInheritedCtorInitExpr *E) { + CallArgList Args; + CallArg ThisArg(RValue::get(This.getPointer()), D->getThisType(getContext()), + /*NeedsCopy=*/false); + + // Forward the parameters. + if (InheritedFromVBase && + CGM.getTarget().getCXXABI().hasConstructorVariants()) { + // Nothing to do; this construction is not responsible for constructing + // the base class containing the inherited constructor. + // FIXME: Can we just pass undef's for the remaining arguments if we don't + // have constructor variants? + Args.push_back(ThisArg); + } else if (!CXXInheritedCtorInitExprArgs.empty()) { + // The inheriting constructor was inlined; just inject its arguments. + assert(CXXInheritedCtorInitExprArgs.size() >= D->getNumParams() && + "wrong number of parameters for inherited constructor call"); + Args = CXXInheritedCtorInitExprArgs; + Args[0] = ThisArg; + } else { + // The inheriting constructor was not inlined. Emit delegating arguments. + Args.push_back(ThisArg); + const auto *OuterCtor = cast<CXXConstructorDecl>(CurCodeDecl); + assert(OuterCtor->getNumParams() == D->getNumParams()); + assert(!OuterCtor->isVariadic() && "should have been inlined"); + + for (const auto *Param : OuterCtor->parameters()) { + assert(getContext().hasSameUnqualifiedType( + OuterCtor->getParamDecl(Param->getFunctionScopeIndex())->getType(), + Param->getType())); + EmitDelegateCallArg(Args, Param, E->getLocation()); + + // Forward __attribute__(pass_object_size). + if (Param->hasAttr<PassObjectSizeAttr>()) { + auto *POSParam = SizeArguments[Param]; + assert(POSParam && "missing pass_object_size value for forwarding"); + EmitDelegateCallArg(Args, POSParam, E->getLocation()); + } + } + } + + EmitCXXConstructorCall(D, Ctor_Base, ForVirtualBase, /*Delegating*/false, + This, Args); +} + +void CodeGenFunction::EmitInlinedInheritingCXXConstructorCall( + const CXXConstructorDecl *Ctor, CXXCtorType CtorType, bool ForVirtualBase, + bool Delegating, CallArgList &Args) { + InlinedInheritingConstructorScope Scope(*this, GlobalDecl(Ctor, CtorType)); + + // Save the arguments to be passed to the inherited constructor. + CXXInheritedCtorInitExprArgs = Args; + + FunctionArgList Params; + QualType RetType = BuildFunctionArgList(CurGD, Params); + FnRetTy = RetType; + + // Insert any ABI-specific implicit constructor arguments. + CGM.getCXXABI().addImplicitConstructorArgs(*this, Ctor, CtorType, + ForVirtualBase, Delegating, Args); + + // Emit a simplified prolog. We only need to emit the implicit params. + assert(Args.size() >= Params.size() && "too few arguments for call"); + for (unsigned I = 0, N = Args.size(); I != N; ++I) { + if (I < Params.size() && isa<ImplicitParamDecl>(Params[I])) { + const RValue &RV = Args[I].RV; + assert(!RV.isComplex() && "complex indirect params not supported"); + ParamValue Val = RV.isScalar() + ? ParamValue::forDirect(RV.getScalarVal()) + : ParamValue::forIndirect(RV.getAggregateAddress()); + EmitParmDecl(*Params[I], Val, I + 1); + } + } + + // Create a return value slot if the ABI implementation wants one. + // FIXME: This is dumb, we should ask the ABI not to try to set the return + // value instead. + if (!RetType->isVoidType()) + ReturnValue = CreateIRTemp(RetType, "retval.inhctor"); + + CGM.getCXXABI().EmitInstanceFunctionProlog(*this); + CXXThisValue = CXXABIThisValue; + + // Directly emit the constructor initializers. + EmitCtorPrologue(Ctor, CtorType, Params); +} + void CodeGenFunction::EmitVTableAssumptionLoad(const VPtr &Vptr, Address This) { llvm::Value *VTableGlobal = CGM.getCXXABI().getVTableAddressPoint(Vptr.Base, Vptr.VTableClass); @@ -2145,19 +2290,6 @@ void CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, Address This, Address Src, const CXXConstructExpr *E) { - if (isMemcpyEquivalentSpecialMember(D)) { - assert(E->getNumArgs() == 1 && "unexpected argcount for trivial ctor"); - assert(D->isCopyOrMoveConstructor() && - "trivial 1-arg ctor not a copy/move ctor"); - EmitAggregateCopyCtor(This, Src, - getContext().getTypeDeclType(D->getParent()), - (*E->arg_begin())->getType()); - return; - } - llvm::Value *Callee = CGM.getAddrOfCXXStructor(D, StructorType::Complete); - assert(D->isInstance() && - "Trying to emit a member call expr on a static method!"); - const FunctionProtoType *FPT = D->getType()->castAs<FunctionProtoType>(); CallArgList Args; @@ -2175,8 +2307,7 @@ CodeGenFunction::EmitSynthesizedCXXCopyCtorCall(const CXXConstructorDecl *D, EmitCallArgs(Args, FPT, drop_begin(E->arguments(), 1), E->getConstructor(), /*ParamsToSkip*/ 1); - EmitCall(CGM.getTypes().arrangeCXXMethodCall(Args, FPT, RequiredArgs::All), - Callee, ReturnValueSlot(), Args, D); + EmitCXXConstructorCall(D, Ctor_Complete, false, false, This, Args); } void @@ -2190,21 +2321,17 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, assert(I != E && "no parameters to constructor"); // this - DelegateArgs.add(RValue::get(LoadCXXThis()), (*I)->getType()); + Address This = LoadCXXThisAddress(); + DelegateArgs.add(RValue::get(This.getPointer()), (*I)->getType()); ++I; - // vtt - if (llvm::Value *VTT = GetVTTParameter(GlobalDecl(Ctor, CtorType), - /*ForVirtualBase=*/false, - /*Delegating=*/true)) { - QualType VoidPP = getContext().getPointerType(getContext().VoidPtrTy); - DelegateArgs.add(RValue::get(VTT), VoidPP); - - if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) { - assert(I != E && "cannot skip vtt parameter, already done with args"); - assert((*I)->getType() == VoidPP && "skipping parameter not of vtt type"); - ++I; - } + // FIXME: The location of the VTT parameter in the parameter list is + // specific to the Itanium ABI and shouldn't be hardcoded here. + if (CGM.getCXXABI().NeedsVTTParameter(CurGD)) { + assert(I != E && "cannot skip vtt parameter, already done with args"); + assert((*I)->getType()->isPointerType() && + "skipping parameter not of vtt type"); + ++I; } // Explicit arguments. @@ -2214,11 +2341,8 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor, EmitDelegateCallArg(DelegateArgs, param, Loc); } - llvm::Value *Callee = - CGM.getAddrOfCXXStructor(Ctor, getFromCtorType(CtorType)); - EmitCall(CGM.getTypes() - .arrangeCXXStructorDeclaration(Ctor, getFromCtorType(CtorType)), - Callee, ReturnValueSlot(), DelegateArgs, Ctor); + EmitCXXConstructorCall(Ctor, CtorType, /*ForVirtualBase=*/false, + /*Delegating=*/true, This, DelegateArgs); } namespace { diff --git a/clang/lib/CodeGen/CGDecl.cpp b/clang/lib/CodeGen/CGDecl.cpp index 83730597939..508720f5b9a 100644 --- a/clang/lib/CodeGen/CGDecl.cpp +++ b/clang/lib/CodeGen/CGDecl.cpp @@ -85,6 +85,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::Captured: case Decl::ClassScopeFunctionSpecialization: case Decl::UsingShadow: + case Decl::ConstructorUsingShadow: case Decl::ObjCTypeParam: llvm_unreachable("Declaration should not be in declstmts!"); case Decl::Function: // void X(); diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp index 42aa94575a7..6d18843591f 100644 --- a/clang/lib/CodeGen/CGExprAgg.cpp +++ b/clang/lib/CodeGen/CGExprAgg.cpp @@ -175,6 +175,7 @@ public: } void VisitCXXBindTemporaryExpr(CXXBindTemporaryExpr *E); void VisitCXXConstructExpr(const CXXConstructExpr *E); + void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *E); void VisitLambdaExpr(LambdaExpr *E); void VisitCXXStdInitializerListExpr(CXXStdInitializerListExpr *E); void VisitExprWithCleanups(ExprWithCleanups *E); @@ -998,6 +999,14 @@ AggExprEmitter::VisitCXXConstructExpr(const CXXConstructExpr *E) { CGF.EmitCXXConstructExpr(E, Slot); } +void AggExprEmitter::VisitCXXInheritedCtorInitExpr( + const CXXInheritedCtorInitExpr *E) { + AggValueSlot Slot = EnsureSlot(E->getType()); + CGF.EmitInheritedCXXConstructorCall( + E->getConstructor(), E->constructsVBase(), Slot.getAddress(), + E->inheritedFromVBase(), E); +} + void AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) { AggValueSlot Slot = EnsureSlot(E->getType()); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index e914d793559..a0158d8b4b2 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -928,18 +928,11 @@ static void TryMarkNoThrow(llvm::Function *F) { F->setDoesNotThrow(); } -void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, - const CGFunctionInfo &FnInfo) { +QualType CodeGenFunction::BuildFunctionArgList(GlobalDecl GD, + FunctionArgList &Args) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); - - // Check if we should generate debug info for this function. - if (FD->hasAttr<NoDebugAttr>()) - DebugInfo = nullptr; // disable debug info indefinitely for this function - - FunctionArgList Args; QualType ResTy = FD->getReturnType(); - CurGD = GD; const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD); if (MD && MD->isInstance()) { if (CGM.getCXXABI().HasThisReturn(GD)) @@ -949,22 +942,48 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, CGM.getCXXABI().buildThisParam(*this, Args); } - for (auto *Param : FD->parameters()) { - Args.push_back(Param); - if (!Param->hasAttr<PassObjectSizeAttr>()) - continue; - - IdentifierInfo *NoID = nullptr; - auto *Implicit = ImplicitParamDecl::Create( - getContext(), Param->getDeclContext(), Param->getLocation(), NoID, - getContext().getSizeType()); - SizeArguments[Param] = Implicit; - Args.push_back(Implicit); + // The base version of an inheriting constructor whose constructed base is a + // virtual base is not passed any arguments (because it doesn't actually call + // the inherited constructor). + bool PassedParams = true; + if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) + if (auto Inherited = CD->getInheritedConstructor()) + PassedParams = + getTypes().inheritingCtorHasParams(Inherited, GD.getCtorType()); + + if (PassedParams) { + for (auto *Param : FD->parameters()) { + Args.push_back(Param); + if (!Param->hasAttr<PassObjectSizeAttr>()) + continue; + + IdentifierInfo *NoID = nullptr; + auto *Implicit = ImplicitParamDecl::Create( + getContext(), Param->getDeclContext(), Param->getLocation(), NoID, + getContext().getSizeType()); + SizeArguments[Param] = Implicit; + Args.push_back(Implicit); + } } if (MD && (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))) CGM.getCXXABI().addImplicitStructorParams(*this, ResTy, Args); + return ResTy; +} + +void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn, + const CGFunctionInfo &FnInfo) { + const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); + CurGD = GD; + + FunctionArgList Args; + QualType ResTy = BuildFunctionArgList(GD, Args); + + // Check if we should generate debug info for this function. + if (FD->hasAttr<NoDebugAttr>()) + DebugInfo = nullptr; // disable debug info indefinitely for this function + SourceRange BodyRange; if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange(); CurEHLocation = BodyRange.getEnd(); diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 4748e6b47dc..441cee54fc1 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1065,6 +1065,61 @@ public: CharUnits OldCXXThisAlignment; }; + class InlinedInheritingConstructorScope { + public: + InlinedInheritingConstructorScope(CodeGenFunction &CGF, GlobalDecl GD) + : CGF(CGF), OldCurGD(CGF.CurGD), OldCurFuncDecl(CGF.CurFuncDecl), + OldCurCodeDecl(CGF.CurCodeDecl), + OldCXXABIThisDecl(CGF.CXXABIThisDecl), + OldCXXABIThisValue(CGF.CXXABIThisValue), + OldCXXThisValue(CGF.CXXThisValue), + OldCXXABIThisAlignment(CGF.CXXABIThisAlignment), + OldCXXThisAlignment(CGF.CXXThisAlignment), + OldReturnValue(CGF.ReturnValue), OldFnRetTy(CGF.FnRetTy), + OldCXXInheritedCtorInitExprArgs( + std::move(CGF.CXXInheritedCtorInitExprArgs)) { + CGF.CurGD = GD; + CGF.CurFuncDecl = CGF.CurCodeDecl = + cast<CXXConstructorDecl>(GD.getDecl()); + CGF.CXXABIThisDecl = nullptr; + CGF.CXXABIThisValue = nullptr; + CGF.CXXThisValue = nullptr; + CGF.CXXABIThisAlignment = CharUnits(); + CGF.CXXThisAlignment = CharUnits(); + CGF.ReturnValue = Address::invalid(); + CGF.FnRetTy = QualType(); + CGF.CXXInheritedCtorInitExprArgs.clear(); + } + ~InlinedInheritingConstructorScope() { + CGF.CurGD = OldCurGD; + CGF.CurFuncDecl = OldCurFuncDecl; + CGF.CurCodeDecl = OldCurCodeDecl; + CGF.CXXABIThisDecl = OldCXXABIThisDecl; + CGF.CXXABIThisValue = OldCXXABIThisValue; + CGF.CXXThisValue = OldCXXThisValue; + CGF.CXXABIThisAlignment = OldCXXABIThisAlignment; + CGF.CXXThisAlignment = OldCXXThisAlignment; + CGF.ReturnValue = OldReturnValue; + CGF.FnRetTy = OldFnRetTy; + CGF.CXXInheritedCtorInitExprArgs = + std::move(OldCXXInheritedCtorInitExprArgs); + } + + private: + CodeGenFunction &CGF; + GlobalDecl OldCurGD; + const Decl *OldCurFuncDecl; + const Decl *OldCurCodeDecl; + ImplicitParamDecl *OldCXXABIThisDecl; + llvm::Value *OldCXXABIThisValue; + llvm::Value *OldCXXThisValue; + CharUnits OldCXXABIThisAlignment; + CharUnits OldCXXThisAlignment; + Address OldReturnValue; + QualType OldFnRetTy; + CallArgList OldCXXInheritedCtorInitExprArgs; + }; + private: /// CXXThisDecl - When generating code for a C++ member function, /// this will hold the implicit 'this' declaration. @@ -1078,6 +1133,10 @@ private: /// this expression. Address CXXDefaultInitExprThis = Address::invalid(); + /// The values of function arguments to use when evaluating + /// CXXInheritedCtorInitExprs within this context. + CallArgList CXXInheritedCtorInitExprArgs; + /// CXXStructorImplicitParamDecl - When generating code for a constructor or /// destructor, this will hold the implicit argument (e.g. VTT). ImplicitParamDecl *CXXStructorImplicitParamDecl; @@ -1301,6 +1360,8 @@ public: const BlockByrefInfo &getBlockByrefInfo(const VarDecl *var); + QualType BuildFunctionArgList(GlobalDecl GD, FunctionArgList &Args); + void GenerateCode(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo); /// \brief Emit code for the start of a function. @@ -1874,10 +1935,32 @@ public: void EmitDelegatingCXXConstructorCall(const CXXConstructorDecl *Ctor, const FunctionArgList &Args); + /// Emit a call to an inheriting constructor (that is, one that invokes a + /// constructor inherited from a base class) by inlining its definition. This + /// is necessary if the ABI does not support forwarding the arguments to the + /// base class constructor (because they're variadic or similar). + void EmitInlinedInheritingCXXConstructorCall(const CXXConstructorDecl *Ctor, + CXXCtorType CtorType, + bool ForVirtualBase, + bool Delegating, + CallArgList &Args); + + /// Emit a call to a constructor inherited from a base class, passing the + /// current constructor's arguments along unmodified (without even making + /// a copy). + void EmitInheritedCXXConstructorCall(const CXXConstructorDecl *D, + bool ForVirtualBase, Address This, + bool InheritedFromVBase, + const CXXInheritedCtorInitExpr *E); + void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, bool ForVirtualBase, bool Delegating, Address This, const CXXConstructExpr *E); + void EmitCXXConstructorCall(const CXXConstructorDecl *D, CXXCtorType Type, + bool ForVirtualBase, bool Delegating, + Address This, CallArgList &Args); + /// Emit assumption load for all bases. Requires to be be called only on /// most-derived class and not under construction of the object. void EmitVTableAssumptionLoads(const CXXRecordDecl *ClassDecl, Address This); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index ac00bf85cd3..bbec03842cb 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -765,6 +765,15 @@ CodeGenModule::getFunctionLinkage(GlobalDecl GD) { : llvm::GlobalValue::LinkOnceODRLinkage; } + if (isa<CXXConstructorDecl>(D) && + cast<CXXConstructorDecl>(D)->isInheritingConstructor() && + Context.getTargetInfo().getCXXABI().isMicrosoft()) { + // Our approach to inheriting constructors is fundamentally different from + // that used by the MS ABI, so keep our inheriting constructor thunks + // internal rather than trying to pick an unambiguous mangling for them. + return llvm::GlobalValue::InternalLinkage; + } + return getLLVMLinkageForDeclarator(D, Linkage, /*isConstantVariable=*/false); } diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h index c77790100a8..affa3344103 100644 --- a/clang/lib/CodeGen/CodeGenTypes.h +++ b/clang/lib/CodeGen/CodeGenTypes.h @@ -205,6 +205,11 @@ public: bool isFuncTypeConvertible(const FunctionType *FT); bool isFuncParamTypeConvertible(QualType Ty); + /// Determine if a C++ inheriting constructor should have parameters matching + /// those of its inherited constructor. + bool inheritingCtorHasParams(const InheritedConstructor &Inherited, + CXXCtorType Type); + /// GetFunctionTypeForVTable - Get the LLVM function type for use in a vtable, /// given a CXXMethodDecl. If the method to has an incomplete return type, /// and/or incomplete argument types, this will return the opaque type. |