Author: compnerd Date: Sun Jul 17 17:27:44 2016 New Revision: 275737 URL: http://llvm.org/viewvc/llvm-project?rev=275737&view=rev Log: CodeGen: honour dllstorage on ObjC types
Add support for ObjC types to respect the DLLImport/DLLExport storage annotations. This only effects COFF output. This would allow usage with clang/C2, but not with clang/LLVM due to hard coded section names. Added: cfe/trunk/test/CodeGenObjC/dllstorage.m Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp cfe/trunk/lib/CodeGen/CGObjCMac.cpp Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=275737&r1=275736&r2=275737&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original) +++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Sun Jul 17 17:27:44 2016 @@ -1073,11 +1073,44 @@ llvm::Value *CGObjCGNU::GetClassNamed(Co // techniques can modify the name -> class mapping. llvm::Value *CGObjCGNU::GetClass(CodeGenFunction &CGF, const ObjCInterfaceDecl *OID) { - return GetClassNamed(CGF, OID->getNameAsString(), OID->isWeakImported()); + auto *Value = + GetClassNamed(CGF, OID->getNameAsString(), OID->isWeakImported()); + if (CGM.getTriple().isOSBinFormatCOFF()) { + if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value)) { + auto DLLStorage = llvm::GlobalValue::DefaultStorageClass; + if (OID->hasAttr<DLLExportAttr>()) + DLLStorage = llvm::GlobalValue::DLLExportStorageClass; + else if (OID->hasAttr<DLLImportAttr>()) + DLLStorage = llvm::GlobalValue::DLLImportStorageClass; + ClassSymbol->setDLLStorageClass(DLLStorage); + } + } + return Value; } llvm::Value *CGObjCGNU::EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) { - return GetClassNamed(CGF, "NSAutoreleasePool", false); + auto *Value = GetClassNamed(CGF, "NSAutoreleasePool", false); + if (CGM.getTriple().isOSBinFormatCOFF()) { + if (auto *ClassSymbol = dyn_cast<llvm::GlobalVariable>(Value)) { + IdentifierInfo &II = CGF.CGM.getContext().Idents.get("NSAutoreleasePool"); + TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl(); + DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); + + const VarDecl *VD = nullptr; + for (const auto &Result : DC->lookup(&II)) + if ((VD = dyn_cast<VarDecl>(Result))) + break; + + auto DLLStorage = llvm::GlobalValue::DefaultStorageClass; + if (!VD || VD->hasAttr<DLLImportAttr>()) + DLLStorage = llvm::GlobalValue::DLLImportStorageClass; + else if (VD->hasAttr<DLLExportAttr>()) + DLLStorage = llvm::GlobalValue::DLLExportStorageClass; + + ClassSymbol->setDLLStorageClass(DLLStorage); + } + } + return Value; } llvm::Value *CGObjCGNU::GetSelector(CodeGenFunction &CGF, Selector Sel, @@ -2354,6 +2387,14 @@ void CGObjCGNU::GenerateClass(const ObjC NULLPtr, NULLPtr, 0x12L, ClassName.c_str(), nullptr, Zeros[0], GenerateIvarList(empty, empty, empty), ClassMethodList, NULLPtr, NULLPtr, NULLPtr, ZeroPtr, ZeroPtr, true); + if (CGM.getTriple().isOSBinFormatCOFF()) { + auto Storage = llvm::GlobalValue::DefaultStorageClass; + if (OID->getClassInterface()->hasAttr<DLLImportAttr>()) + Storage = llvm::GlobalValue::DLLImportStorageClass; + else if (OID->getClassInterface()->hasAttr<DLLExportAttr>()) + Storage = llvm::GlobalValue::DLLExportStorageClass; + cast<llvm::GlobalValue>(MetaClassStruct)->setDLLStorageClass(Storage); + } // Generate the class structure llvm::Constant *ClassStruct = GenerateClassStructure( @@ -2361,6 +2402,14 @@ void CGObjCGNU::GenerateClass(const ObjC llvm::ConstantInt::get(LongTy, instanceSize), IvarList, MethodList, GenerateProtocolList(Protocols), IvarOffsetArray, Properties, StrongIvarBitmap, WeakIvarBitmap); + if (CGM.getTriple().isOSBinFormatCOFF()) { + auto Storage = llvm::GlobalValue::DefaultStorageClass; + if (OID->getClassInterface()->hasAttr<DLLImportAttr>()) + Storage = llvm::GlobalValue::DLLImportStorageClass; + else if (OID->getClassInterface()->hasAttr<DLLExportAttr>()) + Storage = llvm::GlobalValue::DLLExportStorageClass; + cast<llvm::GlobalValue>(ClassStruct)->setDLLStorageClass(Storage); + } // Resolve the class aliases, if they exist. if (ClassPtrAlias) { @@ -2854,7 +2903,12 @@ llvm::Value *CGObjCGNU::EmitIvarOffset(C const ObjCIvarDecl *Ivar) { if (CGM.getLangOpts().ObjCRuntime.isNonFragile()) { Interface = FindIvarInterface(CGM.getContext(), Interface, Ivar); - if (RuntimeVersion < 10) + + // The MSVC linker cannot have a single global defined as LinkOnceAnyLinkage + // and ExternalLinkage, so create a reference to the ivar global and rely on + // the definition being created as part of GenerateClass. + if (RuntimeVersion < 10 || + CGF.CGM.getTarget().getTriple().isKnownWindowsMSVCEnvironment()) return CGF.Builder.CreateZExtOrBitCast( CGF.Builder.CreateDefaultAlignedLoad(CGF.Builder.CreateAlignedLoad( ObjCIvarOffsetVariable(Interface, Ivar), Modified: cfe/trunk/lib/CodeGen/CGObjCMac.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCMac.cpp?rev=275737&r1=275736&r2=275737&view=diff ============================================================================== --- cfe/trunk/lib/CodeGen/CGObjCMac.cpp (original) +++ cfe/trunk/lib/CodeGen/CGObjCMac.cpp Sun Jul 17 17:27:44 2016 @@ -5951,8 +5951,9 @@ llvm::GlobalVariable *CGObjCNonFragileAB GV->setSection("__DATA, __objc_data"); GV->setAlignment( CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ClassnfABITy)); - if (HiddenVisibility) - GV->setVisibility(llvm::GlobalValue::HiddenVisibility); + if (!CGM.getTriple().isOSBinFormatCOFF()) + if (HiddenVisibility) + GV->setVisibility(llvm::GlobalValue::HiddenVisibility); return GV; } @@ -5977,18 +5978,42 @@ void CGObjCNonFragileABIMac::GetClassSiz InstanceStart = RL.getFieldOffset(0) / CGM.getContext().getCharWidth(); } +static llvm::GlobalValue::DLLStorageClassTypes getStorage(CodeGenModule &CGM, + StringRef Name) { + IdentifierInfo &II = CGM.getContext().Idents.get(Name); + TranslationUnitDecl *TUDecl = CGM.getContext().getTranslationUnitDecl(); + DeclContext *DC = TranslationUnitDecl::castToDeclContext(TUDecl); + + const VarDecl *VD = nullptr; + for (const auto &Result : DC->lookup(&II)) + if ((VD = dyn_cast<VarDecl>(Result))) + break; + + if (!VD) + return llvm::GlobalValue::DLLImportStorageClass; + if (VD->hasAttr<DLLExportAttr>()) + return llvm::GlobalValue::DLLExportStorageClass; + if (VD->hasAttr<DLLImportAttr>()) + return llvm::GlobalValue::DLLImportStorageClass; + return llvm::GlobalValue::DefaultStorageClass; +} + void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { if (!ObjCEmptyCacheVar) { - ObjCEmptyCacheVar = new llvm::GlobalVariable( - CGM.getModule(), ObjCTypes.CacheTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_cache"); + ObjCEmptyCacheVar = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CacheTy, false, + llvm::GlobalValue::ExternalLinkage, nullptr, + "_objc_empty_cache"); + if (CGM.getTriple().isOSBinFormatCOFF()) + ObjCEmptyCacheVar->setDLLStorageClass(getStorage(CGM, "_objc_empty_cache")); // Only OS X with deployment version <10.9 use the empty vtable symbol const llvm::Triple &Triple = CGM.getTarget().getTriple(); if (Triple.isMacOSX() && Triple.isMacOSXVersionLT(10, 9)) - ObjCEmptyVtableVar = new llvm::GlobalVariable( - CGM.getModule(), ObjCTypes.ImpnfABITy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, "_objc_empty_vtable"); + ObjCEmptyVtableVar = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ImpnfABITy, false, + llvm::GlobalValue::ExternalLinkage, nullptr, + "_objc_empty_vtable"); } // FIXME: Is this correct (that meta class size is never computed)? @@ -6004,7 +6029,9 @@ void CGObjCNonFragileABIMac::GenerateCla assert(CI && "CGObjCNonFragileABIMac::GenerateClass - class is 0"); // Build the flags for the metaclass. - bool classIsHidden = CI->getVisibility() == HiddenVisibility; + bool classIsHidden = (CGM.getTriple().isOSBinFormatCOFF()) + ? !CI->hasAttr<DLLExportAttr>() + : CI->getVisibility() == HiddenVisibility; if (classIsHidden) flags |= NonFragileABI_Class_Hidden; @@ -6013,7 +6040,7 @@ void CGObjCNonFragileABIMac::GenerateCla if (ID->hasNonZeroConstructors() || ID->hasDestructors()) { flags |= NonFragileABI_Class_HasCXXStructors; if (!ID->hasNonZeroConstructors()) - flags |= NonFragileABI_Class_HasCXXDestructorOnly; + flags |= NonFragileABI_Class_HasCXXDestructorOnly; } if (!CI->getSuperClass()) { @@ -6022,9 +6049,15 @@ void CGObjCNonFragileABIMac::GenerateCla SuperClassGV = GetClassGlobal((getClassSymbolPrefix() + ClassName).str(), CI->isWeakImported()); + if (CGM.getTriple().isOSBinFormatCOFF()) + if (CI->hasAttr<DLLImportAttr>()) + SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); IsAGV = GetClassGlobal((getMetaclassSymbolPrefix() + ClassName).str(), CI->isWeakImported()); + if (CGM.getTriple().isOSBinFormatCOFF()) + if (CI->hasAttr<DLLImportAttr>()) + IsAGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); } else { // Has a root. Current class is not a root. const ObjCInterfaceDecl *Root = ID->getClassInterface(); @@ -6037,11 +6070,17 @@ void CGObjCNonFragileABIMac::GenerateCla IsAGV = GetClassGlobal((getMetaclassSymbolPrefix() + RootClassName).str(), Root->isWeakImported()); + if (CGM.getTriple().isOSBinFormatCOFF()) + if (Root->hasAttr<DLLImportAttr>()) + IsAGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); // work on super class metadata symbol. SuperClassGV = GetClassGlobal((getMetaclassSymbolPrefix() + SuperClassName).str(), Super->isWeakImported()); + if (CGM.getTriple().isOSBinFormatCOFF()) + if (Super->hasAttr<DLLImportAttr>()) + SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); } llvm::GlobalVariable *CLASS_RO_GV = @@ -6051,6 +6090,9 @@ void CGObjCNonFragileABIMac::GenerateCla BuildClassMetaData((getMetaclassSymbolPrefix() + ClassName).str(), IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden, CI->isWeakImported()); + if (CGM.getTriple().isOSBinFormatCOFF()) + if (CI->hasAttr<DLLExportAttr>()) + MetaTClass->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); DefinedMetaClasses.push_back(MetaTClass); // Metadata for the class @@ -6085,6 +6127,9 @@ void CGObjCNonFragileABIMac::GenerateCla SuperClassGV = GetClassGlobal((getClassSymbolPrefix() + SuperClassName).str(), Super->isWeakImported()); + if (CGM.getTriple().isOSBinFormatCOFF()) + if (Super->hasAttr<DLLImportAttr>()) + SuperClassGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); } GetClassSizeInfo(ID, InstanceStart, InstanceSize); @@ -6095,6 +6140,9 @@ void CGObjCNonFragileABIMac::GenerateCla BuildClassMetaData((getClassSymbolPrefix() + ClassName).str(), MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden, CI->isWeakImported()); + if (CGM.getTriple().isOSBinFormatCOFF()) + if (CI->hasAttr<DLLExportAttr>()) + ClassMD->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); DefinedClasses.push_back(ClassMD); ImplementedClasses.push_back(CI); @@ -6312,18 +6360,28 @@ CGObjCNonFragileABIMac::EmitMethodList(T llvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, const ObjCIvarDecl *Ivar) { - const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); llvm::SmallString<64> Name("OBJC_IVAR_$_"); Name += Container->getObjCRuntimeNameAsString(); Name += "."; Name += Ivar->getName(); - llvm::GlobalVariable *IvarOffsetGV = - CGM.getModule().getGlobalVariable(Name); - if (!IvarOffsetGV) - IvarOffsetGV = new llvm::GlobalVariable( - CGM.getModule(), ObjCTypes.IvarOffsetVarTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, Name.str()); + llvm::GlobalVariable *IvarOffsetGV = CGM.getModule().getGlobalVariable(Name); + if (!IvarOffsetGV) { + IvarOffsetGV = + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.IvarOffsetVarTy, + false, llvm::GlobalValue::ExternalLinkage, + nullptr, Name.str()); + if (CGM.getTriple().isOSBinFormatCOFF()) { + bool IsPrivateOrPackage = + Ivar->getAccessControl() == ObjCIvarDecl::Private || + Ivar->getAccessControl() == ObjCIvarDecl::Package; + + if (ID->hasAttr<DLLExportAttr>() && !IsPrivateOrPackage) + IvarOffsetGV->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); + else if (ID->hasAttr<DLLImportAttr>()) + IvarOffsetGV->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); + } + } return IvarOffsetGV; } @@ -6337,14 +6395,17 @@ CGObjCNonFragileABIMac::EmitIvarOffsetVa IvarOffsetGV->setAlignment( CGM.getDataLayout().getABITypeAlignment(ObjCTypes.IvarOffsetVarTy)); - // FIXME: This matches gcc, but shouldn't the visibility be set on the use as - // well (i.e., in ObjCIvarOffsetVariable). - if (Ivar->getAccessControl() == ObjCIvarDecl::Private || - Ivar->getAccessControl() == ObjCIvarDecl::Package || - ID->getVisibility() == HiddenVisibility) - IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility); - else - IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); + if (!CGM.getTriple().isOSBinFormatCOFF()) { + // FIXME: This matches gcc, but shouldn't the visibility be set on the use + // as well (i.e., in ObjCIvarOffsetVariable). + if (Ivar->getAccessControl() == ObjCIvarDecl::Private || + Ivar->getAccessControl() == ObjCIvarDecl::Package || + ID->getVisibility() == HiddenVisibility) + IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility); + else + IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility); + } + IvarOffsetGV->setSection("__DATA, __objc_ivar"); return IvarOffsetGV; } @@ -7179,11 +7240,14 @@ CGObjCNonFragileABIMac::GetEHType(QualTy // There's a particular fixed type info for 'id'. if (T->isObjCIdType() || T->isObjCQualifiedIdType()) { auto *IDEHType = CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id"); - if (!IDEHType) + if (!IDEHType) { IDEHType = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, llvm::GlobalValue::ExternalLinkage, nullptr, "OBJC_EHTYPE_id"); + if (CGM.getTriple().isOSBinFormatCOFF()) + IDEHType->setDLLStorageClass(getStorage(CGM, "OBJC_EHTYPE_id")); + } return IDEHType; } @@ -7238,11 +7302,19 @@ CGObjCNonFragileABIMac::GetInterfaceEHTy // If this type (or a super class) has the __objc_exception__ // attribute, emit an external reference. - if (hasObjCExceptionAttribute(CGM.getContext(), ID)) - return Entry = - new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, - llvm::GlobalValue::ExternalLinkage, nullptr, - "OBJC_EHTYPE_$_" + ClassName); + if (hasObjCExceptionAttribute(CGM.getContext(), ID)) { + std::string EHTypeName = ("OBJC_EHTYPE_$_" + ClassName).str(); + Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, + false, llvm::GlobalValue::ExternalLinkage, + nullptr, EHTypeName); + if (CGM.getTriple().isOSBinFormatCOFF()) { + if (ID->hasAttr<DLLExportAttr>()) + Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); + else if (ID->hasAttr<DLLImportAttr>()) + Entry->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass); + } + return Entry; + } } // Otherwise we need to either make a new entry or fill in the initializer. @@ -7250,11 +7322,14 @@ CGObjCNonFragileABIMac::GetInterfaceEHTy std::string VTableName = "objc_ehtype_vtable"; auto *VTableGV = CGM.getModule().getGlobalVariable(VTableName); - if (!VTableGV) + if (!VTableGV) { VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy, false, llvm::GlobalValue::ExternalLinkage, nullptr, VTableName); + if (CGM.getTriple().isOSBinFormatCOFF()) + VTableGV->setDLLStorageClass(getStorage(CGM, VTableName)); + } llvm::Value *VTableIdx = llvm::ConstantInt::get(CGM.Int32Ty, 2); llvm::Constant *Values[] = { @@ -7274,11 +7349,16 @@ CGObjCNonFragileABIMac::GetInterfaceEHTy Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, L, Init, ("OBJC_EHTYPE_$_" + ClassName).str()); + if (CGM.getTriple().isOSBinFormatCOFF()) + if (hasObjCExceptionAttribute(CGM.getContext(), ID)) + if (ID->hasAttr<DLLExportAttr>()) + Entry->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass); } assert(Entry->getLinkage() == L); - if (ID->getVisibility() == HiddenVisibility) - Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); + if (!CGM.getTriple().isOSBinFormatCOFF()) + if (ID->getVisibility() == HiddenVisibility) + Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); const auto &DL = CGM.getDataLayout(); Entry->setAlignment(DL.getABITypeAlignment(ObjCTypes.EHTypeTy)); Added: cfe/trunk/test/CodeGenObjC/dllstorage.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjC/dllstorage.m?rev=275737&view=auto ============================================================================== --- cfe/trunk/test/CodeGenObjC/dllstorage.m (added) +++ cfe/trunk/test/CodeGenObjC/dllstorage.m Sun Jul 17 17:27:44 2016 @@ -0,0 +1,151 @@ +// 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=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 + +__declspec(dllimport) +@interface I ++ (instancetype) new; +@end + +// CHECK-IR-DAG: @"OBJC_METACLASS_$_I" = external dllimport global %struct._class_t +// CHECK-IR-DAG: @"OBJC_CLASS_$_I" = external dllimport global %struct._class_t + +__declspec(dllexport) +@interface J : I +@end + +// CHECK-IR-DAG: @"OBJC_METACLASS_$_J" = dllexport global %struct._class_t +// CHECK-IR-DAG: @"OBJC_CLASS_$_J" = dllexport global %struct._class_t + +// CHECK-FW-DAG: @_OBJC_METACLASS_J = dllexport global +// CHECK-FW-DAG: @_OBJC_CLASS_J = dllexport global + +@implementation J { + id _ivar; +} +@end + +// CHECK-IR-DAG: @"OBJC_IVAR_$_J._ivar" = global i32 + +@interface K : J +@end + +// CHECK-IR-DAG: @"OBJC_METACLASS_$_K" = global %struct._class_t +// CHECK-IR-DAG: @"OBJC_CLASS_$_K" = global %struct._class_t + +// CHECK-FW-DAG: @_OBJC_METACLASS_K = global +// CHECK-FW-DAG: @_OBJC_CLASS_K = global + +@implementation K { + id _ivar; +} +@end + +// CHECK-IR-DAG: @"OBJC_IVAR_$_K._ivar" = global i32 + +__declspec(dllexport) +@interface L : K +@end + +// CHECK-IR-DAG: @"OBJC_METACLASS_$_L" = dllexport global %struct._class_t +// CHECK-IR-DAG: @"OBJC_CLASS_$_L" = dllexport global %struct._class_t + +// CHECK-FW-DAG: @_OBJC_METACLASS_L = dllexport global +// CHECK-FW-DAG: @_OBJC_CLASS_L = dllexport global + +@implementation L { + id _none; + + @public + id _public; + + @protected + id _protected; + + @package + id _package; + + @private + id _private; +} +@end + +// CHECK-IR-DAG: @"OBJC_IVAR_$_L._none" = global i32 +// CHECK-IR-DAG: @"OBJC_IVAR_$_L._public" = dllexport global i32 +// CHECK-IR-DAG: @"OBJC_IVAR_$_L._protected" = dllexport global i32 +// CHECK-IR-DAG: @"OBJC_IVAR_$_L._package" = global i32 +// CHECK-IR-DAG: @"OBJC_IVAR_$_L._private" = global i32 + +__declspec(dllimport) +@interface M : I { + @public + id _ivar; +} +@end + +// CHEKC-FW-DAG: @_OBJC_CLASS_M = external dllimport global i32 + +// CHECK-IR-DAG: @"OBJC_IVAR_$_M._ivar" = external dllimport global i32 + +__declspec(dllexport) +__attribute__((__objc_exception__)) +@interface N : I +@end + +// CHECK-FW-DAG: @_OBJC_METACLASS_N = dllexport global +// CHECK-FW-DAG: @_OBJC_CLASS_N = dllexport global + +@implementation N : I +@end + +// CHECK-IR-DAG: @"OBJC_EHTYPE_$_N" = 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 + +__attribute__((__objc_exception__)) +@interface P : I +@end + +// CHECK-IR-DAG: @"OBJC_EHTYPE_$_P" = external global %struct._objc_typeinfo + +int g() { + @autoreleasepool { + M *mi = [M new]; + @try { + mi->_ivar = (void *)0; + @throw(@"CFConstantString"); + } @catch (id) { + return 1; + } @catch (I *) { + return 2; + } @catch (J *) { + return 3; + } @catch (K *) { + return 4; + } @catch (L *) { + return 5; + } @catch (M *) { + return 6; + } @catch (N *) { + return 7; + } @catch (O *) { + return 8; + } @catch (P *) { + return 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 + _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits