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 10:00:50 PDT 2013


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





More information about the cfe-commits mailing list