Index: lib/AST/MicrosoftMangle.cpp =================================================================== --- lib/AST/MicrosoftMangle.cpp +++ lib/AST/MicrosoftMangle.cpp @@ -312,7 +312,7 @@ void mangleArtificalTagType(TagTypeKind TK, StringRef UnqualifiedName, ArrayRef NestedNames = None); void mangleType(QualType T, SourceRange Range, - QualifierMangleMode QMM = QMM_Mangle); + QualifierMangleMode QMM = QMM_Mangle, bool ForRTTI = false); void mangleFunctionType(const FunctionType *T, const FunctionDecl *D = nullptr, bool ForceThisQuals = false); @@ -357,6 +357,16 @@ #undef NON_CANONICAL_TYPE #undef TYPE + // Obj-C mangling needs special handing for RTTI. + void mangleType(const BuiltinType *T, Qualifiers Quals, SourceRange Range, + bool ForRTTI); + void mangleType(const ObjCInterfaceType *T, Qualifiers Quals, + SourceRange Range, bool ForRTTI); + void mangleType(const ObjCObjectType *T, Qualifiers Quals, SourceRange Range, + bool ForRTTI); + void mangleType(const ObjCObjectPointerType *T, Qualifiers Quals, + SourceRange Range, bool ForRTTI); + void mangleType(const TagDecl *TD); void mangleDecayedArrayType(const ArrayType *T); void mangleArrayType(const ArrayType *T); @@ -1778,7 +1788,8 @@ } void MicrosoftCXXNameMangler::mangleType(QualType T, SourceRange Range, - QualifierMangleMode QMM) { + QualifierMangleMode QMM, + bool ForRTTI) { // Don't use the canonical types. MSVC includes things like 'const' on // pointer arguments to function pointers that canonicalization strips away. T = T.getDesugaredType(getASTContext()); @@ -1830,6 +1841,23 @@ const Type *ty = T.getTypePtr(); + switch (ty->getTypeClass()) { + case Type::Builtin: + mangleType(cast(ty), Quals, Range, ForRTTI); + return; + case Type::ObjCObjectPointer: + mangleType(cast(ty), Quals, Range, ForRTTI); + return; + case Type::ObjCObject: + mangleType(cast(ty), Quals, Range, ForRTTI); + return; + case Type::ObjCInterface: + mangleType(cast(ty), Quals, Range, ForRTTI); + return; + default: + break; // handled by next switch + } + switch (ty->getTypeClass()) { #define ABSTRACT_TYPE(CLASS, PARENT) #define NON_CANONICAL_TYPE(CLASS, PARENT) \ @@ -1847,8 +1875,13 @@ } } -void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, +void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers Quals, SourceRange Range) { + mangleType(T, Quals, Range, /*ForRTTI=*/false); +} + +void MicrosoftCXXNameMangler::mangleType(const BuiltinType *T, Qualifiers, + SourceRange Range, bool ForRTTI) { // ::= // ::= X # void // ::= C # signed char @@ -1950,9 +1983,27 @@ case BuiltinType::Dependent: llvm_unreachable("placeholder types shouldn't get to name mangling"); - case BuiltinType::ObjCId: - mangleArtificalTagType(TTK_Struct, "objc_object"); + case BuiltinType::ObjCId: { + if (!ForRTTI) { + mangleArtificalTagType(TTK_Struct, "objc_object"); + break; + } + + llvm::SmallString<64> TemplateMangling; + llvm::raw_svector_ostream Stream(TemplateMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + + // Obj-C classes are 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. + Stream << "?$"; + Extra.mangleSourceName("Class"); + // ObjC interfaces have structs underlying them. + Extra.mangleArtificalTagType(TTK_Struct, "objc_object"); + + mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); break; + } case BuiltinType::ObjCClass: mangleArtificalTagType(TTK_Struct, "objc_class"); break; @@ -2488,6 +2539,12 @@ void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, Qualifiers Quals, SourceRange Range) { + mangleType(T, Quals, Range, /*ForRTTI=*/false); +} + +void MicrosoftCXXNameMangler::mangleType(const ObjCObjectPointerType *T, + Qualifiers Quals, SourceRange Range, + bool ForRTTI) { QualType PointeeType = T->getPointeeType(); switch (Quals.getObjCLifetime()) { case Qualifiers::OCL_None: @@ -2500,7 +2557,7 @@ } manglePointerCVQualifiers(Quals); manglePointerExtQualifiers(Quals, PointeeType); - mangleType(PointeeType, Range); + mangleType(PointeeType, Range, QMM_Mangle, /*ForRTTI=*/ForRTTI); } // ::= @@ -2635,20 +2692,48 @@ Diags.Report(Range.getBegin(), DiagID) << Range; } +void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, + Qualifiers Quals, SourceRange Range) { + mangleType(T, Quals, Range, /*ForRTTI=*/false); +} + void MicrosoftCXXNameMangler::mangleType(const ObjCInterfaceType *T, Qualifiers, - SourceRange) { + SourceRange, bool ForRTTI) { + if (!ForRTTI) { + // ObjC interfaces have structs underlying them. + mangleTagTypeKind(TTK_Struct); + mangleName(T->getDecl()); + return; + } + + llvm::SmallString<64> TemplateMangling; + llvm::raw_svector_ostream Stream(TemplateMangling); + MicrosoftCXXNameMangler Extra(Context, Stream); + + // Obj-C classes are 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. + Stream << "?$"; + Extra.mangleSourceName("Class"); // ObjC interfaces have structs underlying them. - mangleTagTypeKind(TTK_Struct); - mangleName(T->getDecl()); + Extra.mangleArtificalTagType(TTK_Struct, T->getDecl()->getName()); + + mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__ObjC"}); } void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, Qualifiers Quals, SourceRange Range) { + mangleType(T, Quals, Range, /*ForRTTI=*/false); +} + +void MicrosoftCXXNameMangler::mangleType(const ObjCObjectType *T, + Qualifiers Quals, SourceRange Range, + bool ForRTTI) { if (T->isKindOfType()) return mangleObjCKindOfType(T, Quals, Range); if (T->qual_empty() && !T->isSpecialized()) - return mangleType(T->getBaseType(), Range, QMM_Drop); + return mangleType(T->getBaseType(), Range, QMM_Drop, ForRTTI); ArgBackRefMap OuterArgsContext; BackRefVec OuterTemplateContext; @@ -3001,7 +3086,8 @@ msvc_hashing_ostream MHO(Out); MicrosoftCXXNameMangler Mangler(*this, MHO); Mangler.getStream() << "??_R0"; - Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); + Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result, + /*ForRTTI=*/true); Mangler.getStream() << "@8"; } @@ -3009,7 +3095,8 @@ raw_ostream &Out) { MicrosoftCXXNameMangler Mangler(*this, Out); Mangler.getStream() << '.'; - Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result); + Mangler.mangleType(T, SourceRange(), MicrosoftCXXNameMangler::QMM_Result, + /*ForRTTI=*/true); } void MicrosoftMangleContextImpl::mangleCXXVirtualDisplacementMap( 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) { + } +}