Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -252,6 +252,11 @@ /// MicrosoftCXXNameMangler - Manage the mangling of a single name for the /// Microsoft Visual C++ ABI. class MicrosoftCXXNameMangler { +public: + enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result }; + enum ForRTTI_t : bool { NotForRTTI = false, ForRTTI = true }; + +private: MicrosoftMangleContextImpl &Context; raw_ostream &Out; @@ -276,25 +281,35 @@ // this check into mangleQualifiers(). const bool PointersAre64Bit; -public: - enum QualifierMangleMode { QMM_Drop, QMM_Mangle, QMM_Escape, QMM_Result }; + ForRTTI_t IsForRTTI; +public: MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_) : Context(C), Out(Out_), Structor(nullptr), StructorType(-1), PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == - 64) {} + 64), + IsForRTTI(NotForRTTI) {} 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) {} + 64), + IsForRTTI(NotForRTTI) {} 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) == - 64) {} + 64), + IsForRTTI(NotForRTTI) {} + + MicrosoftCXXNameMangler(MicrosoftMangleContextImpl &C, raw_ostream &Out_, + ForRTTI_t IsForRTTI) + : Context(C), Out(Out_), Structor(nullptr), StructorType(-1), + PointersAre64Bit(C.getASTContext().getTargetInfo().getPointerWidth(0) == + 64), + IsForRTTI(IsForRTTI) {} raw_ostream &getStream() const { return Out; } @@ -339,6 +354,7 @@ void mangleTemplateInstantiationName(const TemplateDecl *TD, const TemplateArgumentList &TemplateArgs); + void mangleObjCClassName(StringRef Name); void mangleObjCMethodName(const ObjCMethodDecl *MD); void mangleArgumentType(QualType T, SourceRange Range); @@ -1277,6 +1293,27 @@ } } +void MicrosoftCXXNameMangler::mangleObjCClassName(StringRef Name) { + // Obj-C classes are normally mangled as C++ structs with the same name, but + // we want to be able to distinguish a C++ struct X from an Obj-C class X for + // the purposes of exception handling, so we add a discriminator when mangling + // for RTTI. + if (!IsForRTTI) { + mangleArtificalTagType(TTK_Struct, Name); + return; + } + + llvm::SmallString<64> TemplateMangling; + llvm::raw_svector_ostream Stream(TemplateMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + + Stream << "?$"; + Extra.mangleSourceName("Class"); + Extra.mangleArtificalTagType(TTK_Struct, Name); + + mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); +} + void MicrosoftCXXNameMangler::mangleObjCMethodName(const ObjCMethodDecl *MD) { Context.mangleObjCMethodName(MD, Out); } @@ -1951,7 +1988,7 @@ llvm_unreachable("placeholder types shouldn't get to name mangling"); case BuiltinType::ObjCId: - mangleArtificalTagType(TTK_Struct, "objc_object"); + mangleObjCClassName("objc_object"); break; case BuiltinType::ObjCClass: mangleArtificalTagType(TTK_Struct, "objc_class"); @@ -2644,9 +2681,7 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers, SourceRange) { - // ObjC interfaces have structs underlying them. - mangleTagTypeKind(TTK_Struct); - mangleName(T->getDecl()); + mangleObjCClassName(T->getDecl()->getName()); } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, @@ -3006,7 +3041,7 @@ void MicrosoftMangleContextImpl::mangleCXXRTTI(QualType T, raw_ostream &Out) { msvc_hashing_ostream MHO(Out); - MicrosoftCXXNameMangler Mangler(*this, MHO); + MicrosoftCXXNameMangler Mangler(*this, MHO, MicrosoftCXXNameMangler::ForRTTI); Mangler.getStream() << "??_R0"; Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); Mangler.getStream() << "@8"; @@ -3014,7 +3049,7 @@ void MicrosoftMangleContextImpl::mangleCXXRTTIName(QualType T, raw_ostream &Out) { - MicrosoftCXXNameMangler Mangler(*this, Out); + MicrosoftCXXNameMangler Mangler(*this, Out, MicrosoftCXXNameMangler::ForRTTI); Mangler.getStream() << '.'; Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); } Index: test/CodeGenObjCXX/msabi-objc-exceptions-gnustep.mm =================================================================== --- /dev/null +++ test/CodeGenObjCXX/msabi-objc-exceptions-gnustep.mm @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple i686-windows-msvc -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -emit-llvm -o - %s | FileCheck -check-prefix=X86 %s +// RUN: %clang_cc1 -triple x86_64-windows-msvc -fobjc-runtime=gnustep-2.0 -fexceptions -fobjc-exceptions -emit-llvm -o - %s | FileCheck -check-prefix=X64 %s + +// Ensure we have the __ObjC::class discriminator in the RTTI and the RTTI name. +// X86-DAG: @"??_R0PAU?$Class@Uobjc_object@@@__ObjC@@@8" = linkonce_odr global %{{[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [36 x i8] c".PAU?$Class@Uobjc_object@@@__ObjC@@\00" }, comdat +// X64-DAG: @"??_R0PEAU?$Class@Uobjc_object@@@__ObjC@@@8" = linkonce_odr global %{{[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [37 x i8] c".PEAU?$Class@Uobjc_object@@@__ObjC@@\00" }, comdat + +@class I; +// X86-DAG: @"??_R0PAU?$Class@UI@@@__ObjC@@@8" = linkonce_odr global %{{[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [26 x i8] c".PAU?$Class@UI@@@__ObjC@@\00" }, comdat +// X64-DAG: @"??_R0PEAU?$Class@UI@@@__ObjC@@@8" = linkonce_odr global %{{[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [27 x i8] c".PEAU?$Class@UI@@@__ObjC@@\00" }, comdat + +void f(); +void g() { + @try { + f(); + } @catch (I *) { + } @catch (id) { + } +}