r231952 - MS ABI: Implement copy-ctor closures, finish implementing throw
David Majnemer
david.majnemer at gmail.com
Wed Mar 11 11:36:39 PDT 2015
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());
+ 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;
+}
More information about the cfe-commits
mailing list