r231952 - MS ABI: Implement copy-ctor closures, finish implementing throw

Aaron Ballman aaron at aaronballman.com
Thu Mar 12 06:33:20 PDT 2015


On Wed, Mar 11, 2015 at 2:36 PM, David Majnemer
<david.majnemer at gmail.com> wrote:
> Author: majnemer
> Date: Wed Mar 11 13:36:39 2015
> New Revision: 231952
>
> URL: http://llvm.org/viewvc/llvm-project?rev=231952&view=rev
> Log:
> MS ABI: Implement copy-ctor closures, finish implementing throw
>
> This adds support for copy-constructor closures.  These are generated
> when the C++ runtime has to call a copy-constructor with a particular
> calling convention or with default arguments substituted in to the call.
>
> Because the runtime has no mechanism to call the function with a
> different calling convention or know-how to evaluate the default
> arguments at run-time, we create a thunk which will do all the
> appropriate work and package it in a way the runtime can use.
>
> Differential Revision: http://reviews.llvm.org/D8225
>
> Modified:
>     cfe/trunk/include/clang/AST/ASTContext.h
>     cfe/trunk/include/clang/AST/Mangle.h
>     cfe/trunk/include/clang/Basic/ABI.h
>     cfe/trunk/lib/AST/ASTContext.cpp
>     cfe/trunk/lib/AST/CXXABI.h
>     cfe/trunk/lib/AST/ItaniumCXXABI.cpp
>     cfe/trunk/lib/AST/ItaniumMangle.cpp
>     cfe/trunk/lib/AST/MicrosoftCXXABI.cpp
>     cfe/trunk/lib/AST/MicrosoftMangle.cpp
>     cfe/trunk/lib/CodeGen/CGCall.cpp
>     cfe/trunk/lib/CodeGen/CodeGenTypes.h
>     cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
>     cfe/trunk/lib/Sema/SemaExprCXX.cpp
>     cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Wed Mar 11 13:36:39 2015
> @@ -2201,6 +2201,12 @@ public:
>    void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
>                                              CXXConstructorDecl *CD);
>
> +  void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
> +                                       unsigned ParmIdx, Expr *DAE);
> +
> +  Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
> +                                        unsigned ParmIdx);
> +
>    void setManglingNumber(const NamedDecl *ND, unsigned Number);
>    unsigned getManglingNumber(const NamedDecl *ND) const;
>
>
> Modified: cfe/trunk/include/clang/AST/Mangle.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Mangle.h?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Mangle.h (original)
> +++ cfe/trunk/include/clang/AST/Mangle.h Wed Mar 11 13:36:39 2015
> @@ -204,9 +204,9 @@ public:
>                                             raw_ostream &Out) = 0;
>
>    virtual void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
> -                                      uint32_t Size, uint32_t NVOffset,
> -                                      int32_t VBPtrOffset, uint32_t VBIndex,
> -                                      raw_ostream &Out) = 0;
> +                                      CXXCtorType CT, uint32_t Size,
> +                                      uint32_t NVOffset, int32_t VBPtrOffset,
> +                                      uint32_t VBIndex, raw_ostream &Out) = 0;
>
>    virtual void mangleCXXRTTIBaseClassDescriptor(
>        const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t VBPtrOffset,
>
> Modified: cfe/trunk/include/clang/Basic/ABI.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ABI.h?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/ABI.h (original)
> +++ cfe/trunk/include/clang/Basic/ABI.h Wed Mar 11 13:36:39 2015
> @@ -22,9 +22,11 @@ namespace clang {
>
>  /// \brief C++ constructor types.
>  enum CXXCtorType {
> -    Ctor_Complete,          ///< Complete object ctor
> -    Ctor_Base,              ///< Base object ctor
> -    Ctor_Comdat             ///< The COMDAT used for ctors
> +  Ctor_Complete,       ///< Complete object ctor
> +  Ctor_Base,           ///< Base object ctor
> +  Ctor_Comdat,         ///< The COMDAT used for ctors
> +  Ctor_CopyingClosure, ///< Copying closure variant of a ctor
> +  Ctor_DefaultClosure, ///< Default closure variant of a ctor
>  };
>
>  /// \brief C++ destructor types.
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Wed Mar 11 13:36:39 2015
> @@ -8210,6 +8210,18 @@ void ASTContext::addCopyConstructorForEx
>        cast<CXXConstructorDecl>(CD->getFirstDecl()));
>  }
>
> +void ASTContext::addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
> +                                                 unsigned ParmIdx, Expr *DAE) {
> +  ABI->addDefaultArgExprForConstructor(
> +      cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx, DAE);
> +}
> +
> +Expr *ASTContext::getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
> +                                                  unsigned ParmIdx) {
> +  return ABI->getDefaultArgExprForConstructor(
> +      cast<CXXConstructorDecl>(CD->getFirstDecl()), ParmIdx);
> +}
> +
>  void ASTContext::setParameterIndex(const ParmVarDecl *D, unsigned int index) {
>    ParamIndices[D] = index;
>  }
>
> Modified: cfe/trunk/lib/AST/CXXABI.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/CXXABI.h?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/CXXABI.h (original)
> +++ cfe/trunk/lib/AST/CXXABI.h Wed Mar 11 13:36:39 2015
> @@ -21,6 +21,7 @@ namespace clang {
>
>  class ASTContext;
>  class CXXConstructorDecl;
> +class Expr;
>  class MemberPointerType;
>  class MangleNumberingContext;
>
> @@ -50,6 +51,12 @@ public:
>    /// Retrieves the mapping from class to copy constructor for this C++ ABI.
>    virtual const CXXConstructorDecl *
>    getCopyConstructorForExceptionObject(CXXRecordDecl *) = 0;
> +
> +  virtual void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
> +                                               unsigned ParmIdx, Expr *DAE) = 0;
> +
> +  virtual Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
> +                                                unsigned ParmIdx) = 0;
>  };
>
>  /// Creates an instance of a C++ ABI class.
>
> Modified: cfe/trunk/lib/AST/ItaniumCXXABI.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumCXXABI.cpp?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumCXXABI.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumCXXABI.cpp Wed Mar 11 13:36:39 2015
> @@ -141,6 +141,14 @@ public:
>    void addCopyConstructorForExceptionObject(CXXRecordDecl *RD,
>                                              CXXConstructorDecl *CD) override {}
>
> +  void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
> +                                       unsigned ParmIdx, Expr *DAE) override {}
> +
> +  Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
> +                                        unsigned ParmIdx) override {
> +    return nullptr;
> +  }
> +
>    MangleNumberingContext *createMangleNumberingContext() const override {
>      return new ItaniumNumberingContext();
>    }
>
> Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
> +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Wed Mar 11 13:36:39 2015
> @@ -3442,6 +3442,9 @@ void CXXNameMangler::mangleCXXCtorType(C
>    case Ctor_Comdat:
>      Out << "C5";
>      break;
> +  case Ctor_DefaultClosure:
> +  case Ctor_CopyingClosure:
> +    llvm_unreachable("closure constructors don't exist for the Itanium ABI!");
>    }
>  }
>
>
> Modified: cfe/trunk/lib/AST/MicrosoftCXXABI.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftCXXABI.cpp?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/MicrosoftCXXABI.cpp (original)
> +++ cfe/trunk/lib/AST/MicrosoftCXXABI.cpp Wed Mar 11 13:36:39 2015
> @@ -64,6 +64,8 @@ public:
>  class MicrosoftCXXABI : public CXXABI {
>    ASTContext &Context;
>    llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> RecordToCopyCtor;
> +  llvm::SmallDenseMap<std::pair<const CXXConstructorDecl *, unsigned>, Expr *>
> +      CtorToDefaultArgExpr;
>
>  public:
>    MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { }
> @@ -92,6 +94,16 @@ public:
>        Layout.getNonVirtualSize() == PointerSize * 2;
>    }
>
> +  void addDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
> +                                       unsigned ParmIdx, Expr *DAE) override {
> +    CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)] = DAE;
> +  }
> +
> +  Expr *getDefaultArgExprForConstructor(const CXXConstructorDecl *CD,
> +                                        unsigned ParmIdx) override {
> +    return CtorToDefaultArgExpr[std::make_pair(CD, ParmIdx)];
> +  }
> +
>    const CXXConstructorDecl *
>    getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override {
>      return RecordToCopyCtor[RD];
>
> Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original)
> +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Wed Mar 11 13:36:39 2015
> @@ -67,11 +67,15 @@ static const DeclContext *getEffectivePa
>    return getEffectiveDeclContext(cast<Decl>(DC));
>  }
>
> -static const FunctionDecl *getStructor(const FunctionDecl *fn) {
> -  if (const FunctionTemplateDecl *ftd = fn->getPrimaryTemplate())
> -    return ftd->getTemplatedDecl();
> +static const FunctionDecl *getStructor(const NamedDecl *ND) {
> +  if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND))
> +    return FTD->getTemplatedDecl();
> +
> +  const auto *FD = cast<FunctionDecl>(ND);
> +  if (const auto *FTD = FD->getPrimaryTemplate())
> +    return FTD->getTemplatedDecl();
>
> -  return fn;
> +  return FD;
>  }
>
>  static bool isLambda(const NamedDecl *ND) {
> @@ -115,7 +119,7 @@ public:
>    void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries,
>                                     raw_ostream &Out) override;
>    void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD,
> -                              uint32_t Size, uint32_t NVOffset,
> +                              CXXCtorType CT, uint32_t Size, uint32_t NVOffset,
>                                int32_t VBPtrOffset, uint32_t VBIndex,
>                                raw_ostream &Out) override;
>    void mangleCXXRTTI(QualType T, raw_ostream &Out) override;
> @@ -224,6 +228,12 @@ public:
>                           64) {}
>
>    MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
> +                          const CXXConstructorDecl *D, CXXCtorType Type)
> +      : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
> +        PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
> +                         64) {}
> +
> +  MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_,
>                            const CXXDestructorDecl *D, CXXDtorType Type)
>        : Context(C), Out(Out_), Structor(getStructor(D)), StructorType(Type),
>          PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) ==
> @@ -284,6 +294,7 @@ private:
>    void mangleDecayedArrayType(const ArrayType *T);
>    void mangleArrayType(const ArrayType *T);
>    void mangleFunctionClass(const FunctionDecl *FD);
> +  void mangleCallingConvention(CallingConv CC);
>    void mangleCallingConvention(const FunctionType *T);
>    void mangleIntegerLiteral(const llvm::APSInt &Number, bool IsBoolean);
>    void mangleExpression(const Expr *E);
> @@ -770,12 +781,18 @@ void MicrosoftCXXNameMangler::mangleUnqu
>        llvm_unreachable("Can't mangle Objective-C selector names here!");
>
>      case DeclarationName::CXXConstructorName:
> -      if (ND == Structor) {
> -        assert(StructorType == Ctor_Complete &&
> -               "Should never be asked to mangle a ctor other than complete");
> +      if (Structor == getStructor(ND)) {
> +        if (StructorType == Ctor_CopyingClosure) {
> +          Out << "?_O";
> +          return;
> +        }
> +        if (StructorType == Ctor_DefaultClosure) {
> +          Out << "?_F";
> +          return;
> +        }
>        }
>        Out << "?0";
> -      break;
> +      return;
>
>      case DeclarationName::CXXDestructorName:
>        if (ND == Structor)
> @@ -1566,12 +1583,22 @@ void MicrosoftCXXNameMangler::mangleFunc
>    SourceRange Range;
>    if (D) Range = D->getSourceRange();
>
> -  bool IsStructor = false, HasThisQuals = ForceThisQuals;
> +  bool IsStructor = false, HasThisQuals = ForceThisQuals, IsCtorClosure = false;
> +  CallingConv CC = T->getCallConv();
>    if (const CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(D)) {
>      if (MD->isInstance())
>        HasThisQuals = true;
> -    if (isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(MD))
> +    if (isa<CXXDestructorDecl>(MD)) {
> +      IsStructor = true;
> +    } else if (isa<CXXConstructorDecl>(MD)) {
>        IsStructor = true;
> +      IsCtorClosure = (StructorType == Ctor_CopyingClosure ||
> +                       StructorType == Ctor_DefaultClosure) &&
> +                      getStructor(MD) == Structor;
> +      if (IsCtorClosure)
> +        CC = getASTContext().getDefaultCallingConvention(
> +            /*IsVariadic=*/false, /*IsCXXMethod=*/true);
> +    }
>    }
>
>    // If this is a C++ instance method, mangle the CVR qualifiers for the
> @@ -1583,7 +1610,7 @@ void MicrosoftCXXNameMangler::mangleFunc
>      mangleQualifiers(Quals, /*IsMember=*/false);
>    }
>
> -  mangleCallingConvention(T);
> +  mangleCallingConvention(CC);
>
>    // <return-type> ::= <type>
>    //               ::= @ # structors (they have no declared return type)
> @@ -1597,6 +1624,28 @@ void MicrosoftCXXNameMangler::mangleFunc
>        Out << (PointersAre64Bit ? "PEAXI at Z" : "PAXI at Z");
>        return;
>      }
> +    if (IsCtorClosure) {
> +      // Default constructor closure and copy constructor closure both return
> +      // void.
> +      Out << 'X';
> +
> +      if (StructorType == Ctor_DefaultClosure) {
> +        // Default constructor closure always has no arguments.
> +        Out << 'X';
> +      } else if (StructorType == Ctor_CopyingClosure) {
> +        // Copy constructor closure always takes an unqualified reference.
> +        mangleArgumentType(getASTContext().getLValueReferenceType(
> +                               Proto->getParamType(0)
> +                                   ->getAs<LValueReferenceType>()
> +                                   ->getPointeeType(),
> +                               /*SpelledAsLValue=*/true),
> +                           Range);
> +      } else {
> +        llvm_unreachable("unexpected constructor closure!");
> +      }
> +      Out << "@Z";
> +      return;
> +    }
>      Out << '@';
>    } else {
>      QualType ResultType = Proto->getReturnType();
> @@ -1689,7 +1738,7 @@ void MicrosoftCXXNameMangler::mangleFunc
>    } else
>      Out << 'Y';
>  }
> -void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
> +void MicrosoftCXXNameMangler::mangleCallingConvention(CallingConv CC) {
>    // <calling-convention> ::= A # __cdecl
>    //                      ::= B # __export __cdecl
>    //                      ::= C # __pascal
> @@ -1706,7 +1755,7 @@ void MicrosoftCXXNameMangler::mangleCall
>    // that keyword. (It didn't actually export them, it just made them so
>    // that they could be in a DLL and somebody from another module could call
>    // them.)
> -  CallingConv CC = T->getCallConv();
> +
>    switch (CC) {
>      default:
>        llvm_unreachable("Unsupported CC for mangling");
> @@ -1720,6 +1769,9 @@ void MicrosoftCXXNameMangler::mangleCall
>      case CC_X86VectorCall: Out << 'Q'; break;
>    }
>  }
> +void MicrosoftCXXNameMangler::mangleCallingConvention(const FunctionType *T) {
> +  mangleCallingConvention(T->getCallConv());
> +}
>  void MicrosoftCXXNameMangler::mangleThrowSpecification(
>                                                  const FunctionProtoType *FT) {
>    // <throw-spec> ::= Z # throw(...) (default)
> @@ -2310,8 +2362,9 @@ void MicrosoftMangleContextImpl::mangleC
>  }
>
>  void MicrosoftMangleContextImpl::mangleCXXCatchableType(
> -    QualType T, const CXXConstructorDecl *CD, uint32_t Size, uint32_t NVOffset,
> -    int32_t VBPtrOffset, uint32_t VBIndex, raw_ostream &Out) {
> +    QualType T, const CXXConstructorDecl *CD, CXXCtorType CT, uint32_t Size,
> +    uint32_t NVOffset, int32_t VBPtrOffset, uint32_t VBIndex,
> +    raw_ostream &Out) {
>    MicrosoftCXXNameMangler Mangler(*this, Out);
>    Mangler.getStream() << "_CT";
>
> @@ -2328,7 +2381,7 @@ void MicrosoftMangleContextImpl::mangleC
>    llvm::SmallString<64> CopyCtorMangling;
>    if (CD) {
>      llvm::raw_svector_ostream Stream(CopyCtorMangling);
> -    mangleCXXCtor(CD, Ctor_Complete, Stream);
> +    mangleCXXCtor(CD, CT, Stream);
>    }
>    Mangler.getStream() << CopyCtorMangling.substr(1);
>
> @@ -2411,7 +2464,7 @@ void MicrosoftMangleContextImpl::mangleT
>  void MicrosoftMangleContextImpl::mangleCXXCtor(const CXXConstructorDecl *D,
>                                                 CXXCtorType Type,
>                                                 raw_ostream &Out) {
> -  MicrosoftCXXNameMangler mangler(*this, Out);
> +  MicrosoftCXXNameMangler mangler(*this, Out, D, Type);
>    mangler.mangle(D);
>  }
>
>
> Modified: cfe/trunk/lib/CodeGen/CGCall.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGCall.cpp?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGCall.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGCall.cpp Wed Mar 11 13:36:39 2015
> @@ -346,6 +346,22 @@ CodeGenTypes::arrangeMSMemberPointerThun
>                                   FTP->getExtInfo(), RequiredArgs(1));
>  }
>
> +const CGFunctionInfo &
> +CodeGenTypes::arrangeMSCopyCtorClosure(const CXXConstructorDecl *CD) {
> +  CanQual<FunctionProtoType> FTP = GetFormalType(CD);
> +  SmallVector<CanQualType, 2> ArgTys;
> +  const CXXRecordDecl *RD = CD->getParent();
> +  ArgTys.push_back(GetThisType(Context, RD));
> +  ArgTys.push_back(*FTP->param_type_begin());
> +  if (RD->getNumVBases() > 0)
> +    ArgTys.push_back(Context.IntTy);
> +  CallingConv CC = Context.getDefaultCallingConvention(
> +      /*IsVariadic=*/false, /*IsCXXMethod=*/true);
> +  return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/true,
> +                                 /*chainCall=*/false, ArgTys,
> +                                 FunctionType::ExtInfo(CC), RequiredArgs::All);
> +}
> +
>  /// Arrange a call as unto a free function, except possibly with an
>  /// additional number of formal parameters considered required.
>  static const CGFunctionInfo &
>
> Modified: cfe/trunk/lib/CodeGen/CodeGenTypes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenTypes.h?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CodeGenTypes.h (original)
> +++ cfe/trunk/lib/CodeGen/CodeGenTypes.h Wed Mar 11 13:36:39 2015
> @@ -82,6 +82,9 @@ inline StructorType getFromCtorType(CXXC
>      return StructorType::Base;
>    case Ctor_Comdat:
>      llvm_unreachable("not expecting a COMDAT");
> +  case Ctor_CopyingClosure:
> +  case Ctor_DefaultClosure:
> +    llvm_unreachable("not expecting a closure");
>    }
>    llvm_unreachable("not a CXXCtorType");
>  }
> @@ -261,6 +264,7 @@ public:
>                                               const FunctionProtoType *type,
>                                               RequiredArgs required);
>    const CGFunctionInfo &arrangeMSMemberPointerThunk(const CXXMethodDecl *MD);
> +  const CGFunctionInfo &arrangeMSCopyCtorClosure(const CXXConstructorDecl *CD);
>
>    const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionProtoType> Ty);
>    const CGFunctionInfo &arrangeFreeFunctionType(CanQual<FunctionNoProtoType> Ty);
>
> Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original)
> +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Wed Mar 11 13:36:39 2015
> @@ -635,6 +635,8 @@ public:
>      return Fn;
>    }
>
> +  llvm::Function *getAddrOfCXXCopyCtorClosure(const CXXConstructorDecl *CD);
> +
>    llvm::Constant *getCatchableType(QualType T,
>                                     uint32_t NVOffset = 0,
>                                     int32_t VBPtrOffset = -1,
> @@ -3220,6 +3222,103 @@ void MicrosoftCXXABI::emitCXXStructor(co
>    emitCXXDestructor(CGM, cast<CXXDestructorDecl>(MD), Type);
>  }
>
> +llvm::Function *
> +MicrosoftCXXABI::getAddrOfCXXCopyCtorClosure(const CXXConstructorDecl *CD) {
> +  // Calculate the mangled name.
> +  SmallString<256> ThunkName;
> +  llvm::raw_svector_ostream Out(ThunkName);
> +  getMangleContext().mangleCXXCtor(CD, Ctor_CopyingClosure, Out);
> +  Out.flush();
> +
> +  // If the thunk has been generated previously, just return it.
> +  if (llvm::GlobalValue *GV = CGM.getModule().getNamedValue(ThunkName))
> +    return cast<llvm::Function>(GV);
> +
> +  // Create the llvm::Function.
> +  const CGFunctionInfo &FnInfo = CGM.getTypes().arrangeMSCopyCtorClosure(CD);
> +  llvm::FunctionType *ThunkTy = CGM.getTypes().GetFunctionType(FnInfo);
> +  const CXXRecordDecl *RD = CD->getParent();
> +  QualType RecordTy = getContext().getRecordType(RD);
> +  llvm::Function *ThunkFn = llvm::Function::Create(
> +      ThunkTy, getLinkageForRTTI(RecordTy), ThunkName.str(), &CGM.getModule());
> +
> +  // Start codegen.
> +  CodeGenFunction CGF(CGM);
> +  CGF.CurGD = GlobalDecl(CD, Ctor_Complete);
> +
> +  // Build FunctionArgs.
> +  FunctionArgList FunctionArgs;
> +
> +  // A copy constructor always starts with a 'this' pointer as its first
> +  // argument.
> +  buildThisParam(CGF, FunctionArgs);
> +
> +  // Following the 'this' pointer is a reference to the source object that we
> +  // are copying from.
> +  ImplicitParamDecl SrcParam(
> +      getContext(), nullptr, SourceLocation(), &getContext().Idents.get("src"),
> +      getContext().getLValueReferenceType(RecordTy,
> +                                          /*SpelledAsLValue=*/true));
> +  FunctionArgs.push_back(&SrcParam);
> +
> +  // Copy constructors for classes which utilize virtual bases have an
> +  // additional parameter which indicates whether or not it is being delegated
> +  // to by a more derived constructor.
> +  ImplicitParamDecl IsMostDerived(getContext(), nullptr, SourceLocation(),
> +                                  &getContext().Idents.get("is_most_derived"),
> +                                  getContext().IntTy);
> +  // Only add the parameter to the list if thie class has virtual bases.
> +  if (RD->getNumVBases() > 0)
> +    FunctionArgs.push_back(&IsMostDerived);
> +
> +  // Start defining the function.
> +  CGF.StartFunction(GlobalDecl(), FnInfo.getReturnType(), ThunkFn, FnInfo,
> +                    FunctionArgs, CD->getLocation(), SourceLocation());
> +  EmitThisParam(CGF);
> +  llvm::Value *This = getThisValue(CGF);
> +
> +  llvm::Value *SrcVal =
> +      CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(&SrcParam), "src");
> +
> +  CallArgList Args;
> +
> +  // Push the this ptr.
> +  Args.add(RValue::get(This), CD->getThisType(getContext()));
> +
> +  // Push the src ptr.
> +  Args.add(RValue::get(SrcVal), SrcParam.getType());
> +
> +  // Add the rest of the default arguments.
> +  std::vector<Stmt *> ArgVec;
> +  for (unsigned I = 1, E = CD->getNumParams(); I != E; ++I)
> +    ArgVec.push_back(getContext().getDefaultArgExprForConstructor(CD, I));
> +
> +  CodeGenFunction::RunCleanupsScope Cleanups(CGF);
> +
> +  const auto *FPT = CD->getType()->castAs<FunctionProtoType>();
> +  ConstExprIterator ArgBegin(ArgVec.data()), ArgEnd(&*ArgVec.end());

Dereferencing std::vector::end() is UB since it is a past-the-end
value. This is causing failed assertions ("vector iterator not
dereferencable") with checked STL implementations, such as what you
get with Visual Studio's debug mode.

~Aaron

> +  CGF.EmitCallArgs(Args, FPT, ArgBegin, ArgEnd, CD, 1);
> +
> +  // Insert any ABI-specific implicit constructor arguments.
> +  unsigned ExtraArgs = addImplicitConstructorArgs(CGF, CD, Ctor_Complete,
> +                                                  /*ForVirtualBase=*/false,
> +                                                  /*Delegating=*/false, Args);
> +
> +  // Call the destructor with our arguments.
> +  llvm::Value *CalleeFn = CGM.getAddrOfCXXStructor(CD, StructorType::Complete);
> +  const CGFunctionInfo &CalleeInfo = CGM.getTypes().arrangeCXXConstructorCall(
> +      Args, CD, Ctor_Complete, ExtraArgs);
> +  CGF.EmitCall(CalleeInfo, CalleeFn, ReturnValueSlot(), Args, CD);
> +
> +  Cleanups.ForceCleanup();
> +
> +  // Emit the ret instruction, remove any temporary instructions created for the
> +  // aid of CodeGen.
> +  CGF.FinishFunction(SourceLocation());
> +
> +  return ThunkFn;
> +}
> +
>  llvm::Constant *MicrosoftCXXABI::getCatchableType(QualType T,
>                                                    uint32_t NVOffset,
>                                                    int32_t VBPtrOffset,
> @@ -3229,27 +3328,43 @@ llvm::Constant *MicrosoftCXXABI::getCatc
>    CXXRecordDecl *RD = T->getAsCXXRecordDecl();
>    const CXXConstructorDecl *CD =
>        RD ? CGM.getContext().getCopyConstructorForExceptionObject(RD) : nullptr;
> +  CXXCtorType CT = Ctor_Complete;
> +  if (CD) {
> +    CallingConv ExpectedCallingConv = getContext().getDefaultCallingConvention(
> +        /*IsVariadic=*/false, /*IsCXXMethod=*/true);
> +    CallingConv ActualCallingConv =
> +        CD->getType()->getAs<FunctionProtoType>()->getCallConv();
> +    if (ExpectedCallingConv != ActualCallingConv || CD->getNumParams() != 1)
> +      CT = Ctor_CopyingClosure;
> +  }
> +
>    uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity();
>    SmallString<256> MangledName;
>    {
>      llvm::raw_svector_ostream Out(MangledName);
> -    getMangleContext().mangleCXXCatchableType(T, CD, Size, NVOffset,
> +    getMangleContext().mangleCXXCatchableType(T, CD, CT, Size, NVOffset,
>                                                VBPtrOffset, VBIndex, Out);
>    }
>    if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName))
>      return getImageRelativeConstant(GV);
>
> -  // The TypeDescriptor is used by the runtime to determine of a catch handler
> +  // The TypeDescriptor is used by the runtime to determine if a catch handler
>    // is appropriate for the exception object.
>    llvm::Constant *TD = getImageRelativeConstant(getAddrOfRTTIDescriptor(T));
>
>    // The runtime is responsible for calling the copy constructor if the
>    // exception is caught by value.
> -  llvm::Constant *CopyCtor =
> -      CD ? llvm::ConstantExpr::getBitCast(
> -               CGM.getAddrOfCXXStructor(CD, StructorType::Complete),
> -               CGM.Int8PtrTy)
> -         : llvm::Constant::getNullValue(CGM.Int8PtrTy);
> +  llvm::Constant *CopyCtor;
> +  if (CD) {
> +    if (CT == Ctor_CopyingClosure)
> +      CopyCtor = getAddrOfCXXCopyCtorClosure(CD);
> +    else
> +      CopyCtor = CGM.getAddrOfCXXStructor(CD, StructorType::Complete);
> +
> +    CopyCtor = llvm::ConstantExpr::getBitCast(CopyCtor, CGM.Int8PtrTy);
> +  } else {
> +    CopyCtor = llvm::Constant::getNullValue(CGM.Int8PtrTy);
> +  }
>    CopyCtor = getImageRelativeConstant(CopyCtor);
>
>    bool IsScalar = !RD;
>
> Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Wed Mar 11 13:36:39 2015
> @@ -782,14 +782,51 @@ ExprResult Sema::CheckCXXThrowOperand(So
>      }
>    }
>
> +  // The MSVC ABI creates a list of all types which can catch the exception
> +  // object.  This list also references the appropriate copy constructor to call
> +  // if the object is caught by value and has a non-trivial copy constructor.
>    if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
> +    // We are only interested in the public, unambiguous bases contained within
> +    // the exception object.  Bases which are ambiguous or otherwise
> +    // inaccessible are not catchable types.
>      llvm::SmallVector<CXXRecordDecl *, 2> UnambiguousPublicSubobjects;
>      getUnambiguousPublicSubobjects(RD, UnambiguousPublicSubobjects);
> +
>      for (CXXRecordDecl *Subobject : UnambiguousPublicSubobjects) {
> -      if (CXXConstructorDecl *CD = LookupCopyingConstructor(Subobject, 0)) {
> -        MarkFunctionReferenced(E->getExprLoc(), CD);
> -        if (!CD->isTrivial())
> -          Context.addCopyConstructorForExceptionObject(Subobject, CD);
> +      // Attempt to lookup the copy constructor.  Various pieces of machinery
> +      // will spring into action, like template instantiation, which means this
> +      // cannot be a simple walk of the class's decls.  Instead, we must perform
> +      // lookup and overload resolution.
> +      CXXConstructorDecl *CD = LookupCopyingConstructor(Subobject, 0);
> +      if (!CD)
> +        continue;
> +
> +      // Mark the constructor referenced as it is used by this throw expression.
> +      MarkFunctionReferenced(E->getExprLoc(), CD);
> +
> +      // Skip this copy constructor if it is trivial, we don't need to record it
> +      // in the catchable type data.
> +      if (CD->isTrivial())
> +        continue;
> +
> +      // The copy constructor is non-trivial, create a mapping from this class
> +      // type to this constructor.
> +      // N.B.  The selection of copy constructor is not sensitive to this
> +      // particular throw-site.  Lookup will be performed at the catch-site to
> +      // ensure that the copy constructor is, in fact, accessible (via
> +      // friendship or any other means).
> +      Context.addCopyConstructorForExceptionObject(Subobject, CD);
> +
> +      // We don't keep the instantiated default argument expressions around so
> +      // we must rebuild them here.
> +      for (unsigned I = 1, E = CD->getNumParams(); I != E; ++I) {
> +        // Skip any default arguments that we've already instantiated.
> +        if (Context.getDefaultArgExprForConstructor(CD, I))
> +          continue;
> +
> +        Expr *DefaultArg =
> +            BuildCXXDefaultArgExpr(ThrowLoc, CD, CD->getParamDecl(I)).get();
> +        Context.addDefaultArgExprForConstructor(CD, I, DefaultArg);
>        }
>      }
>    }
>
> Modified: cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp?rev=231952&r1=231951&r2=231952&view=diff
> ==============================================================================
> --- cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp (original)
> +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp Wed Mar 11 13:36:39 2015
> @@ -1,4 +1,4 @@
> -// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 %s -fcxx-exceptions | FileCheck %s
> +// RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 -std=c++11 %s -fcxx-exceptions | FileCheck %s
>
>  // CHECK-DAG: @"\01??_R0?AUY@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] c".?AUY@@\00" }, comdat
>  // CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE at ABU0@@Z8" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUY@@@8" to i8*), i32 0, i32 -1, i32 0, i32 8, i8* bitcast (%struct.Y* (%struct.Y*, %struct.Y*, i32)* @"\01??0Y@@QAE at ABU0@@Z" to i8*) }, section ".xdata", comdat
> @@ -12,6 +12,9 @@
>  // CHECK-DAG: @"_CT??_R0?AUV@@@81044" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* @"\01??_R0?AUV@@@8" to i8*), i32 0, i32 4, i32 4, i32 1, i8* null }, section ".xdata", comdat
>  // CHECK-DAG: @"_CTA5?AUY@@" = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.5 { i32 5, [5 x %eh.CatchableType*] [%eh.CatchableType* @"_CT??_R0?AUY@@@8??0Y@@QAE at ABU0@@Z8", %eh.CatchableType* @"_CT??_R0?AUZ@@@81", %eh.CatchableType* @"_CT??_R0?AUW@@@8??0W@@QAE at ABU0@@Z44", %eh.CatchableType* @"_CT??_R0?AUM@@@818", %eh.CatchableType* @"_CT??_R0?AUV@@@81044"] }, section ".xdata", comdat
>  // CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"\01??_DY@@QAE at XZ" to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" to i8*) }, section ".xdata", comdat
> +// CHECK-DAG: @"_CT??_R0?AUDefault@@@8??_ODefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor13* @"\01??_R0?AUDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Default*, %struct.Default*)* @"\01??_ODefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
> +// CHECK-DAG: @"_CT??_R0?AUVariadic@@@8??_OVariadic@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor14* @"\01??_R0?AUVariadic@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.Variadic*, %struct.Variadic*)* @"\01??_OVariadic@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
> +// CHECK-DAG: @"_CT??_R0?AUTemplateWithDefault@@@8??$?_OH at TemplateWithDefault@@QAEXAAU0@@Z1" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor25* @"\01??_R0?AUTemplateWithDefault@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* bitcast (void (%struct.TemplateWithDefault*, %struct.TemplateWithDefault*)* @"\01??$?_OH at TemplateWithDefault@@QAEXAAU0@@Z" to i8*) }, section ".xdata", comdat
>
>
>  struct N { ~N(); };
> @@ -35,3 +38,52 @@ void g(const int *const *y) {
>    // CHECK: call void @_CxxThrowException(i8* %{{.*}}, %eh.ThrowInfo* @_TIC2PAPBH)
>    throw y;
>  }
> +
> +struct Default {
> +  Default(Default &, int = 42);
> +};
> +
> +// CHECK-LABEL: @"\01??_ODefault@@QAEXAAU0@@Z"
> +// CHECK: %[[src_addr:.*]] = alloca
> +// CHECK: %[[this_addr:.*]] = alloca
> +// CHECK: store {{.*}} %src, {{.*}} %[[src_addr]], align 4
> +// CHECK: store {{.*}} %this, {{.*}} %[[this_addr]], align 4
> +// CHECK: %[[this:.*]] = load {{.*}} %[[this_addr]]
> +// CHECK: %[[src:.*]] = load {{.*}} %[[src_addr]]
> +// CHECK: call x86_thiscallcc {{.*}} @"\01??0Default@@QAE at AAU0@H at Z"({{.*}} %[[this]], {{.*}} %[[src]], i32 42)
> +// CHECK: ret void
> +
> +void h(Default &d) {
> +  throw d;
> +}
> +
> +struct Variadic {
> +  Variadic(Variadic &, ...);
> +};
> +
> +void i(Variadic &v) {
> +  throw v;
> +}
> +
> +// CHECK-LABEL: @"\01??_OVariadic@@QAEXAAU0@@Z"
> +// CHECK:  %[[src_addr:.*]] = alloca
> +// CHECK:  %[[this_addr:.*]] = alloca
> +// CHECK:  store {{.*}} %src, {{.*}} %[[src_addr:.*]], align
> +// CHECK:  store {{.*}} %this, {{.*}} %[[this_addr:.*]], align
> +// CHECK:  %[[this:.*]] = load {{.*}} %[[this_addr]]
> +// CHECK:  %[[src:.*]] = load {{.*}} %[[src_addr]]
> +// CHECK:  %call = call {{.*}} @"\01??0Variadic@@QAA at AAU0@ZZ"({{.*}} %[[this]], {{.*}} %[[src]])
> +// CHECK:  ret void
> +
> +struct TemplateWithDefault {
> +  template <typename T>
> +  static int f() {
> +    return 0;
> +  }
> +  template <typename T = int>
> +  TemplateWithDefault(TemplateWithDefault &, T = f<T>());
> +};
> +
> +void j(TemplateWithDefault &twd) {
> +  throw twd;
> +}
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits




More information about the cfe-commits mailing list