From: Daniel Dunbar Date: Wed, 8 Apr 2009 04:21:03 +0000 (+0000) Subject: Implementation definition of interfaces with __objc_exception attribute. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8158a2f78c47bf332dbd8b0b680de8a9b8d0511e;p=clang Implementation definition of interfaces with __objc_exception attribute. - Complete Support __objc_exception__ attribute git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@68591 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index f7829264e7..116d8b010f 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -712,7 +712,7 @@ private: /// FinishNonFragileABIModule - Write out global data structures at the end of /// processing a translation unit. void FinishNonFragileABIModule(); - + llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags, unsigned InstanceStart, unsigned InstanceSize, @@ -795,9 +795,10 @@ private: /// for the given selector. llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel); - /// GetInterfaceEHType - Get the ehtype for the given Objective-C + /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C /// interface. The return value has type EHTypePtrTy. - llvm::Value *GetInterfaceEHType(const ObjCInterfaceType *IT); + llvm::Value *GetInterfaceEHType(const ObjCInterfaceDecl *ID, + bool ForDefinition); const char *getMetaclassSymbolPrefix() const { return "OBJC_METACLASS_$_"; @@ -891,6 +892,16 @@ static llvm::Constant *getConstantGEP(llvm::Constant *C, return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2); } +/// hasObjCExceptionAttribute - Return true if this class or any super +/// class has the __objc_exception__ attribute. +static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *OID) { + if (OID->getAttr()) + return true; + if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) + return hasObjCExceptionAttribute(Super); + return false; +} + /* *** CGObjCMac Public Interface *** */ CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm), @@ -4238,6 +4249,10 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { flags = CLS; if (classIsHidden) flags |= OBJC2_CLS_HIDDEN; + + if (hasObjCExceptionAttribute(ID->getClassInterface())) + flags |= CLS_EXCEPTION; + if (!ID->getClassInterface()->getSuperClass()) { flags |= CLS_ROOT; SuperClassGV = 0; @@ -4287,6 +4302,10 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { classIsHidden); UsedGlobals.push_back(ClassMD); DefinedClasses.push_back(ClassMD); + + // Force the definition of the EHType if necessary. + if (flags & CLS_EXCEPTION) + GetInterfaceEHType(ID->getClassInterface(), true); } /// GenerateProtocolRef - This routine is called to generate code for @@ -5356,7 +5375,7 @@ CGObjCNonFragileABIMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const ObjCInterfaceType *IT = PT->getPointeeType()->getAsObjCInterfaceType(); assert(IT && "Invalid @catch type."); - llvm::Value *EHType = GetInterfaceEHType(IT); + llvm::Value *EHType = GetInterfaceEHType(IT->getDecl(), false); SelectorArgs.push_back(EHType); } } @@ -5544,32 +5563,32 @@ void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF, CGF.Builder.ClearInsertionPoint(); } -static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *OID) { - if (OID->getAttr()) - return true; - if (const ObjCInterfaceDecl *Super = OID->getSuperClass()) - return hasObjCExceptionAttribute(Super); - return false; -} - llvm::Value * -CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceType *IT) { - const ObjCInterfaceDecl *ID = IT->getDecl(); +CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, + bool ForDefinition) { llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()]; - if (Entry) - return Entry; - - // If this type (or a super class) has the __objc_exception__ - // attribute, emit an external reference. - if (hasObjCExceptionAttribute(IT->getDecl())) - return Entry = - new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false, - llvm::GlobalValue::ExternalLinkage, - 0, - (std::string("OBJC_EHTYPE_$_") + - ID->getIdentifier()->getName()), - &CGM.getModule()); + // If we don't need a definition, return the entry if found or check + // if we use an external reference. + if (!ForDefinition) { + if (Entry) + return Entry; + + // If this type (or a super class) has the __objc_exception__ + // attribute, emit an external reference. + if (hasObjCExceptionAttribute(ID)) + return Entry = + new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false, + llvm::GlobalValue::ExternalLinkage, + 0, + (std::string("OBJC_EHTYPE_$_") + + ID->getIdentifier()->getName()), + &CGM.getModule()); + } + + // Otherwise we need to either make a new entry or fill in the + // initializer. + assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition"); std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); std::string VTableName = "objc_ehtype_vtable"; llvm::GlobalVariable *VTableGV = @@ -5587,17 +5606,28 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceType *IT) { Values[2] = GetClassGlobal(ClassName, false); llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values); - Entry = - new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false, - llvm::GlobalValue::WeakAnyLinkage, - Init, - (std::string("OBJC_EHTYPE_$_") + - ID->getIdentifier()->getName()), - &CGM.getModule()); + if (Entry) { + Entry->setInitializer(Init); + } else { + Entry = new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false, + llvm::GlobalValue::WeakAnyLinkage, + Init, + (std::string("OBJC_EHTYPE_$_") + + ID->getIdentifier()->getName()), + &CGM.getModule()); + } + if (CGM.getLangOptions().getVisibilityMode() == LangOptions::HiddenVisibility) Entry->setVisibility(llvm::GlobalValue::HiddenVisibility); - Entry->setSection("__DATA,__datacoal_nt,coalesced"); + Entry->setAlignment(8); + + if (ForDefinition) { + Entry->setSection("__DATA,__objc_const"); + Entry->setLinkage(llvm::GlobalValue::ExternalLinkage); + } else { + Entry->setSection("__DATA,__datacoal_nt,coalesced"); + } return Entry; } diff --git a/test/CodeGenObjC/metadata_symbols.m b/test/CodeGenObjC/metadata_symbols.m index df36a50f52..0edd9e899f 100644 --- a/test/CodeGenObjC/metadata_symbols.m +++ b/test/CodeGenObjC/metadata_symbols.m @@ -2,8 +2,10 @@ // RUN: grep '@"OBJC_METACLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t && // RUN: grep '@"OBJC_CLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t && -// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak global .*section "__DATA,__datacoal_nt,coalesced"' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak global .*section "__DATA,__datacoal_nt,coalesced", align 8' %t && // RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH3" = global .*section "__DATA,__objc_const", align 8' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH3"' %t | count 3 && // RUN: grep -F 'define internal void @"\01-[A im0]"' %t && // FIXME: Should include category name. // RUN: grep -F 'define internal void @"\01-[A im1]"' %t && @@ -13,6 +15,8 @@ // RUN: grep '@"OBJC_METACLASS_$_A" = hidden global .*section "__DATA, __objc_data", align 8' %t && // RUN: grep '@"OBJC_CLASS_$_A" = hidden global .*section "__DATA, __objc_data", align 8' %t && // RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak hidden global .*section "__DATA,__datacoal_nt,coalesced"' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t && +// RUN: grep '@"OBJC_EHTYPE_$_EH3" = hidden global .*section "__DATA,__objc_const", align 8' %t && // RUN: grep -F 'define internal void @"\01-[A im0]"' %t && // FIXME: Should include category name. // RUN: grep -F 'define internal void @"\01-[A im1]"' %t && @@ -39,6 +43,10 @@ __attribute__((__objc_exception__)) @interface EH2 @end +__attribute__((__objc_exception__)) +@interface EH3 +@end + void f1(); void f0(id x) { @@ -46,5 +54,9 @@ void f0(id x) { f1(); } @catch (EH1 *x) { } @catch (EH2 *x) { + } @catch (EH3 *x) { } } + +@implementation EH3 +@end