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

Stephen Lin stephenwlin at gmail.com
Tue Jun 18 12:30:13 PDT 2013


Hmm, this apparently breaks tests when run on ARM, because the tests
are using the host triple...why are there tests that don't set an
explicit triple?

Does anyone know the standard procedure for resolving something like
this? I can make the tests triple-specific but I'm not sure why they
weren't in the first place. The optimization affects only ARM and MSVC
C++ ABI's so I cannot change the results for all targets.

-Stephen

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 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



More information about the cfe-commits mailing list