r184205 - CodeGen: Have 'this'-returning constructors and destructors to take advantage of the new backend 'returned' attribute.

Richard Smith richard at metafoo.co.uk
Thu Oct 31 11:45:57 PDT 2013


On Tue, Jun 18, 2013 at 10:00 AM, Stephen Lin <stephenwlin at gmail.com> wrote:

> Author: stephenwlin
> Date: Tue Jun 18 12:00:49 2013
> New Revision: 184205
>
> URL: http://llvm.org/viewvc/llvm-project?rev=184205&view=rev
> Log:
> CodeGen: Have 'this'-returning constructors and destructors to take
> advantage of the new backend 'returned' attribute.
>

The implementation of the ARM ABI 'implicit return this from constructors'
behavior has caused PR17759. I'm not sure if your patches caused this or if
it's pre-existing; interested in investigating? =)


> The backend will now use the generic 'returned' attribute to form tail
> calls where possible, as well as avoid save-restores of 'this' in some
> cases (specifically the cases that matter for the ARM C++ ABI).
>
> This patch also reverts a prior front-end only partial implementation of
> these optimizations, since it's no longer required.
>
> Modified:
>     cfe/trunk/lib/CodeGen/CGCXXABI.h
>     cfe/trunk/lib/CodeGen/CGCall.cpp
>     cfe/trunk/lib/CodeGen/CGClass.cpp
>     cfe/trunk/lib/CodeGen/CGVTables.cpp
>     cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
>     cfe/trunk/lib/CodeGen/CodeGenFunction.h
>     cfe/trunk/lib/CodeGen/CodeGenModule.cpp
>     cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
>     cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>     cfe/trunk/test/CodeGenCXX/arm.cpp
>     cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp
>     cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp
>     cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp
>
> Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)
> +++ cfe/trunk/lib/CodeGen/CGCXXABI.h Tue Jun 18 12:00:49 2013
> @@ -97,8 +97,12 @@ public:
>      return *MangleCtx;
>    }
>
> -  /// Returns true if the given instance method is one of the
> -  /// kinds that the ABI says returns 'this'.
> +  /// Returns true if the given constructor or destructor is one of the
> +  /// kinds that the ABI says returns 'this' (only applies when called
> +  /// non-virtually for destructors).
> +  ///
> +  /// There currently is no way to indicate if a destructor returns 'this'
> +  /// when called virtually, and code generation does not support the
> case.
>    virtual bool HasThisReturn(GlobalDecl GD) const { return false; }
>
>    /// Returns true if the given record type should be returned indirectly.
> @@ -214,10 +218,10 @@ public:
>                                          const CXXRecordDecl
> *BaseClassDecl) = 0;
>
>    /// Build the signature of the given constructor variant by adding
> -  /// any required parameters.  For convenience, ResTy has been
> -  /// initialized to 'void', and ArgTys has been initialized with the
> -  /// type of 'this' (although this may be changed by the ABI) and
> -  /// will have the formal parameters added to it afterwards.
> +  /// any required parameters.  For convenience, ArgTys has been
> initialized
> +  /// with the type of 'this' and ResTy has been initialized with the
> type of
> +  /// 'this' if HasThisReturn(GlobalDecl(Ctor, T)) is true or 'void'
> otherwise
> +  /// (although both may be changed by the ABI).
>    ///
>    /// If there are ever any ABIs where the implicit parameters are
>    /// intermixed with the formal parameters, we can address those
> @@ -230,9 +234,10 @@ public:
>    virtual llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction
> &CGF);
>
>    /// Build the signature of the given destructor variant by adding
> -  /// any required parameters.  For convenience, ResTy has been
> -  /// initialized to 'void' and ArgTys has been initialized with the
> -  /// type of 'this' (although this may be changed by the ABI).
> +  /// any required parameters.  For convenience, ArgTys has been
> initialized
> +  /// with the type of 'this' and ResTy has been initialized with the
> type of
> +  /// 'this' if HasThisReturn(GlobalDecl(Dtor, T)) is true or 'void'
> otherwise
> +  /// (although both may be changed by the ABI).
>    virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
>                                          CXXDtorType T,
>                                          CanQualType &ResTy,
> @@ -243,7 +248,8 @@ public:
>    /// possibly some extra data for constructors and destructors.
>    ///
>    /// ABIs may also choose to override the return type, which has been
> -  /// initialized with the formal return type of the function.
> +  /// initialized with the type of 'this' if HasThisReturn(CGF.CurGD) is
> true or
> +  /// the formal return type of the function otherwise.
>    virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF,
>                                             QualType &ResTy,
>                                             FunctionArgList &Params) = 0;
> @@ -252,13 +258,14 @@ public:
>    virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;
>
>    /// Emit the constructor call. Return the function that is called.
> -  virtual llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,
> -                                   const CXXConstructorDecl *D,
> -                                   CXXCtorType Type, bool ForVirtualBase,
> -                                   bool Delegating,
> -                                   llvm::Value *This,
> -                                   CallExpr::const_arg_iterator ArgBeg,
> -                                   CallExpr::const_arg_iterator ArgEnd) =
> 0;
> +  virtual RValue EmitConstructorCall(CodeGenFunction &CGF,
> +                                     const CXXConstructorDecl *D,
> +                                     CXXCtorType Type,
> +                                     bool ForVirtualBase, bool Delegating,
> +                                     ReturnValueSlot ReturnValue,
> +                                     llvm::Value *This,
> +                                     CallExpr::const_arg_iterator ArgBeg,
> +                                     CallExpr::const_arg_iterator ArgEnd)
> = 0;
>
>    /// Emit the ABI-specific virtual destructor call.
>    virtual RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
>
> Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGCall.cpp Tue Jun 18 12:00:49 2013
> @@ -200,7 +200,10 @@ CodeGenTypes::arrangeCXXConstructorDecla
>                                                 CXXCtorType ctorKind) {
>    SmallVector<CanQualType, 16> argTypes;
>    argTypes.push_back(GetThisType(Context, D->getParent()));
> -  CanQualType resultType = Context.VoidTy;
> +
> +  GlobalDecl GD(D, ctorKind);
> +  CanQualType resultType =
> +    TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
>
>    TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes);
>
> @@ -225,7 +228,10 @@ CodeGenTypes::arrangeCXXDestructor(const
>                                     CXXDtorType dtorKind) {
>    SmallVector<CanQualType, 2> argTypes;
>    argTypes.push_back(GetThisType(Context, D->getParent()));
> -  CanQualType resultType = Context.VoidTy;
> +
> +  GlobalDecl GD(D, dtorKind);
> +  CanQualType resultType =
> +    TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;
>
>    TheCXXABI.BuildDestructorSignature(D, dtorKind, resultType, argTypes);
>
> @@ -1633,18 +1639,6 @@ static llvm::StoreInst *findDominatingSt
>    return store;
>  }
>
> -/// Check whether 'this' argument of a callsite matches 'this' of the
> caller.
> -static bool checkThisPointer(llvm::Value *ThisArg, llvm::Value *This) {
> -  if (ThisArg == This)
> -    return true;
> -  // Check whether ThisArg is a bitcast of This.
> -  llvm::BitCastInst *Bitcast;
> -  if ((Bitcast = dyn_cast<llvm::BitCastInst>(ThisArg)) &&
> -      Bitcast->getOperand(0) == This)
> -    return true;
> -  return false;
> -}
> -
>  void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,
>                                           bool EmitRetDbgLoc) {
>    // Functions with no result always return void.
> @@ -1741,19 +1735,6 @@ void CodeGenFunction::EmitFunctionEpilog
>      llvm_unreachable("Invalid ABI kind for return argument");
>    }
>
> -  // If this function returns 'this', the last instruction is a CallInst
> -  // that returns 'this', and 'this' argument of the CallInst points to
> -  // the same object as CXXThisValue, use the return value from the
> CallInst.
> -  // We will not need to keep 'this' alive through the callsite. It also
> enables
> -  // optimizations in the backend, such as tail call optimization.
> -  if (CalleeWithThisReturn && CGM.getCXXABI().HasThisReturn(CurGD)) {
> -    llvm::BasicBlock *IP = Builder.GetInsertBlock();
> -    llvm::CallInst *Callsite;
> -    if (!IP->empty() && (Callsite =
> dyn_cast<llvm::CallInst>(&IP->back())) &&
> -        Callsite->getCalledFunction() == CalleeWithThisReturn &&
> -        checkThisPointer(Callsite->getOperand(0), CXXThisValue))
> -      RV = Builder.CreateBitCast(Callsite, RetAI.getCoerceToType());
> -  }
>    llvm::Instruction *Ret = RV ? Builder.CreateRet(RV) :
> Builder.CreateRetVoid();
>    if (!RetDbgLoc.isUnknown())
>      Ret->setDebugLoc(RetDbgLoc);
>
> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Tue Jun 18 12:00:49 2013
> @@ -1661,11 +1661,9 @@ CodeGenFunction::EmitCXXConstructorCall(
>    }
>
>    // Non-trivial constructors are handled in an ABI-specific manner.
> -  llvm::Value *Callee = CGM.getCXXABI().EmitConstructorCall(*this, D,
> Type,
> -                            ForVirtualBase, Delegating, This, ArgBeg,
> ArgEnd);
> -  if (CGM.getCXXABI().HasThisReturn(CurGD) &&
> -      CGM.getCXXABI().HasThisReturn(GlobalDecl(D, Type)))
> -     CalleeWithThisReturn = Callee;
> +  CGM.getCXXABI().EmitConstructorCall(*this, D, Type,
> +                                      ForVirtualBase, Delegating,
> +                                      ReturnValueSlot(), This, ArgBeg,
> ArgEnd);
>  }
>
>  void
> @@ -1757,9 +1755,6 @@ CodeGenFunction::EmitDelegateCXXConstruc
>    llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(Ctor, CtorType);
>    EmitCall(CGM.getTypes().arrangeCXXConstructorDeclaration(Ctor,
> CtorType),
>             Callee, ReturnValueSlot(), DelegateArgs, Ctor);
> -  if (CGM.getCXXABI().HasThisReturn(CurGD) &&
> -      CGM.getCXXABI().HasThisReturn(GlobalDecl(Ctor, CtorType)))
> -     CalleeWithThisReturn = Callee;
>  }
>
>  namespace {
> @@ -1826,9 +1821,6 @@ void CodeGenFunction::EmitCXXDestructorC
>    EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This,
>                      VTT,
> getContext().getPointerType(getContext().VoidPtrTy),
>                      0, 0);
> -  if (CGM.getCXXABI().HasThisReturn(CurGD) &&
> -      CGM.getCXXABI().HasThisReturn(GlobalDecl(DD, Type)))
> -     CalleeWithThisReturn = Callee;
>  }
>
>  namespace {
>
> Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGVTables.cpp Tue Jun 18 12:00:49 2013
> @@ -287,8 +287,9 @@ void CodeGenFunction::GenerateThunk(llvm
>                                      GlobalDecl GD, const ThunkInfo
> &Thunk) {
>    const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());
>    const FunctionProtoType *FPT =
> MD->getType()->getAs<FunctionProtoType>();
> -  QualType ResultType = FPT->getResultType();
>    QualType ThisType = MD->getThisType(getContext());
> +  QualType ResultType =
> +    CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getResultType();
>
>    FunctionArgList FunctionArgs;
>
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Jun 18 12:00:49 2013
> @@ -42,8 +42,7 @@ CodeGenFunction::CodeGenFunction(CodeGen
>      AutoreleaseResult(false), BlockInfo(0), BlockPointer(0),
>      LambdaThisCaptureField(0), NormalCleanupDest(0),
> NextCleanupDestIndex(1),
>      FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0),
> EHSelectorSlot(0),
> -    DebugInfo(0), DisableDebugInfo(false), CalleeWithThisReturn(0),
> -    DidCallStackSave(false),
> +    DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false),
>      IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0),
> UnreachableBlock(0),
>      NumReturnExprs(0), NumSimpleReturnExprs(0),
>      CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0),
> @@ -662,8 +661,12 @@ void CodeGenFunction::GenerateCode(Globa
>    QualType ResTy = FD->getResultType();
>
>    CurGD = GD;
> -  if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance())
> +  const CXXMethodDecl *MD;
> +  if ((MD = dyn_cast<CXXMethodDecl>(FD)) && MD->isInstance()) {
> +    if (CGM.getCXXABI().HasThisReturn(GD))
> +      ResTy = MD->getThisType(getContext());
>      CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args);
> +  }
>
>    for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)
>      Args.push_back(FD->getParamDecl(i));
> @@ -672,10 +675,6 @@ void CodeGenFunction::GenerateCode(Globa
>    if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();
>    CurEHLocation = BodyRange.getEnd();
>
> -  // CalleeWithThisReturn keeps track of the last callee inside this
> function
> -  // that returns 'this'. Before starting the function, we set it to null.
> -  CalleeWithThisReturn = 0;
> -
>    // Emit the standard function prologue.
>    StartFunction(GD, ResTy, Fn, FnInfo, Args, BodyRange.getBegin());
>
> @@ -727,9 +726,6 @@ void CodeGenFunction::GenerateCode(Globa
>
>    // Emit the standard function epilogue.
>    FinishFunction(BodyRange.getEnd());
> -  // CalleeWithThisReturn keeps track of the last callee inside this
> function
> -  // that returns 'this'. After finishing the function, we set it to null.
> -  CalleeWithThisReturn = 0;
>
>    // If we haven't marked the function nothrow through other means, do
>    // a quick pass now to see if we can.
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Jun 18 12:00:49 2013
> @@ -798,10 +798,6 @@ private:
>    CGDebugInfo *DebugInfo;
>    bool DisableDebugInfo;
>
> -  /// If the current function returns 'this', use the field to keep track
> of
> -  /// the callee that returns 'this'.
> -  llvm::Value *CalleeWithThisReturn;
> -
>    /// DidCallStackSave - Whether llvm.stacksave has been called. Used to
> avoid
>    /// calling llvm.stacksave for multiple VLAs in the same scope.
>    bool DidCallStackSave;
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Jun 18 12:00:49 2013
> @@ -717,6 +717,14 @@ void CodeGenModule::SetFunctionAttribute
>    if (!IsIncompleteFunction)
>      SetLLVMFunctionAttributes(FD,
> getTypes().arrangeGlobalDeclaration(GD), F);
>
> +  if (getCXXABI().HasThisReturn(GD)) {
> +    llvm::Type *RetTy = F->getReturnType();
> +    assert(!F->arg_empty() &&
> +           F->arg_begin()->getType()->canLosslesslyBitCastTo(RetTy) &&
> +           "unexpected this return");
> +    F->addAttribute(1, llvm::Attribute::Returned);
> +  }
> +
>    // Only a few attributes are set on declarations; these may later be
>    // overridden by a definition.
>
>
> Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Jun 18 12:00:49 2013
> @@ -119,13 +119,14 @@ public:
>
>    void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
>
> -  llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,
> -                           const CXXConstructorDecl *D,
> -                           CXXCtorType Type, bool ForVirtualBase,
> -                           bool Delegating,
> -                           llvm::Value *This,
> -                           CallExpr::const_arg_iterator ArgBeg,
> -                           CallExpr::const_arg_iterator ArgEnd);
> +  RValue EmitConstructorCall(CodeGenFunction &CGF,
> +                             const CXXConstructorDecl *D,
> +                             CXXCtorType Type,
> +                             bool ForVirtualBase, bool Delegating,
> +                             ReturnValueSlot ReturnValue,
> +                             llvm::Value *This,
> +                             CallExpr::const_arg_iterator ArgBeg,
> +                             CallExpr::const_arg_iterator ArgEnd);
>
>    RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
>                                     const CXXDestructorDecl *Dtor,
> @@ -165,21 +166,11 @@ class ARMCXXABI : public ItaniumCXXABI {
>  public:
>    ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/
> true) {}
>
> -  void BuildConstructorSignature(const CXXConstructorDecl *Ctor,
> -                                 CXXCtorType T,
> -                                 CanQualType &ResTy,
> -                                 SmallVectorImpl<CanQualType> &ArgTys);
> -
> -  void BuildDestructorSignature(const CXXDestructorDecl *Dtor,
> -                                CXXDtorType T,
> -                                CanQualType &ResTy,
> -                                SmallVectorImpl<CanQualType> &ArgTys);
> -
> -  void BuildInstanceFunctionParams(CodeGenFunction &CGF,
> -                                   QualType &ResTy,
> -                                   FunctionArgList &Params);
> -
> -  void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
> +  bool HasThisReturn(GlobalDecl GD) const {
> +    return (isa<CXXConstructorDecl>(GD.getDecl()) || (
> +              isa<CXXDestructorDecl>(GD.getDecl()) &&
> +              GD.getDtorType() != Dtor_Deleting));
> +  }
>
>    void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType
> ResTy);
>
> @@ -191,15 +182,6 @@ public:
>                                       QualType ElementType);
>    llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, llvm::Value
> *allocPtr,
>                                     CharUnits cookieSize);
> -
> -  /// \brief Returns true if the given instance method is one of the
> -  /// kinds that the ARM ABI says returns 'this'.
> -  bool HasThisReturn(GlobalDecl GD) const {
> -    const CXXMethodDecl *MD =
> dyn_cast_or_null<CXXMethodDecl>(GD.getDecl());
> -    if (!MD) return false;
> -    return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() !=
> Dtor_Deleting) ||
> -            (isa<CXXConstructorDecl>(MD)));
> -  }
>  };
>  }
>
> @@ -754,22 +736,14 @@ void ItaniumCXXABI::BuildConstructorSign
>                                  SmallVectorImpl<CanQualType> &ArgTys) {
>    ASTContext &Context = getContext();
>
> -  // 'this' is already there.
> +  // 'this' parameter is already there, as well as 'this' return if
> +  // HasThisReturn(GlobalDecl(Ctor, Type)) is true
>
>    // Check if we need to add a VTT parameter (which has type void **).
>    if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0)
>      ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
>  }
>
> -/// The ARM ABI does the same as the Itanium ABI, but returns 'this'.
> -void ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,
> -                                          CXXCtorType Type,
> -                                          CanQualType &ResTy,
> -                                SmallVectorImpl<CanQualType> &ArgTys) {
> -  ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys);
> -  ResTy = ArgTys[0];
> -}
> -
>  /// The generic ABI passes 'this', plus a VTT if it's destroying a
>  /// base subobject.
>  void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl
> *Dtor,
> @@ -778,25 +752,14 @@ void ItaniumCXXABI::BuildDestructorSigna
>                                  SmallVectorImpl<CanQualType> &ArgTys) {
>    ASTContext &Context = getContext();
>
> -  // 'this' is already there.
> +  // 'this' parameter is already there, as well as 'this' return if
> +  // HasThisReturn(GlobalDecl(Dtor, Type)) is true
>
>    // Check if we need to add a VTT parameter (which has type void **).
>    if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0)
>      ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));
>  }
>
> -/// The ARM ABI does the same as the Itanium ABI, but returns 'this'
> -/// for non-deleting destructors.
> -void ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,
> -                                         CXXDtorType Type,
> -                                         CanQualType &ResTy,
> -                                SmallVectorImpl<CanQualType> &ArgTys) {
> -  ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys);
> -
> -  if (Type != Dtor_Deleting)
> -    ResTy = ArgTys[0];
> -}
> -
>  void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
>                                                  QualType &ResTy,
>                                                  FunctionArgList &Params) {
> @@ -820,16 +783,6 @@ void ItaniumCXXABI::BuildInstanceFunctio
>    }
>  }
>
> -void ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,
> -                                            QualType &ResTy,
> -                                            FunctionArgList &Params) {
> -  ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params);
> -
> -  // Return 'this' from certain constructors and destructors.
> -  if (HasThisReturn(CGF.CurGD))
> -    ResTy = Params[0]->getType();
> -}
> -
>  void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
>    /// Initialize the 'this' slot.
>    EmitThisParam(CGF);
> @@ -840,21 +793,24 @@ void ItaniumCXXABI::EmitInstanceFunction
>        = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)),
>                                 "vtt");
>    }
> -}
>
> -void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
> -  ItaniumCXXABI::EmitInstanceFunctionProlog(CGF);
> -
> -  /// Initialize the return slot to 'this' at the start of the
> -  /// function.
> +  /// If this is a function that the ABI specifies returns 'this',
> initialize
> +  /// the return slot to 'this' at the start of the function.
> +  ///
> +  /// Unlike the setting of return types, this is done within the ABI
> +  /// implementation instead of by clients of CGCXXABI because:
> +  /// 1) getThisValue is currently protected
> +  /// 2) in theory, an ABI could implement 'this' returns some other way;
> +  ///    HasThisReturn only specifies a contract, not the implementation
>    if (HasThisReturn(CGF.CurGD))
>      CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
>  }
>
> -llvm::Value *ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
> +RValue ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
>                                          const CXXConstructorDecl *D,
> -                                        CXXCtorType Type, bool
> ForVirtualBase,
> -                                        bool Delegating,
> +                                        CXXCtorType Type,
> +                                        bool ForVirtualBase, bool
> Delegating,
> +                                        ReturnValueSlot ReturnValue,
>                                          llvm::Value *This,
>                                          CallExpr::const_arg_iterator
> ArgBeg,
>                                          CallExpr::const_arg_iterator
> ArgEnd) {
> @@ -864,9 +820,8 @@ llvm::Value *ItaniumCXXABI::EmitConstruc
>    llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);
>
>    // FIXME: Provide a source location here.
> -  CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(),
> This,
> -                        VTT, VTTTy, ArgBeg, ArgEnd);
> -  return Callee;
> +  return CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValue,
> +                               This, VTT, VTTTy, ArgBeg, ArgEnd);
>  }
>
>  RValue ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
>
> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Jun 18 12:00:49 2013
> @@ -28,6 +28,8 @@ class MicrosoftCXXABI : public CGCXXABI
>  public:
>    MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}
>
> +  bool HasThisReturn(GlobalDecl GD) const;
> +
>    bool isReturnTypeIndirect(const CXXRecordDecl *RD) const {
>      // Structures that are not C++03 PODs are always indirect.
>      return !RD->isPOD();
> @@ -71,13 +73,14 @@ public:
>
>    void EmitInstanceFunctionProlog(CodeGenFunction &CGF);
>
> -  llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,
> -                           const CXXConstructorDecl *D,
> -                           CXXCtorType Type, bool ForVirtualBase,
> -                           bool Delegating,
> -                           llvm::Value *This,
> -                           CallExpr::const_arg_iterator ArgBeg,
> -                           CallExpr::const_arg_iterator ArgEnd);
> +  RValue EmitConstructorCall(CodeGenFunction &CGF,
> +                             const CXXConstructorDecl *D,
> +                             CXXCtorType Type,
> +                             bool ForVirtualBase, bool Delegating,
> +                             ReturnValueSlot ReturnValue,
> +                             llvm::Value *This,
> +                             CallExpr::const_arg_iterator ArgBeg,
> +                             CallExpr::const_arg_iterator ArgEnd);
>
>    RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,
>                                     const CXXDestructorDecl *Dtor,
> @@ -124,7 +127,6 @@ public:
>    llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,
>                                     llvm::Value *allocPtr,
>                                     CharUnits cookieSize);
> -  static bool needThisReturn(GlobalDecl GD);
>
>  private:
>    llvm::Constant *getZeroInt() {
> @@ -299,19 +301,15 @@ MicrosoftCXXABI::GetVirtualBaseClassOffs
>    return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);
>  }
>
> -bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) {
> -  const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());
> -  return isa<CXXConstructorDecl>(MD);
> +bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const {
> +  return isa<CXXConstructorDecl>(GD.getDecl());
>  }
>
>  void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl
> *Ctor,
>                                   CXXCtorType Type,
>                                   CanQualType &ResTy,
>                                   SmallVectorImpl<CanQualType> &ArgTys) {
> -  // 'this' is already in place
> -
> -  // Ctor returns this ptr
> -  ResTy = ArgTys[0];
> +  // 'this' parameter and 'this' return are already in place
>
>    const CXXRecordDecl *Class = Ctor->getParent();
>    if (Class->getNumVBases()) {
> @@ -346,6 +344,7 @@ void MicrosoftCXXABI::BuildDestructorSig
>                                                 CanQualType &ResTy,
>                                          SmallVectorImpl<CanQualType>
> &ArgTys) {
>    // 'this' is already in place
> +
>    // TODO: 'for base' flag
>
>    if (Type == Dtor_Deleting) {
> @@ -366,9 +365,6 @@ void MicrosoftCXXABI::BuildInstanceFunct
>                                                    QualType &ResTy,
>                                                    FunctionArgList
> &Params) {
>    BuildThisParam(CGF, Params);
> -  if (needThisReturn(CGF.CurGD)) {
> -    ResTy = Params[0]->getType();
> -  }
>
>    ASTContext &Context = getContext();
>    const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
> @@ -393,9 +389,17 @@ void MicrosoftCXXABI::BuildInstanceFunct
>
>  void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {
>    EmitThisParam(CGF);
> -  if (needThisReturn(CGF.CurGD)) {
> +
> +  /// If this is a function that the ABI specifies returns 'this',
> initialize
> +  /// the return slot to 'this' at the start of the function.
> +  ///
> +  /// Unlike the setting of return types, this is done within the ABI
> +  /// implementation instead of by clients of CGCXXABI because:
> +  /// 1) getThisValue is currently protected
> +  /// 2) in theory, an ABI could implement 'this' returns some other way;
> +  ///    HasThisReturn only specifies a contract, not the implementation
> +  if (HasThisReturn(CGF.CurGD))
>      CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);
> -  }
>
>    const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());
>    if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {
> @@ -417,11 +421,13 @@ void MicrosoftCXXABI::EmitInstanceFuncti
>    }
>  }
>
> -llvm::Value *MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
> -                                          const CXXConstructorDecl *D,
> -                                          CXXCtorType Type, bool
> ForVirtualBase,
> -                                          bool Delegating,
> -                                          llvm::Value *This,
> +RValue MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,
> +                                            const CXXConstructorDecl *D,
> +                                            CXXCtorType Type,
> +                                            bool ForVirtualBase,
> +                                            bool Delegating,
> +                                            ReturnValueSlot ReturnValue,
> +                                            llvm::Value *This,
>                                            CallExpr::const_arg_iterator
> ArgBeg,
>                                            CallExpr::const_arg_iterator
> ArgEnd) {
>    assert(Type == Ctor_Complete || Type == Ctor_Base);
> @@ -435,10 +441,9 @@ llvm::Value *MicrosoftCXXABI::EmitConstr
>    }
>
>    // FIXME: Provide a source location here.
> -  CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(),
> This,
> -                        ImplicitParam, ImplicitParamTy,
> -                        ArgBeg, ArgEnd);
> -  return Callee;
> +  return CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValue,
> +                               This, ImplicitParam, ImplicitParamTy,
> +                               ArgBeg, ArgEnd);
>  }
>
>  RValue MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,
>
> Modified: cfe/trunk/test/CodeGenCXX/arm.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/arm.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/arm.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/arm.cpp Tue Jun 18 12:00:49 2013
> @@ -52,19 +52,19 @@ namespace test1 {
>      a.bar();
>    }
>
> -  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* %this, i32
> %i) unnamed_addr
> +  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* returned
> %this, i32 %i) unnamed_addr
>    // CHECK:   [[THIS:%.*]] = alloca [[A]]*, align 4
>    // CHECK:   store [[A]]* {{.*}}, [[A]]** [[THIS]]
>    // CHECK:   [[THIS1:%.*]] = load [[A]]** [[THIS]]
> -  // CHECK:   [[THIS2:%.*]] = call [[A]]* @_ZN5test11AC2Ei(
> -  // CHECK:   ret [[A]]* [[THIS2]]
> +  // CHECK:   {{%.*}} = call [[A]]* @_ZN5test11AC2Ei(
> +  // CHECK:   ret [[A]]* [[THIS1]]
>
> -  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* %this)
> unnamed_addr
> +  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* returned
> %this) unnamed_addr
>    // CHECK:   [[THIS:%.*]] = alloca [[A]]*, align 4
>    // CHECK:   store [[A]]* {{.*}}, [[A]]** [[THIS]]
>    // CHECK:   [[THIS1:%.*]] = load [[A]]** [[THIS]]
> -  // CHECK:   [[THIS2:%.*]] = call [[A]]* @_ZN5test11AD2Ev(
> -  // CHECK:   ret [[A]]* [[THIS2]]
> +  // CHECK:   {{%.*}} = call [[A]]* @_ZN5test11AD2Ev(
> +  // CHECK:   ret [[A]]* [[THIS1]]
>  }
>
>  // Awkward virtual cases.
>
> Modified: cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp
> (original)
> +++ cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp Tue
> Jun 18 12:00:49 2013
> @@ -1,60 +1,120 @@
> -//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios3.0
> -target-abi apcs-gnu | FileCheck %s
> +//RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-unknown-linux |
> FileCheck --check-prefix=CHECKGEN %s
> +//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios3.0
> -target-abi apcs-gnu | FileCheck --check-prefix=CHECKARM %s
> +//RUN: %clang_cc1 %s -emit-llvm -o - -DPR12784_WORKAROUND
> -triple=x86_64-pc-win32 -cxx-abi microsoft | FileCheck
> --check-prefix=CHECKMS %s
>
> -// For constructors/desctructors that return 'this', if there exists a
> callsite
> -// that returns 'this' and is immediately before the return instruction,
> make
> -// sure we are using the return value from the callsite.
> -// rdar://12818789
> -
> -// CHECK: define linkonce_odr [[A:%.*]] @_ZN11ObjectCacheC1Ev([[A]]
> %this) unnamed_addr
> -// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN11ObjectCacheC2Ev(
> -// CHECK-NEXT: ret [[A]] [[THIS1]]
> -
> -// CHECK: define linkonce_odr [[A:%.*]]
> @_ZN5TimerI11ObjectCacheEC1EPS0_MS0_FvPS1_E([[A]] %this
> -// CHECK: [[THIS1:%.*]] = call [[A]]
> @_ZN5TimerI11ObjectCacheEC2EPS0_MS0_FvPS1_E(
> -// CHECK-NEXT: ret [[A]] [[THIS1]]
> -
> -// CHECK: define linkonce_odr [[A:%.*]]
> @_ZN5TimerI11ObjectCacheED1Ev([[A]] %this) unnamed_addr
> -// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN5TimerI11ObjectCacheED2Ev(
> -// CHECK-NEXT: ret [[A]] [[THIS1]]
> -
> -// CHECK: define linkonce_odr [[A:%.*]]
> @_ZN5TimerI11ObjectCacheED2Ev([[A]] %this) unnamed_addr
> -// CHECK: [[THIS1:%.*]] = call [[B:%.*]] @_ZN9TimerBaseD2Ev(
> -// CHECK-NEXT: [[THIS2:%.*]] = bitcast [[B]] [[THIS1]] to [[A]]
> -// CHECK-NEXT: ret [[A]] [[THIS2]]
> +// FIXME: Add checks to ensure that Microsoft destructors do not return
> 'this'
> +// once PR12784 is resolved
>
> -class TimerBase {
> +// Make sure we attach the 'returned' attribute to the 'this' parameter of
> +// constructors and destructors which return this (and only these cases)
> +
> +class A {
>  public:
> -    TimerBase();
> -    virtual ~TimerBase();
> +  A();
> +  ~A();
> +
> +private:
> +  int x_;
>  };
>
> -template <typename TimerFiredClass> class Timer : public TimerBase {
> +class B : public A {
>  public:
> -    typedef void (TimerFiredClass::*TimerFiredFunction)(Timer*);
> -
> -    Timer(TimerFiredClass* o, TimerFiredFunction f)
> -        : m_object(o), m_function(f) { }
> +  B(int *i);
> +  ~B();
>
>  private:
> -    virtual void fired() { (m_object->*m_function)(this); }
> +  int *i_;
> +};
>
> -    TimerFiredClass* m_object;
> -    TimerFiredFunction m_function;
> +B::B(int *i) : i_(i) { }
> +#ifndef PR12784_WORKAROUND
> +B::~B() { }
> +#endif
> +
> +// CHECKGEN: define void @_ZN1BC1EPi(%class.B* %this, i32* %i)
> +// CHECKGEN: define void @_ZN1BC2EPi(%class.B* %this, i32* %i)
> +// CHECKGEN: define void @_ZN1BD1Ev(%class.B* %this)
> +// CHECKGEN: define void @_ZN1BD2Ev(%class.B* %this)
> +
> +// CHECKARM: define %class.B* @_ZN1BC1EPi(%class.B* returned %this, i32*
> %i)
> +// CHECKARM: define %class.B* @_ZN1BC2EPi(%class.B* returned %this, i32*
> %i)
> +// CHECKARM: define %class.B* @_ZN1BD1Ev(%class.B* returned %this)
> +// CHECKARM: define %class.B* @_ZN1BD2Ev(%class.B* returned %this)
> +
> +// CHECKMS: define %class.B* @"\01??0B@@QEAA at PEAH@Z"(%class.B* returned
> %this, i32* %i)
> +
> +class C : public A, public B {
> +public:
> +  C(int *i, char *c);
> +  virtual ~C();
> +private:
> +  char *c_;
>  };
>
> -class ObjectCache {
> +C::C(int *i, char *c) : B(i), c_(c) { }
> +#ifndef PR12784_WORKAROUND
> +C::~C() { }
> +#endif
> +
> +// CHECKGEN: define void @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c)
> +// CHECKGEN: define void @_ZN1CC2EPiPc(%class.C* %this, i32* %i, i8* %c)
> +// CHECKGEN: define void @_ZN1CD0Ev(%class.C* %this)
> +// CHECKGEN: define void @_ZN1CD1Ev(%class.C* %this)
> +// CHECKGEN: define void @_ZN1CD2Ev(%class.C* %this)
> +
> +// CHECKARM: define %class.C* @_ZN1CC1EPiPc(%class.C* returned %this,
> i32* %i, i8* %c)
> +// CHECKARM: define %class.C* @_ZN1CC2EPiPc(%class.C* returned %this,
> i32* %i, i8* %c)
> +// CHECKARM: define void @_ZN1CD0Ev(%class.C* %this)
> +// CHECKARM: define %class.C* @_ZN1CD1Ev(%class.C* returned %this)
> +// CHECKARM: define %class.C* @_ZN1CD2Ev(%class.C* returned %this)
> +
> +// CHECKMS: define %class.C* @"\01??0C@@QEAA at PEAHPEAD@Z"(%class.C*
> returned %this, i32* %i, i8* %c)
> +
> +class D : public virtual A {
>  public:
> -    explicit ObjectCache();
> -    ~ObjectCache();
> +  D();
> +  ~D();
> +};
>
> -private:
> -    Timer<ObjectCache> m_notificationPostTimer;
> +#ifndef PR12784_WORKAROUND
> +D::D() { }
> +D::~D() { }
> +#endif
> +
> +// CHECKGEN: define void @_ZN1DC1Ev(%class.D* %this)
> +// CHECKGEN: define void @_ZN1DC2Ev(%class.D* %this, i8** %vtt)
> +// CHECKGEN: define void @_ZN1DD1Ev(%class.D* %this)
> +// CHECKGEN: define void @_ZN1DD2Ev(%class.D* %this, i8** %vtt)
> +
> +// CHECKARM: define %class.D* @_ZN1DC1Ev(%class.D* returned %this)
> +// CHECKARM: define %class.D* @_ZN1DC2Ev(%class.D* returned %this, i8**
> %vtt)
> +// CHECKARM: define %class.D* @_ZN1DD1Ev(%class.D* returned %this)
> +// CHECKARM: define %class.D* @_ZN1DD2Ev(%class.D* returned %this, i8**
> %vtt)
> +
> +class E {
> +public:
> +  E();
> +  virtual ~E();
>  };
>
> -inline ObjectCache::ObjectCache() : m_notificationPostTimer(this, 0) { }
> -inline ObjectCache::~ObjectCache() { }
> +E* gete();
>
> -ObjectCache *test() {
> -  ObjectCache *dd = new ObjectCache();
> -  return dd;
> +void test_destructor() {
> +  E* e1 = new E();
> +  E* e2 = gete();
> +  e1->~E();
> +  e2->~E();
>  }
> +
> +// CHECKARM: define void @_Z15test_destructorv()
> +
> +// CHECKARM: {{%.*}} = call %class.E* @_ZN1EC1Ev(%class.E*
> +
> +// Verify that virtual calls to destructors are not marked with a
> 'returned'
> +// this parameter at the call site...
> +// CHECKARM: [[VFN:%.*]] = getelementptr inbounds %class.E* (%class.E*)**
> +// CHECKARM: [[THUNK:%.*]] = load %class.E* (%class.E*)** [[VFN]]
> +// CHECKARM: call %class.E* [[THUNK]](%class.E*
> +
> +// ...but static calls create declarations with 'returned' this
> +// CHECKARM: declare %class.E* @_ZN1EC1Ev(%class.E* returned)
>
> Modified: cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp Tue Jun 18
> 12:00:49 2013
> @@ -21,7 +21,7 @@ namespace no_elide_base {
>      Derived(const Other &O);
>    };
>
> -  // CHECK: define {{.*}}
> @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"*
> %this, %"struct.no_elide_base::Other"* %O) unnamed_addr
> +  // CHECK: define {{.*}}
> @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"*
> returned %this, %"struct.no_elide_base::Other"* %O) unnamed_addr
>    Derived::Derived(const Other &O)
>      // CHECK: call {{.*}} @_ZNK13no_elide_base5OthercvNS_4BaseEEv
>      // CHECK: call {{.*}} @_ZN13no_elide_base4BaseC2ERKS0_
>
> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=184205&r1=184204&r2=184205&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp Tue Jun 18
> 12:00:49 2013
> @@ -15,7 +15,7 @@ class A {
>  void no_constructor_destructor_infinite_recursion() {
>    A a;
>
> -// CHECK:      define linkonce_odr x86_thiscallcc %"class.basic::A"*
> @"\01??0A at basic@@QAE at XZ"(%"class.basic::A"* %this)
> +// CHECK:      define linkonce_odr x86_thiscallcc %"class.basic::A"*
> @"\01??0A at basic@@QAE at XZ"(%"class.basic::A"* returned %this)
>  // CHECK:        [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca
> %"class.basic::A"*, align 4
>  // CHECK-NEXT:   store %"class.basic::A"* %this, %"class.basic::A"**
> [[THIS_ADDR]], align 4
>  // CHECK-NEXT:   [[T1:%[.0-9A-Z_a-z]+]] = load %"class.basic::A"**
> [[THIS_ADDR]]
> @@ -34,7 +34,7 @@ struct B {
>
>  // Tests that we can define constructors outside the class (PR12784).
>  B::B() {
> -  // CHECK: define x86_thiscallcc %"struct.basic::B"* @"\01??0B at basic
> @@QAE at XZ"(%"struct.basic::B"* %this)
> +  // CHECK: define x86_thiscallcc %"struct.basic::B"* @"\01??0B at basic
> @@QAE at XZ"(%"struct.basic::B"* returned %this)
>    // CHECK: ret
>  }
>
> @@ -136,7 +136,7 @@ struct B : A {
>  };
>
>  B::B() {
> -  // CHECK: define x86_thiscallcc %"struct.constructors::B"*
> @"\01??0B at constructors@@QAE at XZ"(%"struct.constructors::B"* %this)
> +  // CHECK: define x86_thiscallcc %"struct.constructors::B"*
> @"\01??0B at constructors@@QAE at XZ"(%"struct.constructors::B"* returned %this)
>    // CHECK: call x86_thiscallcc %"struct.constructors::A"*
> @"\01??0A at constructors@@QAE at XZ"(%"struct.constructors::A"* %{{.*}})
>    // CHECK: ret
>  }
> @@ -146,7 +146,7 @@ struct C : virtual A {
>  };
>
>  C::C() {
> -  // CHECK: define x86_thiscallcc %"struct.constructors::C"*
> @"\01??0C at constructors@@QAE at XZ"(%"struct.constructors::C"* %this, i32
> %is_most_derived)
> +  // CHECK: define x86_thiscallcc %"struct.constructors::C"*
> @"\01??0C at constructors@@QAE at XZ"(%"struct.constructors::C"* returned
> %this, i32 %is_most_derived)
>    // TODO: make sure this works in the Release build too;
>    // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]],
> align 4
>    // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32*
> %[[IS_MOST_DERIVED_VAR]]
> @@ -175,7 +175,7 @@ struct D : C {
>  };
>
>  D::D() {
> -  // CHECK: define x86_thiscallcc %"struct.constructors::D"*
> @"\01??0D at constructors@@QAE at XZ"(%"struct.constructors::D"* %this, i32
> %is_most_derived) unnamed_addr
> +  // CHECK: define x86_thiscallcc %"struct.constructors::D"*
> @"\01??0D at constructors@@QAE at XZ"(%"struct.constructors::D"* returned
> %this, i32 %is_most_derived) unnamed_addr
>    // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]],
> align 4
>    // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32*
> %[[IS_MOST_DERIVED_VAR]]
>    // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32
> %[[IS_MOST_DERIVED_VAL]], 0
> @@ -196,7 +196,7 @@ struct E : virtual C {
>  };
>
>  E::E() {
> -  // CHECK: define x86_thiscallcc %"struct.constructors::E"*
> @"\01??0E at constructors@@QAE at XZ"(%"struct.constructors::E"* %this, i32
> %is_most_derived) unnamed_addr
> +  // CHECK: define x86_thiscallcc %"struct.constructors::E"*
> @"\01??0E at constructors@@QAE at XZ"(%"struct.constructors::E"* returned
> %this, i32 %is_most_derived) unnamed_addr
>    // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]],
> align 4
>    // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32*
> %[[IS_MOST_DERIVED_VAR]]
>    // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32
> %[[IS_MOST_DERIVED_VAL]], 0
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20131031/27b7a10e/attachment.html>


More information about the cfe-commits mailing list