On Fri, Mar 6, 2015 at 10:53 AM, David Majnemer <[email protected]> wrote:
> Author: majnemer > Date: Fri Mar 6 12:53:55 2015 > New Revision: 231499 > > URL: http://llvm.org/viewvc/llvm-project?rev=231499&view=rev > Log: > MS ABI: Insert copy-constructors into the CatchableType > > Find all unambiguous public classes of the exception object's class type > and reference all of their copy constructors. Yes, this is not > conforming but it is necessary in order to implement their ABI. This is > because the copy constructor is actually referenced by the metadata > describing which catch handlers are eligible to handle the exception > object. > > N.B. This doesn't yet handle the copy constructor closure case yet, > that work is ongoing. > > Differential Revision: http://reviews.llvm.org/D8101 > > Modified: > cfe/trunk/include/clang/AST/ASTContext.h > cfe/trunk/include/clang/AST/Mangle.h > cfe/trunk/lib/AST/ASTContext.cpp > cfe/trunk/lib/AST/CXXABI.h > cfe/trunk/lib/AST/ItaniumCXXABI.cpp > cfe/trunk/lib/AST/MicrosoftCXXABI.cpp > cfe/trunk/lib/AST/MicrosoftMangle.cpp > 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=231499&r1=231498&r2=231499&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/AST/ASTContext.h (original) > +++ cfe/trunk/include/clang/AST/ASTContext.h Fri Mar 6 12:53:55 2015 > @@ -2193,6 +2193,12 @@ public: > /// it is not used. > bool DeclMustBeEmitted(const Decl *D); > > + const CXXConstructorDecl * > + getCopyConstructorForExceptionObject(CXXRecordDecl *RD); > + > + void addCopyConstructorForExceptionObject(CXXRecordDecl *RD, > + CXXConstructorDecl *CD); > + > 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=231499&r1=231498&r2=231499&view=diff > > ============================================================================== > --- cfe/trunk/include/clang/AST/Mangle.h (original) > +++ cfe/trunk/include/clang/AST/Mangle.h Fri Mar 6 12:53:55 2015 > @@ -203,8 +203,8 @@ public: > virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t > NumEntries, > raw_ostream &Out) = 0; > > - virtual void mangleCXXCatchableType(QualType T, uint32_t Size, > - raw_ostream &Out) = 0; > + virtual void mangleCXXCatchableType(QualType T, const > CXXConstructorDecl *CD, > + uint32_t Size, raw_ostream &Out) = > 0; > > virtual void mangleCXXRTTIBaseClassDescriptor( > const CXXRecordDecl *Derived, uint32_t NVOffset, int32_t > VBPtrOffset, > > Modified: cfe/trunk/lib/AST/ASTContext.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=231499&r1=231498&r2=231499&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/ASTContext.cpp (original) > +++ cfe/trunk/lib/AST/ASTContext.cpp Fri Mar 6 12:53:55 2015 > @@ -8189,6 +8189,19 @@ MangleNumberingContext *ASTContext::crea > return ABI->createMangleNumberingContext(); > } > > +const CXXConstructorDecl * > +ASTContext::getCopyConstructorForExceptionObject(CXXRecordDecl *RD) { > + return ABI->getCopyConstructorForExceptionObject( > + cast<CXXRecordDecl>(RD->getFirstDecl())); > +} > + > +void ASTContext::addCopyConstructorForExceptionObject(CXXRecordDecl *RD, > + CXXConstructorDecl > *CD) { > + return ABI->addCopyConstructorForExceptionObject( > + cast<CXXRecordDecl>(RD->getFirstDecl()), > + cast<CXXConstructorDecl>(CD->getFirstDecl())); > +} > + > 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=231499&r1=231498&r2=231499&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/CXXABI.h (original) > +++ cfe/trunk/lib/AST/CXXABI.h Fri Mar 6 12:53:55 2015 > @@ -20,6 +20,7 @@ > namespace clang { > > class ASTContext; > +class CXXConstructorDecl; > class MemberPointerType; > class MangleNumberingContext; > > @@ -41,6 +42,14 @@ public: > > /// Returns a new mangling number context for this C++ ABI. > virtual MangleNumberingContext *createMangleNumberingContext() const = > 0; > + > + /// Adds a mapping from class to copy constructor for this C++ ABI. > + virtual void addCopyConstructorForExceptionObject(CXXRecordDecl *, > + CXXConstructorDecl *) > = 0; > + > + /// Retrieves the mapping from class to copy constructor for this C++ > ABI. > + virtual const CXXConstructorDecl * > + getCopyConstructorForExceptionObject(CXXRecordDecl *) = 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=231499&r1=231498&r2=231499&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/ItaniumCXXABI.cpp (original) > +++ cfe/trunk/lib/AST/ItaniumCXXABI.cpp Fri Mar 6 12:53:55 2015 > @@ -133,6 +133,14 @@ public: > return Layout.getNonVirtualSize() == PointerSize; > } > > + const CXXConstructorDecl * > + getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { > + return nullptr; > + } > + > + void addCopyConstructorForExceptionObject(CXXRecordDecl *RD, > + CXXConstructorDecl *CD) > override {} > + > MangleNumberingContext *createMangleNumberingContext() const override { > return new ItaniumNumberingContext(); > } > > Modified: cfe/trunk/lib/AST/MicrosoftCXXABI.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftCXXABI.cpp?rev=231499&r1=231498&r2=231499&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/MicrosoftCXXABI.cpp (original) > +++ cfe/trunk/lib/AST/MicrosoftCXXABI.cpp Fri Mar 6 12:53:55 2015 > @@ -63,6 +63,8 @@ public: > > class MicrosoftCXXABI : public CXXABI { > ASTContext &Context; > + llvm::SmallDenseMap<CXXRecordDecl *, CXXConstructorDecl *> > RecordToCopyCtor; > + > public: > MicrosoftCXXABI(ASTContext &Ctx) : Context(Ctx) { } > > @@ -82,13 +84,26 @@ public: > return false; > > const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); > - > + > // In the Microsoft ABI, classes can have one or two vtable pointers. > - CharUnits PointerSize = > - > Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); > + CharUnits PointerSize = > + > Context.toCharUnitsFromBits(Context.getTargetInfo().getPointerWidth(0)); > return Layout.getNonVirtualSize() == PointerSize || > Layout.getNonVirtualSize() == PointerSize * 2; > - } > + } > + > + const CXXConstructorDecl * > + getCopyConstructorForExceptionObject(CXXRecordDecl *RD) override { > + return RecordToCopyCtor[RD]; > + } > + > + void > + addCopyConstructorForExceptionObject(CXXRecordDecl *RD, > + CXXConstructorDecl *CD) override { > + assert(CD != nullptr); > + assert(RecordToCopyCtor[RD] == nullptr || RecordToCopyCtor[RD] == CD); > + RecordToCopyCtor[RD] = CD; > + } > > MangleNumberingContext *createMangleNumberingContext() const override { > return new MicrosoftNumberingContext(); > > Modified: cfe/trunk/lib/AST/MicrosoftMangle.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/MicrosoftMangle.cpp?rev=231499&r1=231498&r2=231499&view=diff > > ============================================================================== > --- cfe/trunk/lib/AST/MicrosoftMangle.cpp (original) > +++ cfe/trunk/lib/AST/MicrosoftMangle.cpp Fri Mar 6 12:53:55 2015 > @@ -114,8 +114,8 @@ public: > uint32_t NumEntries, raw_ostream &Out) override; > void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries, > raw_ostream &Out) override; > - void mangleCXXCatchableType(QualType T, uint32_t Size, > - raw_ostream &Out) override; > + void mangleCXXCatchableType(QualType T, const CXXConstructorDecl *CD, > + uint32_t Size, raw_ostream &Out) override; > void mangleCXXRTTI(QualType T, raw_ostream &Out) override; > void mangleCXXRTTIName(QualType T, raw_ostream &Out) override; > void mangleCXXRTTIBaseClassDescriptor(const CXXRecordDecl *Derived, > @@ -2307,13 +2307,25 @@ void MicrosoftMangleContextImpl::mangleC > Mangler.mangleType(T, SourceRange(), > MicrosoftCXXNameMangler::QMM_Result); > } > > -void MicrosoftMangleContextImpl::mangleCXXCatchableType(QualType T, > - uint32_t Size, > - raw_ostream &Out) > { > +void MicrosoftMangleContextImpl::mangleCXXCatchableType( > + QualType T, const CXXConstructorDecl *CD, uint32_t Size, raw_ostream > &Out) { > MicrosoftCXXNameMangler Mangler(*this, Out); > - Mangler.getStream() << "_CT??_R0"; > - Mangler.mangleType(T, SourceRange(), > MicrosoftCXXNameMangler::QMM_Result); > - Mangler.getStream() << "@8"; > + Mangler.getStream() << "_CT"; > + > + llvm::SmallString<64> RTTIMangling; > + { > + llvm::raw_svector_ostream Stream(RTTIMangling); > + mangleCXXRTTI(T, Stream); > + } > + Mangler.getStream() << RTTIMangling.substr(1); > + > + llvm::SmallString<64> CopyCtorMangling; > + if (CD) { > + llvm::raw_svector_ostream Stream(CopyCtorMangling); > + mangleCXXCtor(CD, Ctor_Complete, Stream); > + } > + Mangler.getStream() << CopyCtorMangling.substr(1); > + > Mangler.getStream() << Size; > } > > > Modified: cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp?rev=231499&r1=231498&r2=231499&view=diff > > ============================================================================== > --- cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp (original) > +++ cfe/trunk/lib/CodeGen/MicrosoftCXXABI.cpp Fri Mar 6 12:53:55 2015 > @@ -17,6 +17,7 @@ > #include "CGCXXABI.h" > #include "CGVTables.h" > #include "CodeGenModule.h" > +#include "CodeGenTypes.h" > #include "TargetInfo.h" > #include "clang/AST/Decl.h" > #include "clang/AST/DeclCXX.h" > @@ -3225,11 +3226,14 @@ llvm::Constant *MicrosoftCXXABI::getCatc > uint32_t VBIndex) { > assert(!T->isReferenceType()); > > + CXXRecordDecl *RD = T->getAsCXXRecordDecl(); > + const CXXConstructorDecl *CD = > + RD ? CGM.getContext().getCopyConstructorForExceptionObject(RD) : > nullptr; > uint32_t Size = getContext().getTypeSizeInChars(T).getQuantity(); > SmallString<256> MangledName; > { > llvm::raw_svector_ostream Out(MangledName); > - getMangleContext().mangleCXXCatchableType(T, Size, Out); > + getMangleContext().mangleCXXCatchableType(T, CD, Size, Out); > } > if (llvm::GlobalVariable *GV = > CGM.getModule().getNamedGlobal(MangledName)) > return getImageRelativeConstant(GV); > @@ -3241,16 +3245,15 @@ llvm::Constant *MicrosoftCXXABI::getCatc > // The runtime is responsible for calling the copy constructor if the > // exception is caught by value. > llvm::Constant *CopyCtor = > - > getImageRelativeConstant(llvm::Constant::getNullValue(CGM.Int8PtrTy)); > + CD ? llvm::ConstantExpr::getBitCast( > + CGM.getAddrOfCXXStructor(CD, StructorType::Complete), > + CGM.Int8PtrTy) > + : llvm::Constant::getNullValue(CGM.Int8PtrTy); > + CopyCtor = getImageRelativeConstant(CopyCtor); > > - bool IsScalar = true; > + bool IsScalar = !RD; > bool HasVirtualBases = false; > bool IsStdBadAlloc = false; // std::bad_alloc is special for some > reason. > - if (T->getAsCXXRecordDecl()) { > - IsScalar = false; > - // TODO: Fill in the CopyCtor here! This is not trivial due to > - // copy-constructors possessing things like default arguments. > - } > QualType PointeeType = T; > if (T->isPointerType()) > PointeeType = T->getPointeeType(); > > Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp > URL: > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=231499&r1=231498&r2=231499&view=diff > > ============================================================================== > --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) > +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Fri Mar 6 12:53:55 2015 > @@ -657,6 +657,55 @@ ExprResult Sema::BuildCXXThrow(SourceLoc > CXXThrowExpr(Ex, Context.VoidTy, OpLoc, IsThrownVarInScope); > } > > +static void > +collectPublicBases(CXXRecordDecl *RD, > + llvm::DenseMap<CXXRecordDecl *, unsigned> > &SubobjectsSeen, > + llvm::SmallPtrSetImpl<CXXRecordDecl *> &VBases, > + llvm::SetVector<CXXRecordDecl *> &PublicSubobjectsSeen, > + bool ParentIsPublic) { > + for (const CXXBaseSpecifier &BS : RD->bases()) { > + CXXRecordDecl *BaseDecl = BS.getType()->getAsCXXRecordDecl(); > + bool NewSubobject; > + // Virtual bases constitute the same subobject. Non-virtual bases are > + // always distinct subobjects. > + if (BS.isVirtual()) > + NewSubobject = VBases.insert(BaseDecl).second; > + else > + NewSubobject = true; > + > + if (NewSubobject) > + ++SubobjectsSeen[BaseDecl]; > + > + // Only add subobjects which have public access throughout the entire > chain. > + bool PublicPath = ParentIsPublic && BS.getAccessSpecifier() == > AS_public; > + if (PublicPath) > + PublicSubobjectsSeen.insert(BaseDecl); > + > + // Recurse on to each base subobject. > + collectPublicBases(BaseDecl, SubobjectsSeen, VBases, > PublicSubobjectsSeen, > + PublicPath); > + } > +} > + > +static void getUnambiguousPublicSubobjects( > + CXXRecordDecl *RD, llvm::SmallVectorImpl<CXXRecordDecl *> &Objects) { > + llvm::DenseMap<CXXRecordDecl *, unsigned> SubobjectsSeen; > + llvm::SmallSet<CXXRecordDecl *, 2> VBases; > + llvm::SetVector<CXXRecordDecl *> PublicSubobjectsSeen; > + SubobjectsSeen[RD] = 1; > + PublicSubobjectsSeen.insert(RD); > + collectPublicBases(RD, SubobjectsSeen, VBases, PublicSubobjectsSeen, > + /*ParentIsPublic=*/true); > + > + for (CXXRecordDecl *PublicSubobject : PublicSubobjectsSeen) { > + // Skip ambiguous objects. > + if (SubobjectsSeen[PublicSubobject] > 1) > + continue; > + > + Objects.push_back(PublicSubobject); > + } > +} > + > /// CheckCXXThrowOperand - Validate the operand of a throw. > ExprResult Sema::CheckCXXThrowOperand(SourceLocation ThrowLoc, Expr *E, > bool IsThrownVarInScope) { > @@ -723,18 +772,29 @@ ExprResult Sema::CheckCXXThrowOperand(So > return E; > > // If the class has a destructor, we must be able to call it. > - if (RD->hasIrrelevantDestructor()) > - return E; > + if (!RD->hasIrrelevantDestructor()) { > + if (CXXDestructorDecl *Destructor = LookupDestructor(RD)) { > + MarkFunctionReferenced(E->getExprLoc(), Destructor); > + CheckDestructorAccess(E->getExprLoc(), Destructor, > + PDiag(diag::err_access_dtor_exception) << Ty); > + if (DiagnoseUseOfDecl(Destructor, E->getExprLoc())) > + return ExprError(); > + } > + } > > - CXXDestructorDecl *Destructor = LookupDestructor(RD); > - if (!Destructor) > - return E; > + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { > + llvm::SmallVector<CXXRecordDecl *, 2> UnambiguousPublicSubobjects; > + getUnambiguousPublicSubobjects(RD, UnambiguousPublicSubobjects); > + for (CXXRecordDecl *Subobject : UnambiguousPublicSubobjects) { > + if (CXXConstructorDecl *CD = LookupCopyingConstructor(Subobject, > 0)) { > + if (CD->isTrivial()) > + continue; > Is this necessary? MarkFunctionReferenced checks this for constructors already. If it is necessary, do yo need to check for || hasAttr<DLLExportAttr> here? Same question for destructors above (think of an explicit defaulted protected dtor, which is trivial but not irrelevant.) > + MarkFunctionReferenced(E->getExprLoc(), CD); > + Context.addCopyConstructorForExceptionObject(Subobject, CD); > + } > + } > + } > > - MarkFunctionReferenced(E->getExprLoc(), Destructor); > - CheckDestructorAccess(E->getExprLoc(), Destructor, > - PDiag(diag::err_access_dtor_exception) << Ty); > - if (DiagnoseUseOfDecl(Destructor, E->getExprLoc())) > - return ExprError(); > return E; > } > > > 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=231499&r1=231498&r2=231499&view=diff > > ============================================================================== > --- cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp (original) > +++ cfe/trunk/test/CodeGenCXX/microsoft-abi-throw.cpp Fri Mar 6 12:53:55 > 2015 > @@ -1,16 +1,16 @@ > // RUN: %clang_cc1 -emit-llvm -o - -triple=i386-pc-win32 %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@@@88" = 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* null }, > comdat > +// CHECK-DAG: @"_CT??_R0?AUY@@@8??0Y@@QAE@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@ABU0@@Z" to i8*) }, comdat > // CHECK-DAG: @"\01??_R0?AUZ@@@8" = linkonce_odr global > %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] > c".?AUZ@@\00" }, comdat > // CHECK-DAG: @"_CT??_R0?AUZ@@@81" = linkonce_odr unnamed_addr constant > %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* > @"\01??_R0?AUZ@@@8" to i8*), i32 0, i32 -1, i32 0, i32 1, i8* null }, > comdat > // CHECK-DAG: @"\01??_R0?AUW@@@8" = linkonce_odr global > %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] > c".?AUW@@\00" }, comdat > -// CHECK-DAG: @"_CT??_R0?AUW@@@84" = linkonce_odr unnamed_addr constant > %eh.CatchableType { i32 4, i8* bitcast (%rtti.TypeDescriptor7* > @"\01??_R0?AUW@@@8" to i8*), i32 4, i32 -1, i32 0, i32 4, i8* null }, > comdat > +// CHECK-DAG: @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z4" = linkonce_odr > unnamed_addr constant %eh.CatchableType { i32 4, i8* bitcast > (%rtti.TypeDescriptor7* @"\01??_R0?AUW@@@8" to i8*), i32 4, i32 -1, i32 > 0, i32 4, i8* bitcast (%struct.W* (%struct.W*, %struct.W*, i32)* @"\01??0W@ > @QAE@ABU0@@Z" to i8*) }, comdat > // CHECK-DAG: @"\01??_R0?AUM@@@8" = linkonce_odr global > %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] > c".?AUM@@\00" }, comdat > // CHECK-DAG: @"_CT??_R0?AUM@@@81" = linkonce_odr unnamed_addr constant > %eh.CatchableType { i32 0, i8* bitcast (%rtti.TypeDescriptor7* > @"\01??_R0?AUM@@@8" to i8*), i32 8, i32 -1, i32 0, i32 1, i8* null }, > comdat > // CHECK-DAG: @"\01??_R0?AUV@@@8" = linkonce_odr global > %rtti.TypeDescriptor7 { i8** @"\01??_7type_info@@6B@", i8* null, [8 x i8] > c".?AUV@@\00" }, comdat > // CHECK-DAG: @"_CT??_R0?AUV@@@81" = 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 }, > comdat > -// CHECK-DAG: @"_CTA5?AUY@@" = linkonce_odr unnamed_addr constant > %eh.CatchableTypeArray.5 { i32 5, [5 x %eh.CatchableType*] > [%eh.CatchableType* @"_CT??_R0?AUY@@@88", %eh.CatchableType* > @"_CT??_R0?AUZ@@@81", %eh.CatchableType* @"_CT??_R0?AUW@@@84", > %eh.CatchableType* @"_CT??_R0?AUM@@@81", %eh.CatchableType* > @"_CT??_R0?AUV@@@81"] }, 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@ABU0@@Z8", > %eh.CatchableType* @"_CT??_R0?AUZ@@@81", %eh.CatchableType* > @"_CT??_R0?AUW@@@8??0W@@QAE@ABU0@@Z4", %eh.CatchableType* > @"_CT??_R0?AUM@@@81", > %eh.CatchableType* @"_CT??_R0?AUV@@@81"] }, comdat > // CHECK-DAG: @"_TI5?AUY@@" = linkonce_odr unnamed_addr constant > %eh.ThrowInfo { i32 0, i8* bitcast (void (%struct.Y*)* @"\01??_DY@@QAE@XZ" > to i8*), i8* null, i8* bitcast (%eh.CatchableTypeArray.5* @"_CTA5?AUY@@" > to i8*) }, comdat > > > > > _______________________________________________ > cfe-commits mailing list > [email protected] > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
