Index: lib/CodeGen/CGCXXABI.h =================================================================== --- lib/CodeGen/CGCXXABI.h +++ lib/CodeGen/CGCXXABI.h @@ -249,6 +249,10 @@ llvm::Value *Exn); virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) = 0; + virtual llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty, + StringRef MangledName) { + llvm_unreachable("Only needed for the Microsoft ABI"); + } virtual CatchTypeInfo getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) = 0; virtual CatchTypeInfo getCatchAllTypeInfo(); Index: lib/CodeGen/CGObjCMac.cpp =================================================================== --- lib/CodeGen/CGObjCMac.cpp +++ lib/CodeGen/CGObjCMac.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "CGBlocks.h" +#include "CGCXXABI.h" #include "CGCleanup.h" #include "CGObjCRuntime.h" #include "CGRecordLayout.h" @@ -6358,7 +6359,9 @@ DefinedNonLazyClasses.push_back(ClassMD); // Force the definition of the EHType if necessary. - if (flags & NonFragileABI_Class_Exception) + // Windows MSVC will just emit the EHType locally wherever needed instead. + if ((flags & NonFragileABI_Class_Exception) && + !CGM.getTriple().isWindowsMSVCEnvironment()) (void) GetInterfaceEHType(CI, ForDefinition); // Make sure method definition entries are all clear for next implementation. MethodDefinitions.clear(); @@ -7456,6 +7459,10 @@ CGObjCNonFragileABIMac::GetEHType(QualType T) { // There's a particular fixed type info for 'id'. if (T->isObjCIdType() || T->isObjCQualifiedIdType()) { + if (CGM.getTriple().isWindowsMSVCEnvironment()) + return CGM.getCXXABI().getAddrOfRTTIDescriptor( + T.getLocalUnqualifiedType(), "OBJC_EHTYPE_id"); + auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id"); if (!IDEHType) { IDEHType = @@ -7475,7 +7482,15 @@ const ObjCInterfaceType *IT = PT->getInterfaceType(); assert(IT && "Invalid @catch type."); - return GetInterfaceEHType(IT->getDecl(), NotForDefinition); + const ObjCInterfaceDecl *ID = IT->getDecl(); + if (CGM.getTriple().isWindowsMSVCEnvironment()) { + const ASTContext &Ctx = CGM.getContext(); + return CGM.getCXXABI().getAddrOfRTTIDescriptor( + Ctx.getObjCObjectPointerType(IT->stripObjCKindOfTypeAndQuals(Ctx)), + ("OBJC_EHTYPE_$_" + ID->getObjCRuntimeNameAsString()).str()); + } + + return GetInterfaceEHType(ID, NotForDefinition); } void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF, @@ -7508,6 +7523,9 @@ llvm::Constant * CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, ForDefinition_t IsForDefinition) { + assert(!CGM.getTriple().isWindowsMSVCEnvironment() && + "MSVC EHType should be emitted by GetEHType"); + llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()]; StringRef ClassName = ID->getObjCRuntimeNameAsString(); Index: lib/CodeGen/MicrosoftCXXABI.cpp =================================================================== --- lib/CodeGen/MicrosoftCXXABI.cpp +++ lib/CodeGen/MicrosoftCXXABI.cpp @@ -126,6 +126,8 @@ const VPtrInfo &Info); llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty) override; + llvm::Constant *getAddrOfRTTIDescriptor(QualType Ty, + StringRef MangledName) override; CatchTypeInfo getAddrOfCXXCatchHandlerType(QualType Ty, QualType CatchHandlerType) override; @@ -3759,7 +3761,11 @@ llvm::raw_svector_ostream Out(MangledName); getMangleContext().mangleCXXRTTI(Type, Out); } + return getAddrOfRTTIDescriptor(Type, MangledName); +} +llvm::Constant * +MicrosoftCXXABI::getAddrOfRTTIDescriptor(QualType Type, StringRef MangledName) { // Check to see if we've already declared this TypeDescriptor. if (llvm::GlobalVariable *GV = CGM.getModule().getNamedGlobal(MangledName)) return llvm::ConstantExpr::getBitCast(GV, CGM.Int8PtrTy); Index: test/CodeGenObjC/dllstorage.m =================================================================== --- test/CodeGenObjC/dllstorage.m +++ test/CodeGenObjC/dllstorage.m @@ -1,5 +1,5 @@ // RUN: %clang_cc1 -triple x86_64-unknown-windows-msvc -fdeclspec -fobjc-runtime=ios -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -check-prefix CHECK-IR %s -// RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=macosx -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -check-prefix CHECK-IR %s +// RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=macosx -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -check-prefix CHECK-IR -check-prefix CHECK-ITANIUM %s // RUN: %clang_cc1 -triple i686-windows-itanium -fms-extensions -fobjc-runtime=objfw -fdeclspec -fobjc-exceptions -S -emit-llvm -o - %s | FileCheck -check-prefix CHECK-FW %s // CHECK-IR-DAG: @_objc_empty_cache = external dllimport global %struct._objc_cache @@ -100,20 +100,20 @@ @implementation N : I @end -// CHECK-IR-DAG: @"OBJC_EHTYPE_$_N" = dso_local dllexport global %struct._objc_typeinfo +// CHECK-ITANIUM-DAG: @"OBJC_EHTYPE_$_N" = dso_local dllexport global %struct._objc_typeinfo __declspec(dllimport) __attribute__((__objc_exception__)) @interface O : I @end -// CHECK-IR-DAG: @"OBJC_EHTYPE_$_O" = external dllimport global %struct._objc_typeinfo +// CHECK-ITANIUM-DAG: @"OBJC_EHTYPE_$_O" = external dllimport global %struct._objc_typeinfo __attribute__((__objc_exception__)) @interface P : I @end -// CHECK-IR-DAG: @"OBJC_EHTYPE_$_P" = external dso_local global %struct._objc_typeinfo +// CHECK-ITANIUM-DAG: @"OBJC_EHTYPE_$_P" = external dso_local global %struct._objc_typeinfo @interface Q : M @end @@ -153,9 +153,9 @@ return 0; } -// CHECK-IR-DAG: @OBJC_EHTYPE_id = external dllimport global %struct._objc_typeinfo -// CHECK-IR-DAG: @"OBJC_EHTYPE_$_I" = weak global %struct._objc_typeinfo -// CHECK-IR-DAG: @"OBJC_EHTYPE_$_K" = weak global %struct._objc_typeinfo -// CHECK-IR-DAG: @"OBJC_EHTYPE_$_L" = weak global %struct._objc_typeinfo -// CHECK-IR-DAG: @"OBJC_EHTYPE_$_M" = weak global %struct._objc_typeinfo +// CHECK-ITANIUM-DAG: @OBJC_EHTYPE_id = external dllimport global %struct._objc_typeinfo +// CHECK-ITANIUM-DAG: @"OBJC_EHTYPE_$_I" = weak global %struct._objc_typeinfo +// CHECK-ITANIUM-DAG: @"OBJC_EHTYPE_$_K" = weak global %struct._objc_typeinfo +// CHECK-ITANIUM-DAG: @"OBJC_EHTYPE_$_L" = weak global %struct._objc_typeinfo +// CHECK-ITANIUM-DAG: @"OBJC_EHTYPE_$_M" = weak global %struct._objc_typeinfo Index: test/CodeGenObjC/exceptions-msvc.m =================================================================== --- /dev/null +++ test/CodeGenObjC/exceptions-msvc.m @@ -0,0 +1,81 @@ +// RUN: %clang_cc1 -triple i686--windows-msvc -fobjc-runtime=ios-6.0 -fdeclspec -fexceptions -fobjc-exceptions -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,X86 %s +// RUN: %clang_cc1 -triple i686--windows-msvc -fobjc-runtime=ios-6.0 -fobjc-arc -fdeclspec -fexceptions -fobjc-exceptions -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,X86 %s +// RUN: %clang_cc1 -triple x86_64--windows-msvc -fobjc-runtime=ios-6.0 -fdeclspec -fexceptions -fobjc-exceptions -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,X64 %s +// RUN: %clang_cc1 -triple x86_64--windows-msvc -fobjc-runtime=ios-6.0 -fobjc-arc -fdeclspec -fexceptions -fobjc-exceptions -emit-llvm -o - %s | FileCheck -check-prefixes=CHECK,X64 %s + +#if __has_feature(objc_arc) +#define WEAK __weak +#else +#define WEAK +#endif + +// CHECK-DAG: $OBJC_EHTYPE_id = comdat any +// X86-DAG: @OBJC_EHTYPE_id = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [18 x i8] c".PAUobjc_object@@\00" }, comdat +// X64-DAG: @OBJC_EHTYPE_id = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [19 x i8] c".PEAUobjc_object@@\00" }, comdat + +@class I; + +// CHECK-DAG: $"OBJC_EHTYPE_$_I" = comdat any +// X86-DAG: @"OBJC_EHTYPE_$_I" = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".PAUI@@\00" }, comdat +// X64-DAG: @"OBJC_EHTYPE_$_I" = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".PEAUI@@\00" }, comdat + +@class J; + +// CHECK-DAG: $"OBJC_EHTYPE_$_J" = comdat any +// X86-DAG: @"OBJC_EHTYPE_$_J" = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".PAUJ@@\00" }, comdat +// X64-DAG: @"OBJC_EHTYPE_$_J" = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".PEAUJ@@\00" }, comdat + +// The EHType shouldn't be exported +__declspec(dllexport) +__attribute__((objc_root_class)) +@interface K +@end + +@implementation K +@end + +// CHECK-DAG: $"OBJC_EHTYPE_$_K" = comdat any +// X86-DAG: @"OBJC_EHTYPE_$_K" = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".PAUK@@\00" }, comdat +// X64-DAG: @"OBJC_EHTYPE_$_K" = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".PEAUK@@\00" }, comdat + +__attribute__((objc_root_class)) +__attribute__((objc_runtime_name("NotL"))) +@interface L +@end + +// CHECK-DAG: $"OBJC_EHTYPE_$_NotL" = comdat any +// X86-DAG: @"OBJC_EHTYPE_$_NotL" = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".PAUL@@\00" }, comdat +// X64-DAG: @"OBJC_EHTYPE_$_NotL" = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".PEAUL@@\00" }, comdat + +@class M; + +// CHECK-DAG: $"OBJC_EHTYPE_$_M" = comdat any +// X86-DAG: @"OBJC_EHTYPE_$_M" = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".PAUM@@\00" }, comdat +// X64-DAG: @"OBJC_EHTYPE_$_M" = linkonce_odr global {{%[^ ]+}} { i8** @"??_7type_info@@6B@", i8* null, [9 x i8] c".PEAUM@@\00" }, comdat + +// The EHType shouldn't be generated for this definition, since it's not referenced. +__attribute__((objc_root_class)) +__attribute__((objc_exception)) +@interface N +@end + +@implementation N +@end + +// CHECK-NOT: @"OBJC_EHTYPE_$_N" + +@protocol P; + +void f(void); + +void g() { + @try { + f(); + } @catch (I *) { + } @catch (J

*) { + } @catch (K *) { + } @catch (L *) { + } @catch (M *WEAK) { + } @catch (id) { + } +}