<div dir="ltr">On Tue, Jun 18, 2013 at 10:00 AM, Stephen Lin <span dir="ltr"><<a href="mailto:stephenwlin@gmail.com" target="_blank">stephenwlin@gmail.com</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote">
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: stephenwlin<br>
Date: Tue Jun 18 12:00:49 2013<br>
New Revision: 184205<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=184205&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=184205&view=rev</a><br>
Log:<br>
CodeGen: Have 'this'-returning constructors and destructors to take advantage of the new backend 'returned' attribute.<br></blockquote><div><br></div><div>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? =)</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
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).<br>

<br>
This patch also reverts a prior front-end only partial implementation of these optimizations, since it's no longer required.<br>
<br>
Modified:<br>
    cfe/trunk/lib/CodeGen/CGCXXABI.h<br>
    cfe/trunk/lib/CodeGen/CGCall.cpp<br>
    cfe/trunk/lib/CodeGen/CGClass.cpp<br>
    cfe/trunk/lib/CodeGen/CGVTables.cpp<br>
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp<br>
    cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>
    cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>
    cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
    cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp<br>
    cfe/trunk/test/CodeGenCXX/arm.cpp<br>
    cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp<br>
    cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp<br>
    cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGCXXABI.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCXXABI.h?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGCXXABI.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CGCXXABI.h Tue Jun 18 12:00:49 2013<br>
@@ -97,8 +97,12 @@ public:<br>
     return *MangleCtx;<br>
   }<br>
<br>
-  /// Returns true if the given instance method is one of the<br>
-  /// kinds that the ABI says returns 'this'.<br>
+  /// Returns true if the given constructor or destructor is one of the<br>
+  /// kinds that the ABI says returns 'this' (only applies when called<br>
+  /// non-virtually for destructors).<br>
+  ///<br>
+  /// There currently is no way to indicate if a destructor returns 'this'<br>
+  /// when called virtually, and code generation does not support the case.<br>
   virtual bool HasThisReturn(GlobalDecl GD) const { return false; }<br>
<br>
   /// Returns true if the given record type should be returned indirectly.<br>
@@ -214,10 +218,10 @@ public:<br>
                                         const CXXRecordDecl *BaseClassDecl) = 0;<br>
<br>
   /// Build the signature of the given constructor variant by adding<br>
-  /// any required parameters.  For convenience, ResTy has been<br>
-  /// initialized to 'void', and ArgTys has been initialized with the<br>
-  /// type of 'this' (although this may be changed by the ABI) and<br>
-  /// will have the formal parameters added to it afterwards.<br>
+  /// any required parameters.  For convenience, ArgTys has been initialized<br>
+  /// with the type of 'this' and ResTy has been initialized with the type of<br>
+  /// 'this' if HasThisReturn(GlobalDecl(Ctor, T)) is true or 'void' otherwise<br>
+  /// (although both may be changed by the ABI).<br>
   ///<br>
   /// If there are ever any ABIs where the implicit parameters are<br>
   /// intermixed with the formal parameters, we can address those<br>
@@ -230,9 +234,10 @@ public:<br>
   virtual llvm::BasicBlock *EmitCtorCompleteObjectHandler(CodeGenFunction &CGF);<br>
<br>
   /// Build the signature of the given destructor variant by adding<br>
-  /// any required parameters.  For convenience, ResTy has been<br>
-  /// initialized to 'void' and ArgTys has been initialized with the<br>
-  /// type of 'this' (although this may be changed by the ABI).<br>
+  /// any required parameters.  For convenience, ArgTys has been initialized<br>
+  /// with the type of 'this' and ResTy has been initialized with the type of<br>
+  /// 'this' if HasThisReturn(GlobalDecl(Dtor, T)) is true or 'void' otherwise<br>
+  /// (although both may be changed by the ABI).<br>
   virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,<br>
                                         CXXDtorType T,<br>
                                         CanQualType &ResTy,<br>
@@ -243,7 +248,8 @@ public:<br>
   /// possibly some extra data for constructors and destructors.<br>
   ///<br>
   /// ABIs may also choose to override the return type, which has been<br>
-  /// initialized with the formal return type of the function.<br>
+  /// initialized with the type of 'this' if HasThisReturn(CGF.CurGD) is true or<br>
+  /// the formal return type of the function otherwise.<br>
   virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF,<br>
                                            QualType &ResTy,<br>
                                            FunctionArgList &Params) = 0;<br>
@@ -252,13 +258,14 @@ public:<br>
   virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;<br>
<br>
   /// Emit the constructor call. Return the function that is called.<br>
-  virtual llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,<br>
-                                   const CXXConstructorDecl *D,<br>
-                                   CXXCtorType Type, bool ForVirtualBase,<br>
-                                   bool Delegating,<br>
-                                   llvm::Value *This,<br>
-                                   CallExpr::const_arg_iterator ArgBeg,<br>
-                                   CallExpr::const_arg_iterator ArgEnd) = 0;<br>
+  virtual RValue EmitConstructorCall(CodeGenFunction &CGF,<br>
+                                     const CXXConstructorDecl *D,<br>
+                                     CXXCtorType Type,<br>
+                                     bool ForVirtualBase, bool Delegating,<br>
+                                     ReturnValueSlot ReturnValue,<br>
+                                     llvm::Value *This,<br>
+                                     CallExpr::const_arg_iterator ArgBeg,<br>
+                                     CallExpr::const_arg_iterator ArgEnd) = 0;<br>
<br>
   /// Emit the ABI-specific virtual destructor call.<br>
   virtual RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGCall.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGCall.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGCall.cpp Tue Jun 18 12:00:49 2013<br>
@@ -200,7 +200,10 @@ CodeGenTypes::arrangeCXXConstructorDecla<br>
                                                CXXCtorType ctorKind) {<br>
   SmallVector<CanQualType, 16> argTypes;<br>
   argTypes.push_back(GetThisType(Context, D->getParent()));<br>
-  CanQualType resultType = Context.VoidTy;<br>
+<br>
+  GlobalDecl GD(D, ctorKind);<br>
+  CanQualType resultType =<br>
+    TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;<br>
<br>
   TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes);<br>
<br>
@@ -225,7 +228,10 @@ CodeGenTypes::arrangeCXXDestructor(const<br>
                                    CXXDtorType dtorKind) {<br>
   SmallVector<CanQualType, 2> argTypes;<br>
   argTypes.push_back(GetThisType(Context, D->getParent()));<br>
-  CanQualType resultType = Context.VoidTy;<br>
+<br>
+  GlobalDecl GD(D, dtorKind);<br>
+  CanQualType resultType =<br>
+    TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy;<br>
<br>
   TheCXXABI.BuildDestructorSignature(D, dtorKind, resultType, argTypes);<br>
<br>
@@ -1633,18 +1639,6 @@ static llvm::StoreInst *findDominatingSt<br>
   return store;<br>
 }<br>
<br>
-/// Check whether 'this' argument of a callsite matches 'this' of the caller.<br>
-static bool checkThisPointer(llvm::Value *ThisArg, llvm::Value *This) {<br>
-  if (ThisArg == This)<br>
-    return true;<br>
-  // Check whether ThisArg is a bitcast of This.<br>
-  llvm::BitCastInst *Bitcast;<br>
-  if ((Bitcast = dyn_cast<llvm::BitCastInst>(ThisArg)) &&<br>
-      Bitcast->getOperand(0) == This)<br>
-    return true;<br>
-  return false;<br>
-}<br>
-<br>
 void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,<br>
                                          bool EmitRetDbgLoc) {<br>
   // Functions with no result always return void.<br>
@@ -1741,19 +1735,6 @@ void CodeGenFunction::EmitFunctionEpilog<br>
     llvm_unreachable("Invalid ABI kind for return argument");<br>
   }<br>
<br>
-  // If this function returns 'this', the last instruction is a CallInst<br>
-  // that returns 'this', and 'this' argument of the CallInst points to<br>
-  // the same object as CXXThisValue, use the return value from the CallInst.<br>
-  // We will not need to keep 'this' alive through the callsite. It also enables<br>
-  // optimizations in the backend, such as tail call optimization.<br>
-  if (CalleeWithThisReturn && CGM.getCXXABI().HasThisReturn(CurGD)) {<br>
-    llvm::BasicBlock *IP = Builder.GetInsertBlock();<br>
-    llvm::CallInst *Callsite;<br>
-    if (!IP->empty() && (Callsite = dyn_cast<llvm::CallInst>(&IP->back())) &&<br>
-        Callsite->getCalledFunction() == CalleeWithThisReturn &&<br>
-        checkThisPointer(Callsite->getOperand(0), CXXThisValue))<br>
-      RV = Builder.CreateBitCast(Callsite, RetAI.getCoerceToType());<br>
-  }<br>
   llvm::Instruction *Ret = RV ? Builder.CreateRet(RV) : Builder.CreateRetVoid();<br>
   if (!RetDbgLoc.isUnknown())<br>
     Ret->setDebugLoc(RetDbgLoc);<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGClass.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGClass.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGClass.cpp Tue Jun 18 12:00:49 2013<br>
@@ -1661,11 +1661,9 @@ CodeGenFunction::EmitCXXConstructorCall(<br>
   }<br>
<br>
   // Non-trivial constructors are handled in an ABI-specific manner.<br>
-  llvm::Value *Callee = CGM.getCXXABI().EmitConstructorCall(*this, D, Type,<br>
-                            ForVirtualBase, Delegating, This, ArgBeg, ArgEnd);<br>
-  if (CGM.getCXXABI().HasThisReturn(CurGD) &&<br>
-      CGM.getCXXABI().HasThisReturn(GlobalDecl(D, Type)))<br>
-     CalleeWithThisReturn = Callee;<br>
+  CGM.getCXXABI().EmitConstructorCall(*this, D, Type,<br>
+                                      ForVirtualBase, Delegating,<br>
+                                      ReturnValueSlot(), This, ArgBeg, ArgEnd);<br>
 }<br>
<br>
 void<br>
@@ -1757,9 +1755,6 @@ CodeGenFunction::EmitDelegateCXXConstruc<br>
   llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(Ctor, CtorType);<br>
   EmitCall(CGM.getTypes().arrangeCXXConstructorDeclaration(Ctor, CtorType),<br>
            Callee, ReturnValueSlot(), DelegateArgs, Ctor);<br>
-  if (CGM.getCXXABI().HasThisReturn(CurGD) &&<br>
-      CGM.getCXXABI().HasThisReturn(GlobalDecl(Ctor, CtorType)))<br>
-     CalleeWithThisReturn = Callee;<br>
 }<br>
<br>
 namespace {<br>
@@ -1826,9 +1821,6 @@ void CodeGenFunction::EmitCXXDestructorC<br>
   EmitCXXMemberCall(DD, SourceLocation(), Callee, ReturnValueSlot(), This,<br>
                     VTT, getContext().getPointerType(getContext().VoidPtrTy),<br>
                     0, 0);<br>
-  if (CGM.getCXXABI().HasThisReturn(CurGD) &&<br>
-      CGM.getCXXABI().HasThisReturn(GlobalDecl(DD, Type)))<br>
-     CalleeWithThisReturn = Callee;<br>
 }<br>
<br>
 namespace {<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Tue Jun 18 12:00:49 2013<br>
@@ -287,8 +287,9 @@ void CodeGenFunction::GenerateThunk(llvm<br>
                                     GlobalDecl GD, const ThunkInfo &Thunk) {<br>
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(GD.getDecl());<br>
   const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>();<br>
-  QualType ResultType = FPT->getResultType();<br>
   QualType ThisType = MD->getThisType(getContext());<br>
+  QualType ResultType =<br>
+    CGM.getCXXABI().HasThisReturn(GD) ? ThisType : FPT->getResultType();<br>
<br>
   FunctionArgList FunctionArgs;<br>
<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Tue Jun 18 12:00:49 2013<br>
@@ -42,8 +42,7 @@ CodeGenFunction::CodeGenFunction(CodeGen<br>
     AutoreleaseResult(false), BlockInfo(0), BlockPointer(0),<br>
     LambdaThisCaptureField(0), NormalCleanupDest(0), NextCleanupDestIndex(1),<br>
     FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0),<br>
-    DebugInfo(0), DisableDebugInfo(false), CalleeWithThisReturn(0),<br>
-    DidCallStackSave(false),<br>
+    DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false),<br>
     IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),<br>
     NumReturnExprs(0), NumSimpleReturnExprs(0),<br>
     CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0),<br>
@@ -662,8 +661,12 @@ void CodeGenFunction::GenerateCode(Globa<br>
   QualType ResTy = FD->getResultType();<br>
<br>
   CurGD = GD;<br>
-  if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance())<br>
+  const CXXMethodDecl *MD;<br>
+  if ((MD = dyn_cast<CXXMethodDecl>(FD)) && MD->isInstance()) {<br>
+    if (CGM.getCXXABI().HasThisReturn(GD))<br>
+      ResTy = MD->getThisType(getContext());<br>
     CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args);<br>
+  }<br>
<br>
   for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)<br>
     Args.push_back(FD->getParamDecl(i));<br>
@@ -672,10 +675,6 @@ void CodeGenFunction::GenerateCode(Globa<br>
   if (Stmt *Body = FD->getBody()) BodyRange = Body->getSourceRange();<br>
   CurEHLocation = BodyRange.getEnd();<br>
<br>
-  // CalleeWithThisReturn keeps track of the last callee inside this function<br>
-  // that returns 'this'. Before starting the function, we set it to null.<br>
-  CalleeWithThisReturn = 0;<br>
-<br>
   // Emit the standard function prologue.<br>
   StartFunction(GD, ResTy, Fn, FnInfo, Args, BodyRange.getBegin());<br>
<br>
@@ -727,9 +726,6 @@ void CodeGenFunction::GenerateCode(Globa<br>
<br>
   // Emit the standard function epilogue.<br>
   FinishFunction(BodyRange.getEnd());<br>
-  // CalleeWithThisReturn keeps track of the last callee inside this function<br>
-  // that returns 'this'. After finishing the function, we set it to null.<br>
-  CalleeWithThisReturn = 0;<br>
<br>
   // If we haven't marked the function nothrow through other means, do<br>
   // a quick pass now to see if we can.<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.h?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenFunction.h (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.h Tue Jun 18 12:00:49 2013<br>
@@ -798,10 +798,6 @@ private:<br>
   CGDebugInfo *DebugInfo;<br>
   bool DisableDebugInfo;<br>
<br>
-  /// If the current function returns 'this', use the field to keep track of<br>
-  /// the callee that returns 'this'.<br>
-  llvm::Value *CalleeWithThisReturn;<br>
-<br>
   /// DidCallStackSave - Whether llvm.stacksave has been called. Used to avoid<br>
   /// calling llvm.stacksave for multiple VLAs in the same scope.<br>
   bool DidCallStackSave;<br>
<br>
Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Tue Jun 18 12:00:49 2013<br>
@@ -717,6 +717,14 @@ void CodeGenModule::SetFunctionAttribute<br>
   if (!IsIncompleteFunction)<br>
     SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F);<br>
<br>
+  if (getCXXABI().HasThisReturn(GD)) {<br>
+    llvm::Type *RetTy = F->getReturnType();<br>
+    assert(!F->arg_empty() &&<br>
+           F->arg_begin()->getType()->canLosslesslyBitCastTo(RetTy) &&<br>
+           "unexpected this return");<br>
+    F->addAttribute(1, llvm::Attribute::Returned);<br>
+  }<br>
+<br>
   // Only a few attributes are set on declarations; these may later be<br>
   // overridden by a definition.<br>
<br>
<br>
Modified: cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/ItaniumCXXABI.cpp Tue Jun 18 12:00:49 2013<br>
@@ -119,13 +119,14 @@ public:<br>
<br>
   void EmitInstanceFunctionProlog(CodeGenFunction &CGF);<br>
<br>
-  llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,<br>
-                           const CXXConstructorDecl *D,<br>
-                           CXXCtorType Type, bool ForVirtualBase,<br>
-                           bool Delegating,<br>
-                           llvm::Value *This,<br>
-                           CallExpr::const_arg_iterator ArgBeg,<br>
-                           CallExpr::const_arg_iterator ArgEnd);<br>
+  RValue EmitConstructorCall(CodeGenFunction &CGF,<br>
+                             const CXXConstructorDecl *D,<br>
+                             CXXCtorType Type,<br>
+                             bool ForVirtualBase, bool Delegating,<br>
+                             ReturnValueSlot ReturnValue,<br>
+                             llvm::Value *This,<br>
+                             CallExpr::const_arg_iterator ArgBeg,<br>
+                             CallExpr::const_arg_iterator ArgEnd);<br>
<br>
   RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,<br>
                                    const CXXDestructorDecl *Dtor,<br>
@@ -165,21 +166,11 @@ class ARMCXXABI : public ItaniumCXXABI {<br>
 public:<br>
   ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {}<br>
<br>
-  void BuildConstructorSignature(const CXXConstructorDecl *Ctor,<br>
-                                 CXXCtorType T,<br>
-                                 CanQualType &ResTy,<br>
-                                 SmallVectorImpl<CanQualType> &ArgTys);<br>
-<br>
-  void BuildDestructorSignature(const CXXDestructorDecl *Dtor,<br>
-                                CXXDtorType T,<br>
-                                CanQualType &ResTy,<br>
-                                SmallVectorImpl<CanQualType> &ArgTys);<br>
-<br>
-  void BuildInstanceFunctionParams(CodeGenFunction &CGF,<br>
-                                   QualType &ResTy,<br>
-                                   FunctionArgList &Params);<br>
-<br>
-  void EmitInstanceFunctionProlog(CodeGenFunction &CGF);<br>
+  bool HasThisReturn(GlobalDecl GD) const {<br>
+    return (isa<CXXConstructorDecl>(GD.getDecl()) || (<br>
+              isa<CXXDestructorDecl>(GD.getDecl()) &&<br>
+              GD.getDtorType() != Dtor_Deleting));<br>
+  }<br>
<br>
   void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy);<br>
<br>
@@ -191,15 +182,6 @@ public:<br>
                                      QualType ElementType);<br>
   llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF, llvm::Value *allocPtr,<br>
                                    CharUnits cookieSize);<br>
-<br>
-  /// \brief Returns true if the given instance method is one of the<br>
-  /// kinds that the ARM ABI says returns 'this'.<br>
-  bool HasThisReturn(GlobalDecl GD) const {<br>
-    const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(GD.getDecl());<br>
-    if (!MD) return false;<br>
-    return ((isa<CXXDestructorDecl>(MD) && GD.getDtorType() != Dtor_Deleting) ||<br>
-            (isa<CXXConstructorDecl>(MD)));<br>
-  }<br>
 };<br>
 }<br>
<br>
@@ -754,22 +736,14 @@ void ItaniumCXXABI::BuildConstructorSign<br>
                                 SmallVectorImpl<CanQualType> &ArgTys) {<br>
   ASTContext &Context = getContext();<br>
<br>
-  // 'this' is already there.<br>
+  // 'this' parameter is already there, as well as 'this' return if<br>
+  // HasThisReturn(GlobalDecl(Ctor, Type)) is true<br>
<br>
   // Check if we need to add a VTT parameter (which has type void **).<br>
   if (Type == Ctor_Base && Ctor->getParent()->getNumVBases() != 0)<br>
     ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));<br>
 }<br>
<br>
-/// The ARM ABI does the same as the Itanium ABI, but returns 'this'.<br>
-void ARMCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,<br>
-                                          CXXCtorType Type,<br>
-                                          CanQualType &ResTy,<br>
-                                SmallVectorImpl<CanQualType> &ArgTys) {<br>
-  ItaniumCXXABI::BuildConstructorSignature(Ctor, Type, ResTy, ArgTys);<br>
-  ResTy = ArgTys[0];<br>
-}<br>
-<br>
 /// The generic ABI passes 'this', plus a VTT if it's destroying a<br>
 /// base subobject.<br>
 void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,<br>
@@ -778,25 +752,14 @@ void ItaniumCXXABI::BuildDestructorSigna<br>
                                 SmallVectorImpl<CanQualType> &ArgTys) {<br>
   ASTContext &Context = getContext();<br>
<br>
-  // 'this' is already there.<br>
+  // 'this' parameter is already there, as well as 'this' return if<br>
+  // HasThisReturn(GlobalDecl(Dtor, Type)) is true<br>
<br>
   // Check if we need to add a VTT parameter (which has type void **).<br>
   if (Type == Dtor_Base && Dtor->getParent()->getNumVBases() != 0)<br>
     ArgTys.push_back(Context.getPointerType(Context.VoidPtrTy));<br>
 }<br>
<br>
-/// The ARM ABI does the same as the Itanium ABI, but returns 'this'<br>
-/// for non-deleting destructors.<br>
-void ARMCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,<br>
-                                         CXXDtorType Type,<br>
-                                         CanQualType &ResTy,<br>
-                                SmallVectorImpl<CanQualType> &ArgTys) {<br>
-  ItaniumCXXABI::BuildDestructorSignature(Dtor, Type, ResTy, ArgTys);<br>
-<br>
-  if (Type != Dtor_Deleting)<br>
-    ResTy = ArgTys[0];<br>
-}<br>
-<br>
 void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,<br>
                                                 QualType &ResTy,<br>
                                                 FunctionArgList &Params) {<br>
@@ -820,16 +783,6 @@ void ItaniumCXXABI::BuildInstanceFunctio<br>
   }<br>
 }<br>
<br>
-void ARMCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,<br>
-                                            QualType &ResTy,<br>
-                                            FunctionArgList &Params) {<br>
-  ItaniumCXXABI::BuildInstanceFunctionParams(CGF, ResTy, Params);<br>
-<br>
-  // Return 'this' from certain constructors and destructors.<br>
-  if (HasThisReturn(CGF.CurGD))<br>
-    ResTy = Params[0]->getType();<br>
-}<br>
-<br>
 void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {<br>
   /// Initialize the 'this' slot.<br>
   EmitThisParam(CGF);<br>
@@ -840,21 +793,24 @@ void ItaniumCXXABI::EmitInstanceFunction<br>
       = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)),<br>
                                "vtt");<br>
   }<br>
-}<br>
<br>
-void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {<br>
-  ItaniumCXXABI::EmitInstanceFunctionProlog(CGF);<br>
-<br>
-  /// Initialize the return slot to 'this' at the start of the<br>
-  /// function.<br>
+  /// If this is a function that the ABI specifies returns 'this', initialize<br>
+  /// the return slot to 'this' at the start of the function.<br>
+  ///<br>
+  /// Unlike the setting of return types, this is done within the ABI<br>
+  /// implementation instead of by clients of CGCXXABI because:<br>
+  /// 1) getThisValue is currently protected<br>
+  /// 2) in theory, an ABI could implement 'this' returns some other way;<br>
+  ///    HasThisReturn only specifies a contract, not the implementation<br>
   if (HasThisReturn(CGF.CurGD))<br>
     CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);<br>
 }<br>
<br>
-llvm::Value *ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,<br>
+RValue ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,<br>
                                         const CXXConstructorDecl *D,<br>
-                                        CXXCtorType Type, bool ForVirtualBase,<br>
-                                        bool Delegating,<br>
+                                        CXXCtorType Type,<br>
+                                        bool ForVirtualBase, bool Delegating,<br>
+                                        ReturnValueSlot ReturnValue,<br>
                                         llvm::Value *This,<br>
                                         CallExpr::const_arg_iterator ArgBeg,<br>
                                         CallExpr::const_arg_iterator ArgEnd) {<br>
@@ -864,9 +820,8 @@ llvm::Value *ItaniumCXXABI::EmitConstruc<br>
   llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);<br>
<br>
   // FIXME: Provide a source location here.<br>
-  CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,<br>
-                        VTT, VTTTy, ArgBeg, ArgEnd);<br>
-  return Callee;<br>
+  return CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValue,<br>
+                               This, VTT, VTTTy, ArgBeg, ArgEnd);<br>
 }<br>
<br>
 RValue ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,<br>
<br>
Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)<br>
+++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Tue Jun 18 12:00:49 2013<br>
@@ -28,6 +28,8 @@ class MicrosoftCXXABI : public CGCXXABI<br>
 public:<br>
   MicrosoftCXXABI(CodeGenModule &CGM) : CGCXXABI(CGM) {}<br>
<br>
+  bool HasThisReturn(GlobalDecl GD) const;<br>
+<br>
   bool isReturnTypeIndirect(const CXXRecordDecl *RD) const {<br>
     // Structures that are not C++03 PODs are always indirect.<br>
     return !RD->isPOD();<br>
@@ -71,13 +73,14 @@ public:<br>
<br>
   void EmitInstanceFunctionProlog(CodeGenFunction &CGF);<br>
<br>
-  llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,<br>
-                           const CXXConstructorDecl *D,<br>
-                           CXXCtorType Type, bool ForVirtualBase,<br>
-                           bool Delegating,<br>
-                           llvm::Value *This,<br>
-                           CallExpr::const_arg_iterator ArgBeg,<br>
-                           CallExpr::const_arg_iterator ArgEnd);<br>
+  RValue EmitConstructorCall(CodeGenFunction &CGF,<br>
+                             const CXXConstructorDecl *D,<br>
+                             CXXCtorType Type,<br>
+                             bool ForVirtualBase, bool Delegating,<br>
+                             ReturnValueSlot ReturnValue,<br>
+                             llvm::Value *This,<br>
+                             CallExpr::const_arg_iterator ArgBeg,<br>
+                             CallExpr::const_arg_iterator ArgEnd);<br>
<br>
   RValue EmitVirtualDestructorCall(CodeGenFunction &CGF,<br>
                                    const CXXDestructorDecl *Dtor,<br>
@@ -124,7 +127,6 @@ public:<br>
   llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,<br>
                                    llvm::Value *allocPtr,<br>
                                    CharUnits cookieSize);<br>
-  static bool needThisReturn(GlobalDecl GD);<br>
<br>
 private:<br>
   llvm::Constant *getZeroInt() {<br>
@@ -299,19 +301,15 @@ MicrosoftCXXABI::GetVirtualBaseClassOffs<br>
   return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);<br>
 }<br>
<br>
-bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) {<br>
-  const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl());<br>
-  return isa<CXXConstructorDecl>(MD);<br>
+bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const {<br>
+  return isa<CXXConstructorDecl>(GD.getDecl());<br>
 }<br>
<br>
 void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,<br>
                                  CXXCtorType Type,<br>
                                  CanQualType &ResTy,<br>
                                  SmallVectorImpl<CanQualType> &ArgTys) {<br>
-  // 'this' is already in place<br>
-<br>
-  // Ctor returns this ptr<br>
-  ResTy = ArgTys[0];<br>
+  // 'this' parameter and 'this' return are already in place<br>
<br>
   const CXXRecordDecl *Class = Ctor->getParent();<br>
   if (Class->getNumVBases()) {<br>
@@ -346,6 +344,7 @@ void MicrosoftCXXABI::BuildDestructorSig<br>
                                                CanQualType &ResTy,<br>
                                         SmallVectorImpl<CanQualType> &ArgTys) {<br>
   // 'this' is already in place<br>
+<br>
   // TODO: 'for base' flag<br>
<br>
   if (Type == Dtor_Deleting) {<br>
@@ -366,9 +365,6 @@ void MicrosoftCXXABI::BuildInstanceFunct<br>
                                                   QualType &ResTy,<br>
                                                   FunctionArgList &Params) {<br>
   BuildThisParam(CGF, Params);<br>
-  if (needThisReturn(CGF.CurGD)) {<br>
-    ResTy = Params[0]->getType();<br>
-  }<br>
<br>
   ASTContext &Context = getContext();<br>
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());<br>
@@ -393,9 +389,17 @@ void MicrosoftCXXABI::BuildInstanceFunct<br>
<br>
 void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {<br>
   EmitThisParam(CGF);<br>
-  if (needThisReturn(CGF.CurGD)) {<br>
+<br>
+  /// If this is a function that the ABI specifies returns 'this', initialize<br>
+  /// the return slot to 'this' at the start of the function.<br>
+  ///<br>
+  /// Unlike the setting of return types, this is done within the ABI<br>
+  /// implementation instead of by clients of CGCXXABI because:<br>
+  /// 1) getThisValue is currently protected<br>
+  /// 2) in theory, an ABI could implement 'this' returns some other way;<br>
+  ///    HasThisReturn only specifies a contract, not the implementation<br>
+  if (HasThisReturn(CGF.CurGD))<br>
     CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);<br>
-  }<br>
<br>
   const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());<br>
   if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) {<br>
@@ -417,11 +421,13 @@ void MicrosoftCXXABI::EmitInstanceFuncti<br>
   }<br>
 }<br>
<br>
-llvm::Value *MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,<br>
-                                          const CXXConstructorDecl *D,<br>
-                                          CXXCtorType Type, bool ForVirtualBase,<br>
-                                          bool Delegating,<br>
-                                          llvm::Value *This,<br>
+RValue MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,<br>
+                                            const CXXConstructorDecl *D,<br>
+                                            CXXCtorType Type,<br>
+                                            bool ForVirtualBase,<br>
+                                            bool Delegating,<br>
+                                            ReturnValueSlot ReturnValue,<br>
+                                            llvm::Value *This,<br>
                                           CallExpr::const_arg_iterator ArgBeg,<br>
                                           CallExpr::const_arg_iterator ArgEnd) {<br>
   assert(Type == Ctor_Complete || Type == Ctor_Base);<br>
@@ -435,10 +441,9 @@ llvm::Value *MicrosoftCXXABI::EmitConstr<br>
   }<br>
<br>
   // FIXME: Provide a source location here.<br>
-  CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This,<br>
-                        ImplicitParam, ImplicitParamTy,<br>
-                        ArgBeg, ArgEnd);<br>
-  return Callee;<br>
+  return CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValue,<br>
+                               This, ImplicitParam, ImplicitParamTy,<br>
+                               ArgBeg, ArgEnd);<br>
 }<br>
<br>
 RValue MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/arm.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/arm.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/arm.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/arm.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/arm.cpp Tue Jun 18 12:00:49 2013<br>
@@ -52,19 +52,19 @@ namespace test1 {<br>
     a.bar();<br>
   }<br>
<br>
-  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* %this, i32 %i) unnamed_addr<br>
+  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* returned %this, i32 %i) unnamed_addr<br>
   // CHECK:   [[THIS:%.*]] = alloca [[A]]*, align 4<br>
   // CHECK:   store [[A]]* {{.*}}, [[A]]** [[THIS]]<br>
   // CHECK:   [[THIS1:%.*]] = load [[A]]** [[THIS]]<br>
-  // CHECK:   [[THIS2:%.*]] = call [[A]]* @_ZN5test11AC2Ei(<br>
-  // CHECK:   ret [[A]]* [[THIS2]]<br>
+  // CHECK:   {{%.*}} = call [[A]]* @_ZN5test11AC2Ei(<br>
+  // CHECK:   ret [[A]]* [[THIS1]]<br>
<br>
-  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* %this) unnamed_addr<br>
+  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* returned %this) unnamed_addr<br>
   // CHECK:   [[THIS:%.*]] = alloca [[A]]*, align 4<br>
   // CHECK:   store [[A]]* {{.*}}, [[A]]** [[THIS]]<br>
   // CHECK:   [[THIS1:%.*]] = load [[A]]** [[THIS]]<br>
-  // CHECK:   [[THIS2:%.*]] = call [[A]]* @_ZN5test11AD2Ev(<br>
-  // CHECK:   ret [[A]]* [[THIS2]]<br>
+  // CHECK:   {{%.*}} = call [[A]]* @_ZN5test11AD2Ev(<br>
+  // CHECK:   ret [[A]]* [[THIS1]]<br>
 }<br>
<br>
 // Awkward virtual cases.<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/constructor-destructor-return-this.cpp Tue Jun 18 12:00:49 2013<br>
@@ -1,60 +1,120 @@<br>
-//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios3.0 -target-abi apcs-gnu | FileCheck %s<br>
+//RUN: %clang_cc1 %s -emit-llvm -o - -triple=i686-unknown-linux | FileCheck --check-prefix=CHECKGEN %s<br>
+//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios3.0 -target-abi apcs-gnu | FileCheck --check-prefix=CHECKARM %s<br>
+//RUN: %clang_cc1 %s -emit-llvm -o - -DPR12784_WORKAROUND -triple=x86_64-pc-win32 -cxx-abi microsoft | FileCheck --check-prefix=CHECKMS %s<br>
<br>
-// For constructors/desctructors that return 'this', if there exists a callsite<br>
-// that returns 'this' and is immediately before the return instruction, make<br>
-// sure we are using the return value from the callsite.<br>
-// rdar://12818789<br>
-<br>
-// CHECK: define linkonce_odr [[A:%.*]] @_ZN11ObjectCacheC1Ev([[A]] %this) unnamed_addr<br>
-// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN11ObjectCacheC2Ev(<br>
-// CHECK-NEXT: ret [[A]] [[THIS1]]<br>
-<br>
-// CHECK: define linkonce_odr [[A:%.*]] @_ZN5TimerI11ObjectCacheEC1EPS0_MS0_FvPS1_E([[A]] %this<br>
-// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN5TimerI11ObjectCacheEC2EPS0_MS0_FvPS1_E(<br>
-// CHECK-NEXT: ret [[A]] [[THIS1]]<br>
-<br>
-// CHECK: define linkonce_odr [[A:%.*]] @_ZN5TimerI11ObjectCacheED1Ev([[A]] %this) unnamed_addr<br>
-// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN5TimerI11ObjectCacheED2Ev(<br>
-// CHECK-NEXT: ret [[A]] [[THIS1]]<br>
-<br>
-// CHECK: define linkonce_odr [[A:%.*]] @_ZN5TimerI11ObjectCacheED2Ev([[A]] %this) unnamed_addr<br>
-// CHECK: [[THIS1:%.*]] = call [[B:%.*]] @_ZN9TimerBaseD2Ev(<br>
-// CHECK-NEXT: [[THIS2:%.*]] = bitcast [[B]] [[THIS1]] to [[A]]<br>
-// CHECK-NEXT: ret [[A]] [[THIS2]]<br>
+// FIXME: Add checks to ensure that Microsoft destructors do not return 'this'<br>
+// once PR12784 is resolved<br>
<br>
-class TimerBase {<br>
+// Make sure we attach the 'returned' attribute to the 'this' parameter of<br>
+// constructors and destructors which return this (and only these cases)<br>
+<br>
+class A {<br>
 public:<br>
-    TimerBase();<br>
-    virtual ~TimerBase();<br>
+  A();<br>
+  ~A();<br>
+<br>
+private:<br>
+  int x_;<br>
 };<br>
<br>
-template <typename TimerFiredClass> class Timer : public TimerBase {<br>
+class B : public A {<br>
 public:<br>
-    typedef void (TimerFiredClass::*TimerFiredFunction)(Timer*);<br>
-<br>
-    Timer(TimerFiredClass* o, TimerFiredFunction f)<br>
-        : m_object(o), m_function(f) { }<br>
+  B(int *i);<br>
+  ~B();<br>
<br>
 private:<br>
-    virtual void fired() { (m_object->*m_function)(this); }<br>
+  int *i_;<br>
+};<br>
<br>
-    TimerFiredClass* m_object;<br>
-    TimerFiredFunction m_function;<br>
+B::B(int *i) : i_(i) { }<br>
+#ifndef PR12784_WORKAROUND<br>
+B::~B() { }<br>
+#endif<br>
+<br>
+// CHECKGEN: define void @_ZN1BC1EPi(%class.B* %this, i32* %i)<br>
+// CHECKGEN: define void @_ZN1BC2EPi(%class.B* %this, i32* %i)<br>
+// CHECKGEN: define void @_ZN1BD1Ev(%class.B* %this)<br>
+// CHECKGEN: define void @_ZN1BD2Ev(%class.B* %this)<br>
+<br>
+// CHECKARM: define %class.B* @_ZN1BC1EPi(%class.B* returned %this, i32* %i)<br>
+// CHECKARM: define %class.B* @_ZN1BC2EPi(%class.B* returned %this, i32* %i)<br>
+// CHECKARM: define %class.B* @_ZN1BD1Ev(%class.B* returned %this)<br>
+// CHECKARM: define %class.B* @_ZN1BD2Ev(%class.B* returned %this)<br>
+<br>
+// CHECKMS: define %class.B* @"\01??0B@@QEAA@PEAH@Z"(%class.B* returned %this, i32* %i)<br>
+<br>
+class C : public A, public B {<br>
+public:<br>
+  C(int *i, char *c);<br>
+  virtual ~C();<br>
+private:<br>
+  char *c_;<br>
 };<br>
<br>
-class ObjectCache {<br>
+C::C(int *i, char *c) : B(i), c_(c) { }<br>
+#ifndef PR12784_WORKAROUND<br>
+C::~C() { }<br>
+#endif<br>
+<br>
+// CHECKGEN: define void @_ZN1CC1EPiPc(%class.C* %this, i32* %i, i8* %c)<br>
+// CHECKGEN: define void @_ZN1CC2EPiPc(%class.C* %this, i32* %i, i8* %c)<br>
+// CHECKGEN: define void @_ZN1CD0Ev(%class.C* %this)<br>
+// CHECKGEN: define void @_ZN1CD1Ev(%class.C* %this)<br>
+// CHECKGEN: define void @_ZN1CD2Ev(%class.C* %this)<br>
+<br>
+// CHECKARM: define %class.C* @_ZN1CC1EPiPc(%class.C* returned %this, i32* %i, i8* %c)<br>
+// CHECKARM: define %class.C* @_ZN1CC2EPiPc(%class.C* returned %this, i32* %i, i8* %c)<br>
+// CHECKARM: define void @_ZN1CD0Ev(%class.C* %this)<br>
+// CHECKARM: define %class.C* @_ZN1CD1Ev(%class.C* returned %this)<br>
+// CHECKARM: define %class.C* @_ZN1CD2Ev(%class.C* returned %this)<br>
+<br>
+// CHECKMS: define %class.C* @"\01??0C@@QEAA@PEAHPEAD@Z"(%class.C* returned %this, i32* %i, i8* %c)<br>
+<br>
+class D : public virtual A {<br>
 public:<br>
-    explicit ObjectCache();<br>
-    ~ObjectCache();<br>
+  D();<br>
+  ~D();<br>
+};<br>
<br>
-private:<br>
-    Timer<ObjectCache> m_notificationPostTimer;<br>
+#ifndef PR12784_WORKAROUND<br>
+D::D() { }<br>
+D::~D() { }<br>
+#endif<br>
+<br>
+// CHECKGEN: define void @_ZN1DC1Ev(%class.D* %this)<br>
+// CHECKGEN: define void @_ZN1DC2Ev(%class.D* %this, i8** %vtt)<br>
+// CHECKGEN: define void @_ZN1DD1Ev(%class.D* %this)<br>
+// CHECKGEN: define void @_ZN1DD2Ev(%class.D* %this, i8** %vtt)<br>
+<br>
+// CHECKARM: define %class.D* @_ZN1DC1Ev(%class.D* returned %this)<br>
+// CHECKARM: define %class.D* @_ZN1DC2Ev(%class.D* returned %this, i8** %vtt)<br>
+// CHECKARM: define %class.D* @_ZN1DD1Ev(%class.D* returned %this)<br>
+// CHECKARM: define %class.D* @_ZN1DD2Ev(%class.D* returned %this, i8** %vtt)<br>
+<br>
+class E {<br>
+public:<br>
+  E();<br>
+  virtual ~E();<br>
 };<br>
<br>
-inline ObjectCache::ObjectCache() : m_notificationPostTimer(this, 0) { }<br>
-inline ObjectCache::~ObjectCache() { }<br>
+E* gete();<br>
<br>
-ObjectCache *test() {<br>
-  ObjectCache *dd = new ObjectCache();<br>
-  return dd;<br>
+void test_destructor() {<br>
+  E* e1 = new E();<br>
+  E* e2 = gete();<br>
+  e1->~E();<br>
+  e2->~E();<br>
 }<br>
+<br>
+// CHECKARM: define void @_Z15test_destructorv()<br>
+<br>
+// CHECKARM: {{%.*}} = call %class.E* @_ZN1EC1Ev(%class.E*<br>
+<br>
+// Verify that virtual calls to destructors are not marked with a 'returned'<br>
+// this parameter at the call site...<br>
+// CHECKARM: [[VFN:%.*]] = getelementptr inbounds %class.E* (%class.E*)**<br>
+// CHECKARM: [[THUNK:%.*]] = load %class.E* (%class.E*)** [[VFN]]<br>
+// CHECKARM: call %class.E* [[THUNK]](%class.E*<br>
+<br>
+// ...but static calls create declarations with 'returned' this<br>
+// CHECKARM: declare %class.E* @_ZN1EC1Ev(%class.E* returned)<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/copy-constructor-elim-2.cpp Tue Jun 18 12:00:49 2013<br>
@@ -21,7 +21,7 @@ namespace no_elide_base {<br>
     Derived(const Other &O);<br>
   };<br>
<br>
-  // CHECK: define {{.*}} @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* %this, %"struct.no_elide_base::Other"* %O) unnamed_addr<br>
+  // CHECK: define {{.*}} @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* returned %this, %"struct.no_elide_base::Other"* %O) unnamed_addr<br>
   Derived::Derived(const Other &O)<br>
     // CHECK: call {{.*}} @_ZNK13no_elide_base5OthercvNS_4BaseEEv<br>
     // CHECK: call {{.*}} @_ZN13no_elide_base4BaseC2ERKS0_<br>
<br>
Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=184205&r1=184204&r2=184205&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp?rev=184205&r1=184204&r2=184205&view=diff</a><br>

==============================================================================<br>
--- cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp (original)<br>
+++ cfe/trunk/test/CodeGenCXX/microsoft-abi-structors.cpp Tue Jun 18 12:00:49 2013<br>
@@ -15,7 +15,7 @@ class A {<br>
 void no_constructor_destructor_infinite_recursion() {<br>
   A a;<br>
<br>
-// CHECK:      define linkonce_odr x86_thiscallcc %"class.basic::A"* @"\01??0A@basic@@QAE@XZ"(%"class.basic::A"* %this)<br>
+// CHECK:      define linkonce_odr x86_thiscallcc %"class.basic::A"* @"\01??0A@basic@@QAE@XZ"(%"class.basic::A"* returned %this)<br>
 // CHECK:        [[THIS_ADDR:%[.0-9A-Z_a-z]+]] = alloca %"class.basic::A"*, align 4<br>
 // CHECK-NEXT:   store %"class.basic::A"* %this, %"class.basic::A"** [[THIS_ADDR]], align 4<br>
 // CHECK-NEXT:   [[T1:%[.0-9A-Z_a-z]+]] = load %"class.basic::A"** [[THIS_ADDR]]<br>
@@ -34,7 +34,7 @@ struct B {<br>
<br>
 // Tests that we can define constructors outside the class (PR12784).<br>
 B::B() {<br>
-  // CHECK: define x86_thiscallcc %"struct.basic::B"* @"\01??0B@basic@@QAE@XZ"(%"struct.basic::B"* %this)<br>
+  // CHECK: define x86_thiscallcc %"struct.basic::B"* @"\01??0B@basic@@QAE@XZ"(%"struct.basic::B"* returned %this)<br>
   // CHECK: ret<br>
 }<br>
<br>
@@ -136,7 +136,7 @@ struct B : A {<br>
 };<br>
<br>
 B::B() {<br>
-  // CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* %this)<br>
+  // CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* returned %this)<br>
   // CHECK: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@XZ"(%"struct.constructors::A"* %{{.*}})<br>
   // CHECK: ret<br>
 }<br>
@@ -146,7 +146,7 @@ struct C : virtual A {<br>
 };<br>
<br>
 C::C() {<br>
-  // CHECK: define x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %this, i32 %is_most_derived)<br>
+  // CHECK: define x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* returned %this, i32 %is_most_derived)<br>
   // TODO: make sure this works in the Release build too;<br>
   // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4<br>
   // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]]<br>
@@ -175,7 +175,7 @@ struct D : C {<br>
 };<br>
<br>
 D::D() {<br>
-  // CHECK: define x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* %this, i32 %is_most_derived) unnamed_addr<br>
+  // CHECK: define x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* returned %this, i32 %is_most_derived) unnamed_addr<br>
   // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4<br>
   // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]]<br>
   // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0<br>
@@ -196,7 +196,7 @@ struct E : virtual C {<br>
 };<br>
<br>
 E::E() {<br>
-  // CHECK: define x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* %this, i32 %is_most_derived) unnamed_addr<br>
+  // CHECK: define x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* returned %this, i32 %is_most_derived) unnamed_addr<br>
   // CHECK: store i32 %is_most_derived, i32* %[[IS_MOST_DERIVED_VAR:.*]], align 4<br>
   // CHECK: %[[IS_MOST_DERIVED_VAL:.*]] = load i32* %[[IS_MOST_DERIVED_VAR]]<br>
   // CHECK: %[[SHOULD_CALL_VBASE_CTORS:.*]] = icmp ne i32 %[[IS_MOST_DERIVED_VAL]], 0<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div></div>