diff options
| -rw-r--r-- | clang/lib/CodeGen/CGCXXABI.h | 43 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 35 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 13 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGExprCXX.cpp | 26 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGVTables.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 16 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenModule.cpp | 8 | ||||
| -rw-r--r-- | clang/lib/CodeGen/ItaniumCXXABI.cpp | 123 | ||||
| -rw-r--r-- | clang/lib/CodeGen/MicrosoftCXXABI.cpp | 72 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/arm.cpp | 12 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/constructor-destructor-return-this.cpp | 141 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/copy-constructor-elim-2.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/copy-constructor-synthesis-2.cpp | 2 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/default-constructor-template-member.cpp | 3 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/mangle-template.cpp | 4 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-structors.cpp | 12 | ||||
| -rw-r--r-- | clang/test/CodeGenCXX/virtual-base-destructor-call.cpp | 12 | 
18 files changed, 272 insertions, 259 deletions
diff --git a/clang/lib/CodeGen/CGCXXABI.h b/clang/lib/CodeGen/CGCXXABI.h index cfcba090cc3..04bc54b6bfc 100644 --- a/clang/lib/CodeGen/CGCXXABI.h +++ b/clang/lib/CodeGen/CGCXXABI.h @@ -97,12 +97,8 @@ public:      return *MangleCtx;    } -  /// 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. +  /// Returns true if the given instance method is one of the +  /// kinds that the ABI says returns 'this'.    virtual bool HasThisReturn(GlobalDecl GD) const { return false; }    /// Returns true if the given record type should be returned indirectly. @@ -218,10 +214,10 @@ public:                                          const CXXRecordDecl *BaseClassDecl) = 0;    /// Build the signature of the given constructor variant by adding -  /// 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). +  /// 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.    ///    /// If there are ever any ABIs where the implicit parameters are    /// intermixed with the formal parameters, we can address those @@ -235,10 +231,9 @@ public:                                                            const CXXRecordDecl *RD);    /// Build the signature of the given destructor variant by adding -  /// 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). +  /// 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).    virtual void BuildDestructorSignature(const CXXDestructorDecl *Dtor,                                          CXXDtorType T,                                          CanQualType &ResTy, @@ -249,8 +244,7 @@ public:    /// possibly some extra data for constructors and destructors.    ///    /// ABIs may also choose to override the return type, which has been -  /// initialized with the type of 'this' if HasThisReturn(CGF.CurGD) is true or -  /// the formal return type of the function otherwise. +  /// initialized with the formal return type of the function.    virtual void BuildInstanceFunctionParams(CodeGenFunction &CGF,                                             QualType &ResTy,                                             FunctionArgList &Params) = 0; @@ -259,20 +253,21 @@ public:    virtual void EmitInstanceFunctionProlog(CodeGenFunction &CGF) = 0;    /// Emit the constructor call. Return the function that is called. -  virtual void EmitConstructorCall(CodeGenFunction &CGF, +  virtual llvm::Value *EmitConstructorCall(CodeGenFunction &CGF,                                     const CXXConstructorDecl *D, -                                   CXXCtorType Type, -                                   bool ForVirtualBase, bool Delegating, +                                   CXXCtorType Type, bool ForVirtualBase, +                                   bool Delegating,                                     llvm::Value *This,                                     CallExpr::const_arg_iterator ArgBeg,                                     CallExpr::const_arg_iterator ArgEnd) = 0;    /// Emit the ABI-specific virtual destructor call. -  virtual void EmitVirtualDestructorCall(CodeGenFunction &CGF, -                                         const CXXDestructorDecl *Dtor, -                                         CXXDtorType DtorType, -                                         SourceLocation CallLoc, -                                         llvm::Value *This) = 0; +  virtual RValue EmitVirtualDestructorCall(CodeGenFunction &CGF, +                                           const CXXDestructorDecl *Dtor, +                                           CXXDtorType DtorType, +                                           SourceLocation CallLoc, +                                           ReturnValueSlot ReturnValue, +                                           llvm::Value *This) = 0;    /// Emit any tables needed to implement virtual inheritance.  For Itanium,    /// this emits virtual table tables.  For the MSVC++ ABI, this emits virtual diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index f74ae391205..80446393d5b 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -200,10 +200,7 @@ CodeGenTypes::arrangeCXXConstructorDeclaration(const CXXConstructorDecl *D,                                                 CXXCtorType ctorKind) {    SmallVector<CanQualType, 16> argTypes;    argTypes.push_back(GetThisType(Context, D->getParent())); - -  GlobalDecl GD(D, ctorKind); -  CanQualType resultType = -    TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy; +  CanQualType resultType = Context.VoidTy;    TheCXXABI.BuildConstructorSignature(D, ctorKind, resultType, argTypes); @@ -228,10 +225,7 @@ CodeGenTypes::arrangeCXXDestructor(const CXXDestructorDecl *D,                                     CXXDtorType dtorKind) {    SmallVector<CanQualType, 2> argTypes;    argTypes.push_back(GetThisType(Context, D->getParent())); - -  GlobalDecl GD(D, dtorKind); -  CanQualType resultType = -    TheCXXABI.HasThisReturn(GD) ? argTypes.front() : Context.VoidTy; +  CanQualType resultType = Context.VoidTy;    TheCXXABI.BuildDestructorSignature(D, dtorKind, resultType, argTypes); @@ -1639,6 +1633,18 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {    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. @@ -1735,6 +1741,19 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI,      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); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index cceae6873a6..a32c152fee2 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1662,8 +1662,11 @@ CodeGenFunction::EmitCXXConstructorCall(const CXXConstructorDecl *D,    }    // Non-trivial constructors are handled in an ABI-specific manner. -  CGM.getCXXABI().EmitConstructorCall(*this, D, Type, ForVirtualBase, -                                      Delegating, This, ArgBeg, ArgEnd); +  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;  }  void @@ -1755,6 +1758,9 @@ CodeGenFunction::EmitDelegateCXXConstructorCall(const CXXConstructorDecl *Ctor,    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 { @@ -1821,6 +1827,9 @@ void CodeGenFunction::EmitCXXDestructorCall(const CXXDestructorDecl *DD,    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 { diff --git a/clang/lib/CodeGen/CGExprCXX.cpp b/clang/lib/CodeGen/CGExprCXX.cpp index 438657ae223..60a70f8e07f 100644 --- a/clang/lib/CodeGen/CGExprCXX.cpp +++ b/clang/lib/CodeGen/CGExprCXX.cpp @@ -280,15 +280,16 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,    // We also don't emit a virtual call if the base expression has a record type    // because then we know what the type is.    bool UseVirtualCall = CanUseVirtualCall && !DevirtualizedMethod; -  llvm::Value *Callee; +  llvm::Value *Callee;    if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) { -    assert(CE->arg_begin() == CE->arg_end() && -           "Destructor shouldn't have explicit parameters"); -    assert(ReturnValue.isNull() && "Destructor shouldn't have return value");      if (UseVirtualCall) { -      CGM.getCXXABI().EmitVirtualDestructorCall(*this, Dtor, Dtor_Complete, -                                                CE->getExprLoc(), This); +      assert(CE->arg_begin() == CE->arg_end() && +             "Virtual destructor shouldn't have explicit parameters"); +      return CGM.getCXXABI().EmitVirtualDestructorCall(*this, Dtor, +                                                       Dtor_Complete, +                                                       CE->getExprLoc(), +                                                       ReturnValue, This);      } else {        if (getLangOpts().AppleKext &&            MD->isVirtual() && @@ -301,16 +302,12 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE,            cast<CXXDestructorDecl>(DevirtualizedMethod);          Callee = CGM.GetAddrOfFunction(GlobalDecl(DDtor, Dtor_Complete), Ty);        } -      EmitCXXMemberCall(MD, CE->getExprLoc(), Callee, ReturnValue, This, -                        /*ImplicitParam=*/0, QualType(), 0, 0);      } -    return RValue::get(0); -  } -   -  if (const CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(MD)) { +  } else if (const CXXConstructorDecl *Ctor = +               dyn_cast<CXXConstructorDecl>(MD)) {      Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty);    } else if (UseVirtualCall) { -    Callee = BuildVirtualCall(MD, This, Ty);  +      Callee = BuildVirtualCall(MD, This, Ty);     } else {      if (getLangOpts().AppleKext &&          MD->isVirtual() && @@ -1416,7 +1413,8 @@ static void EmitObjectDelete(CodeGenFunction &CGF,          // FIXME: Provide a source location here.          CXXDtorType DtorType = UseGlobalDelete ? Dtor_Complete : Dtor_Deleting;          CGF.CGM.getCXXABI().EmitVirtualDestructorCall(CGF, Dtor, DtorType, -                                                      SourceLocation(), Ptr); +                                                      SourceLocation(), +                                                      ReturnValueSlot(), Ptr);          if (UseGlobalDelete) {            CGF.PopCleanupBlock(); diff --git a/clang/lib/CodeGen/CGVTables.cpp b/clang/lib/CodeGen/CGVTables.cpp index 9c4a5e0cdad..e15639d31dd 100644 --- a/clang/lib/CodeGen/CGVTables.cpp +++ b/clang/lib/CodeGen/CGVTables.cpp @@ -287,9 +287,8 @@ void CodeGenFunction::GenerateThunk(llvm::Function *Fn,                                      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; diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index e8469e64802..297fc655e44 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -42,7 +42,8 @@ CodeGenFunction::CodeGenFunction(CodeGenModule &cgm, bool suppressNewContext)      AutoreleaseResult(false), BlockInfo(0), BlockPointer(0),      LambdaThisCaptureField(0), NormalCleanupDest(0), NextCleanupDestIndex(1),      FirstBlockInfo(0), EHResumeBlock(0), ExceptionSlot(0), EHSelectorSlot(0), -    DebugInfo(0), DisableDebugInfo(false), DidCallStackSave(false), +    DebugInfo(0), DisableDebugInfo(false), CalleeWithThisReturn(0), +    DidCallStackSave(false),      IndirectBranch(0), SwitchInsn(0), CaseRangeBlock(0), UnreachableBlock(0),      NumReturnExprs(0), NumSimpleReturnExprs(0),      CXXABIThisDecl(0), CXXABIThisValue(0), CXXThisValue(0), @@ -661,12 +662,8 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,    QualType ResTy = FD->getResultType();    CurGD = GD; -  const CXXMethodDecl *MD; -  if ((MD = dyn_cast<CXXMethodDecl>(FD)) && MD->isInstance()) { -    if (CGM.getCXXABI().HasThisReturn(GD)) -      ResTy = MD->getThisType(getContext()); +  if (isa<CXXMethodDecl>(FD) && cast<CXXMethodDecl>(FD)->isInstance())      CGM.getCXXABI().BuildInstanceFunctionParams(*this, ResTy, Args); -  }    for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i)      Args.push_back(FD->getParamDecl(i)); @@ -675,6 +672,10 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,    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()); @@ -726,6 +727,9 @@ void CodeGenFunction::GenerateCode(GlobalDecl GD, llvm::Function *Fn,    // 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. diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index b7e2086c75a..7b18edf3215 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -798,6 +798,10 @@ 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; diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index 3298d5a0899..efff4b118d5 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -722,14 +722,6 @@ void CodeGenModule::SetFunctionAttributes(GlobalDecl GD,    if (!IsIncompleteFunction)      SetLLVMFunctionAttributes(FD, getTypes().arrangeGlobalDeclaration(GD), F); -  if (getCXXABI().HasThisReturn(GD)) { -    assert(!F->arg_empty() && -           F->arg_begin()->getType() -             ->canLosslesslyBitCastTo(F->getReturnType()) && -           "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. diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp index 51c1dc5e590..36b3da58b99 100644 --- a/clang/lib/CodeGen/ItaniumCXXABI.cpp +++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp @@ -119,17 +119,20 @@ public:    void EmitInstanceFunctionProlog(CodeGenFunction &CGF); -  void EmitConstructorCall(CodeGenFunction &CGF, -                           const CXXConstructorDecl *D, CXXCtorType Type, -                           bool ForVirtualBase, bool Delegating, +  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); -  void EmitVirtualDestructorCall(CodeGenFunction &CGF, -                                 const CXXDestructorDecl *Dtor, -                                 CXXDtorType DtorType, SourceLocation CallLoc, -                                 llvm::Value *This); +  RValue EmitVirtualDestructorCall(CodeGenFunction &CGF, +                                   const CXXDestructorDecl *Dtor, +                                   CXXDtorType DtorType, +                                   SourceLocation CallLoc, +                                   ReturnValueSlot ReturnValue, +                                   llvm::Value *This);    void EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes Linkage,                                      const CXXRecordDecl *RD); @@ -165,11 +168,21 @@ class ARMCXXABI : public ItaniumCXXABI {  public:    ARMCXXABI(CodeGen::CodeGenModule &CGM) : ItaniumCXXABI(CGM, /*ARM*/ true) {} -  bool HasThisReturn(GlobalDecl GD) const { -    return (isa<CXXConstructorDecl>(GD.getDecl()) || ( -              isa<CXXDestructorDecl>(GD.getDecl()) && -              GD.getDtorType() != Dtor_Deleting)); -  } +  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);    void EmitReturnFromThunk(CodeGenFunction &CGF, RValue RV, QualType ResTy); @@ -181,6 +194,15 @@ 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))); +  }  };  } @@ -735,14 +757,22 @@ void ItaniumCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,                                  SmallVectorImpl<CanQualType> &ArgTys) {    ASTContext &Context = getContext(); -  // 'this' parameter is already there, as well as 'this' return if -  // HasThisReturn(GlobalDecl(Ctor, Type)) is true +  // 'this' is already there.    // 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, @@ -751,14 +781,25 @@ void ItaniumCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,                                  SmallVectorImpl<CanQualType> &ArgTys) {    ASTContext &Context = getContext(); -  // 'this' parameter is already there, as well as 'this' return if -  // HasThisReturn(GlobalDecl(Dtor, Type)) is true +  // 'this' is already there.    // 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) { @@ -782,6 +823,16 @@ void ItaniumCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,    }  } +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); @@ -792,23 +843,21 @@ void ItaniumCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {        = CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(getVTTDecl(CGF)),                                 "vtt");    } +} -  /// 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 +void ARMCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) { +  ItaniumCXXABI::EmitInstanceFunctionProlog(CGF); + +  /// Initialize the return slot to 'this' at the start of the +  /// function.    if (HasThisReturn(CGF.CurGD))      CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue);  } -void ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF, +llvm::Value *ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,                                          const CXXConstructorDecl *D, -                                        CXXCtorType Type, -                                        bool ForVirtualBase, bool Delegating, +                                        CXXCtorType Type, bool ForVirtualBase, +                                        bool Delegating,                                          llvm::Value *This,                                          CallExpr::const_arg_iterator ArgBeg,                                          CallExpr::const_arg_iterator ArgEnd) { @@ -818,15 +867,17 @@ void ItaniumCXXABI::EmitConstructorCall(CodeGenFunction &CGF,    llvm::Value *Callee = CGM.GetAddrOfCXXConstructor(D, Type);    // FIXME: Provide a source location here. -  CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), -                        This, VTT, VTTTy, ArgBeg, ArgEnd); +  CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This, +                        VTT, VTTTy, ArgBeg, ArgEnd); +  return Callee;  } -void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, -                                              const CXXDestructorDecl *Dtor, -                                              CXXDtorType DtorType, -                                              SourceLocation CallLoc, -                                              llvm::Value *This) { +RValue ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, +                                                const CXXDestructorDecl *Dtor, +                                                CXXDtorType DtorType, +                                                SourceLocation CallLoc, +                                                ReturnValueSlot ReturnValue, +                                                llvm::Value *This) {    assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);    const CGFunctionInfo *FInfo @@ -834,8 +885,8 @@ void ItaniumCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,    llvm::Type *Ty = CGF.CGM.getTypes().GetFunctionType(*FInfo);    llvm::Value *Callee = CGF.BuildVirtualCall(Dtor, DtorType, This, Ty); -  CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This, -                        /*ImplicitParam=*/0, QualType(), 0, 0); +  return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This, +                               /*ImplicitParam=*/0, QualType(), 0, 0);  }  void ItaniumCXXABI::EmitVirtualInheritanceTables( diff --git a/clang/lib/CodeGen/MicrosoftCXXABI.cpp b/clang/lib/CodeGen/MicrosoftCXXABI.cpp index 1dca209ed4f..1ff794695cb 100644 --- a/clang/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/clang/lib/CodeGen/MicrosoftCXXABI.cpp @@ -30,8 +30,6 @@ 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(); @@ -76,17 +74,20 @@ public:    void EmitInstanceFunctionProlog(CodeGenFunction &CGF); -  void EmitConstructorCall(CodeGenFunction &CGF, -                           const CXXConstructorDecl *D, CXXCtorType Type, -                           bool ForVirtualBase, bool Delegating, +  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); -  -  void EmitVirtualDestructorCall(CodeGenFunction &CGF, -                                 const CXXDestructorDecl *Dtor, -                                 CXXDtorType DtorType, SourceLocation CallLoc, -                                 llvm::Value *This); + +  RValue EmitVirtualDestructorCall(CodeGenFunction &CGF, +                                   const CXXDestructorDecl *Dtor, +                                   CXXDtorType DtorType, +                                   SourceLocation CallLoc, +                                   ReturnValueSlot ReturnValue, +                                   llvm::Value *This);    void EmitVirtualInheritanceTables(llvm::GlobalVariable::LinkageTypes Linkage,                                      const CXXRecordDecl *RD); @@ -129,6 +130,7 @@ public:    llvm::Value *readArrayCookieImpl(CodeGenFunction &CGF,                                     llvm::Value *allocPtr,                                     CharUnits cookieSize); +  static bool needThisReturn(GlobalDecl GD);  private:    llvm::Constant *getZeroInt() { @@ -312,15 +314,19 @@ MicrosoftCXXABI::GetVirtualBaseClassOffset(CodeGenFunction &CGF,    return CGF.Builder.CreateNSWAdd(VBPtrOffset, VBPtrToNewBase);  } -bool MicrosoftCXXABI::HasThisReturn(GlobalDecl GD) const { -  return isa<CXXConstructorDecl>(GD.getDecl()); +bool MicrosoftCXXABI::needThisReturn(GlobalDecl GD) { +  const CXXMethodDecl* MD = cast<CXXMethodDecl>(GD.getDecl()); +  return isa<CXXConstructorDecl>(MD);  }  void MicrosoftCXXABI::BuildConstructorSignature(const CXXConstructorDecl *Ctor,                                   CXXCtorType Type,                                   CanQualType &ResTy,                                   SmallVectorImpl<CanQualType> &ArgTys) { -  // 'this' parameter and 'this' return are already in place +  // 'this' is already in place + +  // Ctor returns this ptr +  ResTy = ArgTys[0];    const CXXRecordDecl *Class = Ctor->getParent();    if (Class->getNumVBases()) { @@ -378,7 +384,6 @@ void MicrosoftCXXABI::BuildDestructorSignature(const CXXDestructorDecl *Dtor,                                                 CanQualType &ResTy,                                          SmallVectorImpl<CanQualType> &ArgTys) {    // 'this' is already in place -    // TODO: 'for base' flag    if (Type == Dtor_Deleting) { @@ -399,6 +404,9 @@ void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,                                                    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()); @@ -423,17 +431,9 @@ void MicrosoftCXXABI::BuildInstanceFunctionParams(CodeGenFunction &CGF,  void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {    EmitThisParam(CGF); - -  /// 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)) +  if (needThisReturn(CGF.CurGD)) {      CGF.Builder.CreateStore(getThisValue(CGF), CGF.ReturnValue); +  }    const CXXMethodDecl *MD = cast<CXXMethodDecl>(CGF.CurGD.getDecl());    if (isa<CXXConstructorDecl>(MD) && MD->getParent()->getNumVBases()) { @@ -455,10 +455,9 @@ void MicrosoftCXXABI::EmitInstanceFunctionProlog(CodeGenFunction &CGF) {    }  } -void MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF, +llvm::Value *MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,                                            const CXXConstructorDecl *D, -                                          CXXCtorType Type,  -                                          bool ForVirtualBase, +                                          CXXCtorType Type, bool ForVirtualBase,                                            bool Delegating,                                            llvm::Value *This,                                            CallExpr::const_arg_iterator ArgBeg, @@ -475,14 +474,17 @@ void MicrosoftCXXABI::EmitConstructorCall(CodeGenFunction &CGF,    // FIXME: Provide a source location here.    CGF.EmitCXXMemberCall(D, SourceLocation(), Callee, ReturnValueSlot(), This, -                        ImplicitParam, ImplicitParamTy, ArgBeg, ArgEnd); +                        ImplicitParam, ImplicitParamTy, +                        ArgBeg, ArgEnd); +  return Callee;  } -void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, -                                                const CXXDestructorDecl *Dtor, -                                                CXXDtorType DtorType, -                                                SourceLocation CallLoc, -                                                llvm::Value *This) { +RValue MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF, +                                                  const CXXDestructorDecl *Dtor, +                                                  CXXDtorType DtorType, +                                                  SourceLocation CallLoc, +                                                  ReturnValueSlot ReturnValue, +                                                  llvm::Value *This) {    assert(DtorType == Dtor_Deleting || DtorType == Dtor_Complete);    // We have only one destructor in the vftable but can get both behaviors @@ -497,8 +499,8 @@ void MicrosoftCXXABI::EmitVirtualDestructorCall(CodeGenFunction &CGF,      = llvm::ConstantInt::get(llvm::IntegerType::getInt1Ty(CGF.getLLVMContext()),                               DtorType == Dtor_Deleting); -  CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValueSlot(), This, -                        ImplicitParam, Context.BoolTy, 0, 0); +  return CGF.EmitCXXMemberCall(Dtor, CallLoc, Callee, ReturnValue, This, +                               ImplicitParam, Context.BoolTy, 0, 0);  }  const VBTableVector & diff --git a/clang/test/CodeGenCXX/arm.cpp b/clang/test/CodeGenCXX/arm.cpp index 5578b2ab2b5..48f2f008401 100644 --- a/clang/test/CodeGenCXX/arm.cpp +++ b/clang/test/CodeGenCXX/arm.cpp @@ -52,19 +52,19 @@ namespace test1 {      a.bar();    } -  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* returned %this, i32 %i) unnamed_addr +  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AC1Ei([[A]]* %this, i32 %i) unnamed_addr    // CHECK:   [[THIS:%.*]] = alloca [[A]]*, align 4    // CHECK:   store [[A]]* {{.*}}, [[A]]** [[THIS]]    // CHECK:   [[THIS1:%.*]] = load [[A]]** [[THIS]] -  // CHECK:   {{%.*}} = call [[A]]* @_ZN5test11AC2Ei( -  // CHECK:   ret [[A]]* [[THIS1]] +  // CHECK:   [[THIS2:%.*]] = call [[A]]* @_ZN5test11AC2Ei( +  // CHECK:   ret [[A]]* [[THIS2]] -  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* returned %this) unnamed_addr +  // CHECK: define linkonce_odr [[A]]* @_ZN5test11AD1Ev([[A]]* %this) unnamed_addr    // CHECK:   [[THIS:%.*]] = alloca [[A]]*, align 4    // CHECK:   store [[A]]* {{.*}}, [[A]]** [[THIS]]    // CHECK:   [[THIS1:%.*]] = load [[A]]** [[THIS]] -  // CHECK:   {{%.*}} = call [[A]]* @_ZN5test11AD2Ev( -  // CHECK:   ret [[A]]* [[THIS1]] +  // CHECK:   [[THIS2:%.*]] = call [[A]]* @_ZN5test11AD2Ev( +  // CHECK:   ret [[A]]* [[THIS2]]  }  // Awkward virtual cases. diff --git a/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp b/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp index 1e9a0cea70e..1ff922de60f 100644 --- a/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp +++ b/clang/test/CodeGenCXX/constructor-destructor-return-this.cpp @@ -1,119 +1,60 @@ -//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 +//RUN: %clang_cc1 %s -emit-llvm -o - -triple=thumbv7-apple-ios3.0 -target-abi apcs-gnu | FileCheck %s -// FIXME: Add checks to ensure that Microsoft destructors do not return 'this' -// once PR12784 is resolved +// 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 -// Make sure we attach the 'returned' attribute to the 'this' parameter of -// constructors and destructors which return this (and only these cases) +// CHECK: define linkonce_odr [[A:%.*]] @_ZN11ObjectCacheC1Ev([[A]] %this) unnamed_addr +// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN11ObjectCacheC2Ev( +// CHECK-NEXT: ret [[A]] [[THIS1]] -class A { -public: -  A(); -  ~A(); +// CHECK: define linkonce_odr [[A:%.*]] @_ZN5TimerI11ObjectCacheEC1EPS0_MS0_FvPS1_E([[A]] %this +// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN5TimerI11ObjectCacheEC2EPS0_MS0_FvPS1_E( +// CHECK-NEXT: ret [[A]] [[THIS1]] -private: -  int x_; -}; +// CHECK: define linkonce_odr [[A:%.*]] @_ZN5TimerI11ObjectCacheED1Ev([[A]] %this) unnamed_addr +// CHECK: [[THIS1:%.*]] = call [[A]] @_ZN5TimerI11ObjectCacheED2Ev( +// CHECK-NEXT: ret [[A]] [[THIS1]] -class B : public A { -public: -  B(int *i); -  ~B(); - -private: -  int *i_; -}; +// 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]] -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@PEAH@Z"(%class.B* returned %this, i32* %i) - -class C : public A, public B { +class TimerBase {  public: -  C(int *i, char *c); -  virtual ~C(); -private: -  char *c_; +    TimerBase(); +    virtual ~TimerBase();  }; -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@PEAHPEAD@Z"(%class.C* returned %this, i32* %i, i8* %c) - -class D : public virtual A { +template <typename TimerFiredClass> class Timer : public TimerBase {  public: -  D(); -  ~D(); -}; +    typedef void (TimerFiredClass::*TimerFiredFunction)(Timer*); -#ifndef PR12784_WORKAROUND -D::D() { } -D::~D() { } -#endif +    Timer(TimerFiredClass* o, TimerFiredFunction f) +        : m_object(o), m_function(f) { } -// 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) +private: +    virtual void fired() { (m_object->*m_function)(this); } -// 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) +    TimerFiredClass* m_object; +    TimerFiredFunction m_function; +}; -class E { +class ObjectCache {  public: -  E(); -  virtual ~E(); +    explicit ObjectCache(); +    ~ObjectCache(); + +private: +    Timer<ObjectCache> m_notificationPostTimer;  }; -E* gete(); +inline ObjectCache::ObjectCache() : m_notificationPostTimer(this, 0) { } +inline ObjectCache::~ObjectCache() { } -void test_destructor() { -  const E& e1 = E(); -  E* e2 = gete(); -  e2->~E(); +ObjectCache *test() { +  ObjectCache *dd = new ObjectCache(); +  return dd;  } - -// CHECKARM: define void @_Z15test_destructorv() - -// 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: {{%.*}} = call %class.E* @_ZN1ED1Ev(%class.E* % - -// CHECKARM: declare %class.E* @_ZN1ED1Ev(%class.E* returned) diff --git a/clang/test/CodeGenCXX/copy-constructor-elim-2.cpp b/clang/test/CodeGenCXX/copy-constructor-elim-2.cpp index b1447040e6c..4ff877516b0 100644 --- a/clang/test/CodeGenCXX/copy-constructor-elim-2.cpp +++ b/clang/test/CodeGenCXX/copy-constructor-elim-2.cpp @@ -21,7 +21,7 @@ namespace no_elide_base {      Derived(const Other &O);    }; -  // CHECK: define {{.*}} @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* returned %this, %"struct.no_elide_base::Other"* %O) unnamed_addr +  // CHECK: define {{.*}} @_ZN13no_elide_base7DerivedC1ERKNS_5OtherE(%"struct.no_elide_base::Derived"* %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_ diff --git a/clang/test/CodeGenCXX/copy-constructor-synthesis-2.cpp b/clang/test/CodeGenCXX/copy-constructor-synthesis-2.cpp index 03c66339947..d028a28fdd6 100644 --- a/clang/test/CodeGenCXX/copy-constructor-synthesis-2.cpp +++ b/clang/test/CodeGenCXX/copy-constructor-synthesis-2.cpp @@ -3,5 +3,5 @@  struct A { virtual void a(); };  A x(A& y) { return y; } -// CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(%struct.A* {{.*}}%this, %struct.A*) unnamed_addr +// CHECK: define linkonce_odr {{.*}} @_ZN1AC1ERKS_(%struct.A* %this, %struct.A*) unnamed_addr  // CHECK: store i8** getelementptr inbounds ([3 x i8*]* @_ZTV1A, i64 0, i64 2) diff --git a/clang/test/CodeGenCXX/default-constructor-template-member.cpp b/clang/test/CodeGenCXX/default-constructor-template-member.cpp index 215696405a4..0dd64dfcb4c 100644 --- a/clang/test/CodeGenCXX/default-constructor-template-member.cpp +++ b/clang/test/CodeGenCXX/default-constructor-template-member.cpp @@ -5,7 +5,6 @@ struct B { A<int> x; };  void a() {       B b;  } -  // CHECK: call {{.*}} @_ZN1BC1Ev -// CHECK: define linkonce_odr {{.*}} @_ZN1BC1Ev(%struct.B* {{.*}}%this) unnamed_addr +// CHECK: define linkonce_odr {{.*}} @_ZN1BC1Ev(%struct.B* %this) unnamed_addr  // CHECK: call {{.*}} @_ZN1AIiEC1Ev diff --git a/clang/test/CodeGenCXX/mangle-template.cpp b/clang/test/CodeGenCXX/mangle-template.cpp index 03eae53ad02..15a85c7bd2e 100644 --- a/clang/test/CodeGenCXX/mangle-template.cpp +++ b/clang/test/CodeGenCXX/mangle-template.cpp @@ -82,7 +82,7 @@ namespace test7 {      X(U*, typename int_c<(meta<T>::value + meta<U>::value)>::type *) { }    }; -  // CHECK: define weak_odr {{.*}} @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsr4metaIS3_EE5valueEE4typeE( +  // CHECK: define weak_odr {{.*}} @_ZN5test71XIiEC1IdEEPT_PNS_5int_cIXplL_ZNS_4metaIiE5valueEEsr4metaIS3_EE5valueEE4typeE(%"struct.test7::X"* %this, double*, float*) unnamed_addr    template X<int>::X(double*, float*);  } @@ -101,7 +101,7 @@ namespace test8 {    template<typename T>    void f(int_c<meta<T>::type::value>) { } -  // CHECK: define weak_odr void @_ZN5test81fIiEEvNS_5int_cIXsr4metaIT_E4typeE5valueEEE( +  // CHECK: define weak_odr void @_ZN5test81fIiEEvNS_5int_cIXsr4metaIT_E4typeE5valueEEE    template void f<int>(int_c<sizeof(int)>);  } diff --git a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp index 27c00063395..9d4a1c5e908 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-structors.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-structors.cpp @@ -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@basic@@QAE@XZ"(%"class.basic::A"* returned %this) +// CHECK:      define linkonce_odr x86_thiscallcc %"class.basic::A"* @"\01??0A@basic@@QAE@XZ"(%"class.basic::A"* %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@basic@@QAE@XZ"(%"struct.basic::B"* returned %this) +  // CHECK: define x86_thiscallcc %"struct.basic::B"* @"\01??0B@basic@@QAE@XZ"(%"struct.basic::B"* %this)    // CHECK: ret  } @@ -136,7 +136,7 @@ struct B : A {  };  B::B() { -  // CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* returned %this) +  // CHECK: define x86_thiscallcc %"struct.constructors::B"* @"\01??0B@constructors@@QAE@XZ"(%"struct.constructors::B"* %this)    // CHECK: call x86_thiscallcc %"struct.constructors::A"* @"\01??0A@constructors@@QAE@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@constructors@@QAE@XZ"(%"struct.constructors::C"* returned %this, i32 %is_most_derived) +  // CHECK: define x86_thiscallcc %"struct.constructors::C"* @"\01??0C@constructors@@QAE@XZ"(%"struct.constructors::C"* %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]] @@ -179,7 +179,7 @@ struct D : C {  };  D::D() { -  // CHECK: define x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* returned %this, i32 %is_most_derived) unnamed_addr +  // CHECK: define x86_thiscallcc %"struct.constructors::D"* @"\01??0D@constructors@@QAE@XZ"(%"struct.constructors::D"* %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 @@ -204,7 +204,7 @@ struct E : virtual C {  };  E::E() { -  // CHECK: define x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* returned %this, i32 %is_most_derived) unnamed_addr +  // CHECK: define x86_thiscallcc %"struct.constructors::E"* @"\01??0E@constructors@@QAE@XZ"(%"struct.constructors::E"* %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 diff --git a/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp b/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp index a8d4520b5eb..2424d218d6b 100644 --- a/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp +++ b/clang/test/CodeGenCXX/virtual-base-destructor-call.cpp @@ -18,34 +18,34 @@ int main() {  // basic_iostream's complete dtor calls its base dtor, then its  // virtual base's dtor. -//  CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED1Ev(%struct.basic_iostream* {{.*}}%this) unnamed_addr +//  CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED1Ev(%struct.basic_iostream* %this) unnamed_addr  //  CHECK: call {{.*}} @_ZN14basic_iostreamIcED2Ev  //  CHECK: call {{.*}} @_ZN9basic_iosD2Ev  // basic_iostream's base dtor calls its non-virtual base dtor. -//  CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED2Ev(%struct.basic_iostream* {{.*}}%this, i8** %vtt) unnamed_addr +//  CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED2Ev(%struct.basic_iostream* %this, i8** %vtt) unnamed_addr  //  CHECK: call {{.*}} @_ZN13basic_istreamIcED2Ev  //  CHECK: }  // basic_iostream's deleting dtor calls its complete dtor, then  // operator delete(). -//  CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* {{.*}}%this) unnamed_addr +//  CHECK: define linkonce_odr {{.*}} @_ZN14basic_iostreamIcED0Ev(%struct.basic_iostream* %this) unnamed_addr  //  CHECK: call {{.*}} @_ZN14basic_iostreamIcED1Ev  //  CHECK: call {{.*}} @_ZdlPv  // basic_istream's complete dtor calls the base dtor,  // then its virtual base's base dtor. -//  CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED1Ev(%struct.basic_istream* {{.*}}%this) unnamed_addr +//  CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED1Ev(%struct.basic_istream* %this) unnamed_addr  //  CHECK: call {{.*}} @_ZN13basic_istreamIcED2Ev  //  CHECK: call {{.*}} @_ZN9basic_iosD2Ev  // basic_istream's deleting dtor calls the complete dtor, then  // operator delete(). -//  CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED0Ev(%struct.basic_istream* {{.*}}%this) unnamed_addr +//  CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED0Ev(%struct.basic_istream* %this) unnamed_addr  //  CHECK: call {{.*}} @_ZN13basic_istreamIcED1Ev  //  CHECK: call {{.*}} @_ZdlPv  // basic_istream's base dtor is a no-op. -//  CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED2Ev(%struct.basic_istream* {{.*}}%this, i8** %vtt) unnamed_addr +//  CHECK: define linkonce_odr {{.*}} @_ZN13basic_istreamIcED2Ev(%struct.basic_istream* %this, i8** %vtt) unnamed_addr  //  CHECK-NOT: call  //  CHECK: }  | 

