r275737 - CodeGen: honour dllstorage on ObjC types

Saleem Abdulrasool via cfe-commits cfe-commits at lists.llvm.org
Sun Jul 17 15:27:44 PDT 2016


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)
+ at interface I
++ (instancetype) new;
+ at 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)
+ at interface J : I
+ at 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
+
+ at implementation J {
+  id _ivar;
+}
+ at end
+
+// CHECK-IR-DAG: @"OBJC_IVAR_$_J._ivar" = global i32
+
+ at interface K : J
+ at 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
+
+ at implementation K {
+  id _ivar;
+}
+ at end
+
+// CHECK-IR-DAG: @"OBJC_IVAR_$_K._ivar" = global i32
+
+__declspec(dllexport)
+ at interface L : K
+ at 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
+
+ at implementation L {
+  id _none;
+
+  @public
+  id _public;
+
+  @protected
+  id _protected;
+
+  @package
+  id _package;
+
+  @private
+  id _private;
+}
+ at 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)
+ at interface M : I {
+  @public
+  id _ivar;
+}
+ at 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__))
+ at interface N : I
+ at end
+
+// CHECK-FW-DAG: @_OBJC_METACLASS_N = dllexport global
+// CHECK-FW-DAG: @_OBJC_CLASS_N = dllexport global
+
+ at implementation N : I
+ at end
+
+// CHECK-IR-DAG: @"OBJC_EHTYPE_$_N" = dllexport global %struct._objc_typeinfo
+
+__declspec(dllimport)
+__attribute__((__objc_exception__))
+ at interface O : I
+ at end
+
+// CHECK-IR-DAG: @"OBJC_EHTYPE_$_O" = external dllimport global %struct._objc_typeinfo
+
+__attribute__((__objc_exception__))
+ at interface P : I
+ at 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
+




More information about the cfe-commits mailing list