From 451b92ab6ab6148cbdfc057379aee13ac3a3b08d Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 16 Jul 2014 16:16:04 +0000 Subject: [PATCH] Objective-C. Introducing __attribute__((objc_runtime_name("runtimename")) to be applied to class or protocols. This will direct IRGen for Objective-C metadata to use the new name in various places where class and protocol names are needed. rdar:// 17631257 llvm-svn: 213167 --- clang/include/clang/AST/DeclObjC.h | 5 + clang/include/clang/Basic/Attr.td | 8 + clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 +- clang/include/clang/Sema/AttributeList.h | 3 +- clang/lib/AST/DeclObjC.cpp | 23 ++ clang/lib/CodeGen/CGObjCMac.cpp | 256 ++++++++++++--------- clang/lib/Sema/SemaDeclAttr.cpp | 14 ++ clang/test/CodeGenObjC/exceptions-asm-attribute.m | 86 +++++++ .../test/CodeGenObjC/objc-asm-attribute-neg-test.m | 34 +++ clang/test/CodeGenObjC/objc-asm-attribute-test.m | 54 +++++ 10 files changed, 372 insertions(+), 114 deletions(-) create mode 100644 clang/test/CodeGenObjC/exceptions-asm-attribute.m create mode 100644 clang/test/CodeGenObjC/objc-asm-attribute-neg-test.m create mode 100644 clang/test/CodeGenObjC/objc-asm-attribute-test.m diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 520f523..de52526 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -955,6 +955,7 @@ public: void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List, unsigned Num, ASTContext &C); + StringRef getObjCRuntimeNameAsString() const; /// Returns the designated initializers for the interface. /// @@ -1653,6 +1654,8 @@ public: /// \brief Starts the definition of this Objective-C protocol. void startDefinition(); + StringRef getObjCRuntimeNameAsString() const; + SourceRange getSourceRange() const override LLVM_READONLY { if (isThisDeclarationADefinition()) return ObjCContainerDecl::getSourceRange(); @@ -2100,6 +2103,8 @@ public: std::string getNameAsString() const { return getName(); } + + StringRef getObjCRuntimeNameAsString() const; const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; } ObjCInterfaceDecl *getSuperClass() { return SuperClass; } diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index f34034e..964e502 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -989,6 +989,14 @@ def ObjCDesignatedInitializer : Attr { let Documentation = [Undocumented]; } +def ObjCRuntimeName : Attr { + let Spellings = [GNU<"objc_runtime_name">]; + let Subjects = SubjectList<[ObjCInterface, ObjCProtocol], ErrorDiag, + "ExpectedObjectiveCInterfaceOrProtocol">; + let Args = [StringArgument<"MetadataName", 1>]; + let Documentation = [Undocumented]; +} + def OptimizeNone : InheritableAttr { let Spellings = [GNU<"optnone">, CXX11<"clang", "optnone">]; let Subjects = SubjectList<[Function, ObjCMethod]>; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 6388ffe..4e77ec7 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2165,7 +2165,8 @@ def warn_attribute_wrong_decl_type : Warning< "struct or union|struct, union or class|types|" "Objective-C instance methods|init methods of interface or class extension declarations|" "variables, functions and classes|Objective-C protocols|" - "functions and global variables|structs or typedefs}1">, + "functions and global variables|structs or typedefs|" + "interface or protocol declarations}1">, InGroup; def err_attribute_wrong_decl_type : Error; def warn_type_attribute_wrong_type : Warning< diff --git a/clang/include/clang/Sema/AttributeList.h b/clang/include/clang/Sema/AttributeList.h index 24e4cd4..c21c19f 100644 --- a/clang/include/clang/Sema/AttributeList.h +++ b/clang/include/clang/Sema/AttributeList.h @@ -841,7 +841,8 @@ enum AttributeDeclKind { ExpectedFunctionVariableOrClass, ExpectedObjectiveCProtocol, ExpectedFunctionGlobalVarMethodOrProperty, - ExpectedStructOrTypedef + ExpectedStructOrTypedef, + ExpectedObjectiveCInterfaceOrProtocol }; } // end namespace clang diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp index 186a741..f01383a 100644 --- a/clang/lib/AST/DeclObjC.cpp +++ b/clang/lib/AST/DeclObjC.cpp @@ -1199,6 +1199,22 @@ bool ObjCInterfaceDecl::hasDesignatedInitializers() const { return data().HasDesignatedInitializers; } +StringRef +ObjCInterfaceDecl::getObjCRuntimeNameAsString() const { + if (ObjCRuntimeNameAttr *ObjCRTName = getAttr()) + return ObjCRTName->getMetadataName(); + return getName(); +} + +StringRef +ObjCImplementationDecl::getObjCRuntimeNameAsString() const { + if (ObjCInterfaceDecl *ID = + const_cast(this)->getClassInterface()) + return ID->getObjCRuntimeNameAsString(); + + return getName(); +} + ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const { if (const ObjCInterfaceDecl *Def = getDefinition()) { if (data().ExternallyCompleted) @@ -1603,6 +1619,13 @@ void ObjCProtocolDecl::collectInheritedProtocolProperties( } } +StringRef +ObjCProtocolDecl::getObjCRuntimeNameAsString() const { + if (ObjCRuntimeNameAttr *ObjCRTName = getAttr()) + return ObjCRTName->getMetadataName(); + return getName(); +} + //===----------------------------------------------------------------------===// // ObjCCategoryDecl //===----------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index de760c8..6f0979d 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -855,7 +855,7 @@ protected: llvm::SetVector DefinedSymbols; /// ClassNames - uniqued class names. - llvm::DenseMap ClassNames; + llvm::StringMap ClassNames; /// MethodVarNames - uniqued method variable names. llvm::DenseMap MethodVarNames; @@ -932,8 +932,9 @@ protected: const Decl *Container); /// GetClassName - Return a unique constant for the given selector's - /// name. The return value has type char *. - llvm::Constant *GetClassName(IdentifierInfo *Ident); + /// runtime name (which may change via use of objc_runtime_name attribute on + /// class or protocol definition. The return value has type char *. + llvm::Constant *GetClassName(StringRef RuntimeName); llvm::Function *GetMethodDefinition(const ObjCMethodDecl *MD); @@ -1312,7 +1313,7 @@ private: unsigned InstanceStart, unsigned InstanceSize, const ObjCImplementationDecl *ID); - llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName, + llvm::GlobalVariable * BuildClassMetaData(const std::string &ClassName, llvm::Constant *IsAGV, llvm::Constant *SuperClassGV, llvm::Constant *ClassRoGV, @@ -1377,7 +1378,8 @@ private: const ObjCInterfaceDecl *ID); llvm::Value *EmitClassRefFromId(CodeGenFunction &CGF, - IdentifierInfo *II, bool Weak); + IdentifierInfo *II, bool Weak, + const ObjCInterfaceDecl *ID); llvm::Value *EmitNSAutoreleasePoolClassRef(CodeGenFunction &CGF) override; @@ -2624,7 +2626,7 @@ llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) { llvm::Constant *Values[] = { EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods, MethodTypesExt), - GetClassName(PD->getIdentifier()), + GetClassName(PD->getObjCRuntimeNameAsString()), EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(), PD->protocol_begin(), PD->protocol_end()), @@ -2936,8 +2938,8 @@ void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { ClassMethods.push_back(GetMethodConstant(I)); llvm::Constant *Values[7]; - Values[0] = GetClassName(OCD->getIdentifier()); - Values[1] = GetClassName(Interface->getIdentifier()); + Values[0] = GetClassName(OCD->getName()); + Values[1] = GetClassName(Interface->getObjCRuntimeNameAsString()); LazySymbols.insert(Interface->getIdentifier()); Values[2] = EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(), @@ -3080,12 +3082,12 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) { LazySymbols.insert(Super->getIdentifier()); Values[ 1] = - llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), + llvm::ConstantExpr::getBitCast(GetClassName(Super->getObjCRuntimeNameAsString()), ObjCTypes.ClassPtrTy); } else { Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy); } - Values[ 2] = GetClassName(ID->getIdentifier()); + Values[ 2] = GetClassName(ID->getObjCRuntimeNameAsString()); // Version is always 0. Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); @@ -3138,19 +3140,19 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID, while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) Root = Super; Values[ 0] = - llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()), + llvm::ConstantExpr::getBitCast(GetClassName(Root->getObjCRuntimeNameAsString()), ObjCTypes.ClassPtrTy); // The super class for the metaclass is emitted as the name of the // super class. The runtime fixes this up to point to the // *metaclass* for the super class. if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) { Values[ 1] = - llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()), + llvm::ConstantExpr::getBitCast(GetClassName(Super->getObjCRuntimeNameAsString()), ObjCTypes.ClassPtrTy); } else { Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy); } - Values[ 2] = GetClassName(ID->getIdentifier()); + Values[ 2] = GetClassName(ID->getObjCRuntimeNameAsString()); // Version is always 0. Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0); Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags); @@ -4342,7 +4344,7 @@ void CGObjCMac::EmitModuleInfo() { llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion), llvm::ConstantInt::get(ObjCTypes.LongTy, Size), // This used to be the filename, now it is unused. - GetClassName(&CGM.getContext().Idents.get("")), + GetClassName(StringRef("")), EmitModuleSymbols() }; CreateMetadataVar("\01L_OBJC_MODULES", @@ -4406,7 +4408,7 @@ llvm::Value *CGObjCMac::EmitClassRefFromId(CodeGenFunction &CGF, if (!Entry) { llvm::Constant *Casted = - llvm::ConstantExpr::getBitCast(GetClassName(II), + llvm::ConstantExpr::getBitCast(GetClassName(II->getName()), ObjCTypes.ClassPtrTy); Entry = CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted, @@ -4447,18 +4449,17 @@ llvm::Value *CGObjCMac::EmitSelector(CodeGenFunction &CGF, Selector Sel, return CGF.Builder.CreateLoad(Entry); } -llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) { - llvm::GlobalVariable *&Entry = ClassNames[Ident]; - - if (!Entry) - Entry = CreateMetadataVar( - "\01L_OBJC_CLASS_NAME_", - llvm::ConstantDataArray::getString(VMContext, Ident->getName()), - ((ObjCABI == 2) ? "__TEXT,__objc_classname,cstring_literals" - : "__TEXT,__cstring,cstring_literals"), - 1, true); - - return getConstantGEP(VMContext, Entry, 0, 0); +llvm::Constant *CGObjCCommonMac::GetClassName(StringRef RuntimeName) { + llvm::GlobalVariable *&Entry = ClassNames[RuntimeName]; + if (!Entry) + Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_", + llvm::ConstantDataArray::getString(VMContext, + RuntimeName), + ((ObjCABI == 2) ? + "__TEXT,__objc_classname,cstring_literals" : + "__TEXT,__cstring,cstring_literals"), + 1, true); + return getConstantGEP(VMContext, Entry, 0, 0); } llvm::Function *CGObjCCommonMac::GetMethodDefinition(const ObjCMethodDecl *MD) { @@ -4962,7 +4963,7 @@ void CGObjCMac::FinishModule() { llvm::Constant *Values[5]; Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy); - Values[1] = GetClassName(I->first); + Values[1] = GetClassName(I->first->getName()); Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy); Values[3] = Values[4] = llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy); @@ -5628,7 +5629,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( unsigned InstanceStart, unsigned InstanceSize, const ObjCImplementationDecl *ID) { - std::string ClassName = ID->getNameAsString(); + std::string ClassName = ID->getObjCRuntimeNameAsString(); llvm::Constant *Values[10]; // 11 for 64bit targets! if (CGM.getLangOpts().ObjCAutoRefCount) @@ -5641,17 +5642,19 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( Values[ 3] = (flags & NonFragileABI_Class_Meta) ? GetIvarLayoutName(nullptr, ObjCTypes) : BuildIvarLayout(ID, true); - Values[ 4] = GetClassName(ID->getIdentifier()); + Values[ 4] = GetClassName(ID->getObjCRuntimeNameAsString()); // const struct _method_list_t * const baseMethods; std::vector Methods; std::string MethodListName("\01l_OBJC_$_"); if (flags & NonFragileABI_Class_Meta) { - MethodListName += "CLASS_METHODS_" + ID->getNameAsString(); + MethodListName += "CLASS_METHODS_"; + MethodListName += ID->getObjCRuntimeNameAsString(); for (const auto *I : ID->class_methods()) // Class methods should always be defined. Methods.push_back(GetMethodConstant(I)); } else { - MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString(); + MethodListName += "INSTANCE_METHODS_"; + MethodListName += ID->getObjCRuntimeNameAsString(); for (const auto *I : ID->instance_methods()) // Instance methods should always be defined. Methods.push_back(GetMethodConstant(I)); @@ -5675,7 +5678,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( const ObjCInterfaceDecl *OID = ID->getClassInterface(); assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer"); Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_" - + OID->getName(), + + OID->getObjCRuntimeNameAsString(), OID->all_referenced_protocol_begin(), OID->all_referenced_protocol_end()); @@ -5686,7 +5689,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( } else { Values[ 7] = EmitIvarList(ID); Values[ 8] = BuildIvarLayout(ID, false); - Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(), + Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getObjCRuntimeNameAsString(), ID, ID->getClassInterface(), ObjCTypes); } llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy, @@ -5717,7 +5720,7 @@ llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer( /// } /// llvm::GlobalVariable *CGObjCNonFragileABIMac::BuildClassMetaData( - std::string &ClassName, llvm::Constant *IsAGV, llvm::Constant *SuperClassGV, + const std::string &ClassName, llvm::Constant *IsAGV, llvm::Constant *SuperClassGV, llvm::Constant *ClassRoGV, bool HiddenVisibility, bool Weak) { llvm::Constant *Values[] = { IsAGV, @@ -5765,7 +5768,7 @@ void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID, } void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { - std::string ClassName = ID->getNameAsString(); + std::string ClassName = ID->getObjCRuntimeNameAsString(); if (!ObjCEmptyCacheVar) { ObjCEmptyCacheVar = new llvm::GlobalVariable( CGM.getModule(), @@ -5797,8 +5800,9 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ClassnfABITy); uint32_t InstanceSize = InstanceStart; uint32_t flags = NonFragileABI_Class_Meta; - std::string ObjCMetaClassName(getMetaclassSymbolPrefix()); - std::string ObjCClassName(getClassSymbolPrefix()); + llvm::SmallString<64> ObjCMetaClassName(getMetaclassSymbolPrefix()); + llvm::SmallString<64> ObjCClassName(getClassSymbolPrefix()); + llvm::SmallString<64> TClassName; llvm::GlobalVariable *SuperClassGV, *IsAGV; @@ -5819,31 +5823,38 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { if (!ID->getClassInterface()->getSuperClass()) { // class is root flags |= NonFragileABI_Class_Root; - SuperClassGV = GetClassGlobal(ObjCClassName + ClassName, + TClassName = ObjCClassName; + TClassName += ClassName; + SuperClassGV = GetClassGlobal(TClassName.str(), ID->getClassInterface()->isWeakImported()); - IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName, + TClassName = ObjCMetaClassName; + TClassName += ClassName; + IsAGV = GetClassGlobal(TClassName.str(), ID->getClassInterface()->isWeakImported()); } else { // Has a root. Current class is not a root. const ObjCInterfaceDecl *Root = ID->getClassInterface(); while (const ObjCInterfaceDecl *Super = Root->getSuperClass()) Root = Super; - IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString(), + TClassName = ObjCMetaClassName ; + TClassName += Root->getObjCRuntimeNameAsString(); + IsAGV = GetClassGlobal(TClassName.str(), Root->isWeakImported()); + // work on super class metadata symbol. - std::string SuperClassName = - ObjCMetaClassName + - ID->getClassInterface()->getSuperClass()->getNameAsString(); + TClassName = ObjCMetaClassName; + TClassName += ID->getClassInterface()->getSuperClass()->getObjCRuntimeNameAsString(); SuperClassGV = GetClassGlobal( - SuperClassName, - ID->getClassInterface()->getSuperClass()->isWeakImported()); + TClassName.str(), + ID->getClassInterface()->getSuperClass()->isWeakImported()); } llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags, InstanceStart, InstanceSize,ID); - std::string TClassName = ObjCMetaClassName + ClassName; + TClassName = ObjCMetaClassName; + TClassName += ClassName; llvm::GlobalVariable *MetaTClass = BuildClassMetaData( - TClassName, IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden, + TClassName.str(), IsAGV, SuperClassGV, CLASS_RO_GV, classIsHidden, ID->getClassInterface()->isWeakImported()); DefinedMetaClasses.push_back(MetaTClass); @@ -5873,11 +5884,11 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { SuperClassGV = nullptr; } else { // Has a root. Current class is not a root. - std::string RootClassName = - ID->getClassInterface()->getSuperClass()->getNameAsString(); + TClassName = ObjCClassName; + TClassName += ID->getClassInterface()->getSuperClass()->getObjCRuntimeNameAsString(); SuperClassGV = GetClassGlobal( - ObjCClassName + RootClassName, - ID->getClassInterface()->getSuperClass()->isWeakImported()); + TClassName.str(), + ID->getClassInterface()->getSuperClass()->isWeakImported()); } GetClassSizeInfo(ID, InstanceStart, InstanceSize); CLASS_RO_GV = BuildClassRoTInitializer(flags, @@ -5885,9 +5896,10 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) { InstanceSize, ID); - TClassName = ObjCClassName + ClassName; + TClassName = ObjCClassName; + TClassName += ClassName; llvm::GlobalVariable *ClassMD = - BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV, + BuildClassMetaData(TClassName.str(), MetaTClass, SuperClassGV, CLASS_RO_GV, classIsHidden, ID->getClassInterface()->isWeakImported()); DefinedClasses.push_back(ClassMD); @@ -5923,7 +5935,7 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, ObjCTypes.getExternalProtocolPtrTy()); std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_"); - ProtocolName += PD->getName(); + ProtocolName += PD->getObjCRuntimeNameAsString(); llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName); if (PTGV) @@ -5953,53 +5965,63 @@ llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CodeGenFunction &CGF, void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { const ObjCInterfaceDecl *Interface = OCD->getClassInterface(); const char *Prefix = "\01l_OBJC_$_CATEGORY_"; - std::string ExtCatName(Prefix + Interface->getNameAsString()+ - "_$_" + OCD->getNameAsString()); - std::string ExtClassName(getClassSymbolPrefix() + - Interface->getNameAsString()); + + llvm::SmallString<64> ExtCatName(Prefix); + ExtCatName += Interface->getObjCRuntimeNameAsString(); + ExtCatName += "_$_"; + ExtCatName += OCD->getNameAsString(); + + llvm::SmallString<64> ExtClassName(getClassSymbolPrefix()); + ExtClassName += Interface->getObjCRuntimeNameAsString(); llvm::Constant *Values[6]; - Values[0] = GetClassName(OCD->getIdentifier()); + Values[0] = GetClassName(OCD->getIdentifier()->getName()); // meta-class entry symbol llvm::GlobalVariable *ClassGV = - GetClassGlobal(ExtClassName, Interface->isWeakImported()); + GetClassGlobal(ExtClassName.str(), Interface->isWeakImported()); Values[1] = ClassGV; std::vector Methods; - std::string MethodListName(Prefix); - MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() + - "_$_" + OCD->getNameAsString(); + llvm::SmallString<64> MethodListName(Prefix); + + MethodListName += "INSTANCE_METHODS_"; + MethodListName += Interface->getObjCRuntimeNameAsString(); + MethodListName += "_$_"; + MethodListName += OCD->getName(); for (const auto *I : OCD->instance_methods()) // Instance methods should always be defined. Methods.push_back(GetMethodConstant(I)); - Values[2] = EmitMethodList(MethodListName, + Values[2] = EmitMethodList(MethodListName.str(), "__DATA, __objc_const", Methods); MethodListName = Prefix; - MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" + - OCD->getNameAsString(); + MethodListName += "CLASS_METHODS_"; + MethodListName += Interface->getObjCRuntimeNameAsString(); + MethodListName += "_$_"; + MethodListName += OCD->getNameAsString(); + Methods.clear(); for (const auto *I : OCD->class_methods()) // Class methods should always be defined. Methods.push_back(GetMethodConstant(I)); - Values[3] = EmitMethodList(MethodListName, + Values[3] = EmitMethodList(MethodListName.str(), "__DATA, __objc_const", Methods); const ObjCCategoryDecl *Category = Interface->FindCategoryDeclaration(OCD->getIdentifier()); if (Category) { SmallString<256> ExtName; - llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_" + llvm::raw_svector_ostream(ExtName) << Interface->getObjCRuntimeNameAsString() << "_$_" << OCD->getName(); Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_" - + Interface->getName() + "_$_" - + Category->getName(), - Category->protocol_begin(), - Category->protocol_end()); + + Interface->getObjCRuntimeNameAsString() + "_$_" + + Category->getName(), + Category->protocol_begin(), + Category->protocol_end()); Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(), OCD, Category, ObjCTypes); } else { @@ -6015,7 +6037,7 @@ void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) { false, llvm::GlobalValue::PrivateLinkage, Init, - ExtCatName); + ExtCatName.str()); assertPrivateName(GCATV); GCATV->setAlignment( CGM.getDataLayout().getABITypeAlignment(ObjCTypes.CategorynfABITy)); @@ -6089,15 +6111,18 @@ CGObjCNonFragileABIMac::EmitMethodList(Twine Name, llvm::GlobalVariable * CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID, const ObjCIvarDecl *Ivar) { + const ObjCInterfaceDecl *Container = Ivar->getContainingInterface(); - std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() + - '.' + Ivar->getNameAsString(); + 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); + CGM.getModule(), ObjCTypes.IvarOffsetVarTy, false, + llvm::GlobalValue::ExternalLinkage, nullptr, Name.str()); return IvarOffsetGV; } @@ -6192,7 +6217,7 @@ llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList( new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false, llvm::GlobalValue::PrivateLinkage, Init, - Prefix + OID->getName()); + Prefix + OID->getObjCRuntimeNameAsString()); assertPrivateName(GV); GV->setAlignment( CGM.getDataLayout().getABITypeAlignment(Init->getType())); @@ -6214,7 +6239,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef( new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false, llvm::GlobalValue::WeakAnyLinkage, nullptr, - "\01l_OBJC_PROTOCOL_$_" + PD->getName()); + "\01l_OBJC_PROTOCOL_$_" + PD->getObjCRuntimeNameAsString()); Entry->setSection("__DATA,__datacoal_nt,coalesced"); } @@ -6289,35 +6314,35 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( llvm::Constant *Values[11]; // isa is NULL Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy); - Values[1] = GetClassName(PD->getIdentifier()); - Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(), + Values[1] = GetClassName(PD->getObjCRuntimeNameAsString()); + Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getObjCRuntimeNameAsString(), PD->protocol_begin(), PD->protocol_end()); Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_" - + PD->getName(), + + PD->getObjCRuntimeNameAsString(), "__DATA, __objc_const", InstanceMethods); Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_" - + PD->getName(), + + PD->getObjCRuntimeNameAsString(), "__DATA, __objc_const", ClassMethods); Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_" - + PD->getName(), + + PD->getObjCRuntimeNameAsString(), "__DATA, __objc_const", OptInstanceMethods); Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_" - + PD->getName(), + + PD->getObjCRuntimeNameAsString(), "__DATA, __objc_const", OptClassMethods); - Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(), + Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getObjCRuntimeNameAsString(), nullptr, PD, ObjCTypes); uint32_t Size = CGM.getDataLayout().getTypeAllocSize(ObjCTypes.ProtocolnfABITy); Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size); Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy); Values[10] = EmitProtocolMethodTypes("\01l_OBJC_$_PROTOCOL_METHOD_TYPES_" - + PD->getName(), + + PD->getObjCRuntimeNameAsString(), MethodTypesExt, ObjCTypes); llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy, Values); @@ -6330,7 +6355,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false, llvm::GlobalValue::WeakAnyLinkage, Init, - "\01l_OBJC_PROTOCOL_$_" + PD->getName()); + "\01l_OBJC_PROTOCOL_$_" + PD->getObjCRuntimeNameAsString()); Entry->setAlignment( CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABITy)); Entry->setSection("__DATA,__datacoal_nt,coalesced"); @@ -6345,7 +6370,7 @@ llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol( llvm::GlobalVariable *PTGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy, false, llvm::GlobalValue::WeakAnyLinkage, Entry, - "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName()); + "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getObjCRuntimeNameAsString()); PTGV->setAlignment( CGM.getDataLayout().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy)); PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip"); @@ -6639,11 +6664,14 @@ CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name, bool Weak) { llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, IdentifierInfo *II, - bool Weak) { + bool Weak, + const ObjCInterfaceDecl *ID) { llvm::GlobalVariable *&Entry = ClassReferences[II]; if (!Entry) { - std::string ClassName(getClassSymbolPrefix() + II->getName().str()); + std::string ClassName( + getClassSymbolPrefix() + + (ID ? ID->getObjCRuntimeNameAsString() : II->getName()).str()); llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, Weak); Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, @@ -6662,13 +6690,13 @@ llvm::Value *CGObjCNonFragileABIMac::EmitClassRefFromId(CodeGenFunction &CGF, llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID) { - return EmitClassRefFromId(CGF, ID->getIdentifier(), ID->isWeakImported()); + return EmitClassRefFromId(CGF, ID->getIdentifier(), ID->isWeakImported(), ID); } llvm::Value *CGObjCNonFragileABIMac::EmitNSAutoreleasePoolClassRef( CodeGenFunction &CGF) { IdentifierInfo *II = &CGM.getContext().Idents.get("NSAutoreleasePool"); - return EmitClassRefFromId(CGF, II, false); + return EmitClassRefFromId(CGF, II, false, 0); } llvm::Value * @@ -6677,8 +6705,9 @@ CGObjCNonFragileABIMac::EmitSuperClassRef(CodeGenFunction &CGF, llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()]; if (!Entry) { - std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); - llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, + llvm::SmallString<64> ClassName(getClassSymbolPrefix()); + ClassName += ID->getObjCRuntimeNameAsString(); + llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(), ID->isWeakImported()); Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, @@ -6703,11 +6732,11 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF, bool Weak) { llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()]; if (!Entry) { - - std::string MetaClassName(getMetaclassSymbolPrefix() + - ID->getNameAsString()); + llvm::SmallString<64> MetaClassName(getMetaclassSymbolPrefix()); + MetaClassName += ID->getObjCRuntimeNameAsString(); llvm::GlobalVariable *MetaClassGV = - GetClassGlobal(MetaClassName, Weak); + GetClassGlobal(MetaClassName.str(), Weak); + Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false, llvm::GlobalValue::PrivateLinkage, MetaClassGV, @@ -6728,8 +6757,9 @@ llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CodeGenFunction &CGF, llvm::Value *CGObjCNonFragileABIMac::GetClass(CodeGenFunction &CGF, const ObjCInterfaceDecl *ID) { if (ID->isWeakImported()) { - std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString()); - llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName, true); + llvm::SmallString<64> ClassName(getClassSymbolPrefix()); + ClassName += ID->getObjCRuntimeNameAsString(); + llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName.str(), true); (void)ClassGV; assert(ClassGV->hasExternalWeakLinkage()); } @@ -7004,17 +7034,18 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, // 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_$_" + - ID->getIdentifier()->getName())); + new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, + llvm::GlobalValue::ExternalLinkage, + nullptr, + ("OBJC_EHTYPE_$_" + + ID->getObjCRuntimeNameAsString())); } // 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()); + llvm::SmallString<64> ClassName(getClassSymbolPrefix()); + ClassName += ID->getObjCRuntimeNameAsString(); std::string VTableName = "objc_ehtype_vtable"; llvm::GlobalVariable *VTableGV = CGM.getModule().getGlobalVariable(VTableName); @@ -7028,8 +7059,8 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, llvm::Constant *Values[] = { llvm::ConstantExpr::getGetElementPtr(VTableGV, VTableIdx), - GetClassName(ID->getIdentifier()), - GetClassGlobal(ClassName) + GetClassName(ID->getObjCRuntimeNameAsString()), + GetClassGlobal(ClassName.str()) }; llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values); @@ -7040,11 +7071,12 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID, if (Entry) { Entry->setInitializer(Init); } else { + llvm::SmallString<64> EHTYPEName("OBJC_EHTYPE_$_"); + EHTYPEName += ID->getObjCRuntimeNameAsString(); Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false, L, Init, - ("OBJC_EHTYPE_$_" + - ID->getIdentifier()->getName())); + EHTYPEName.str()); } assert(Entry->getLinkage() == L); diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index c87942d..29be703 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3597,6 +3597,16 @@ static void handleObjCDesignatedInitializer(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } +static void handleObjCRuntimeName(Sema &S, Decl *D, + const AttributeList &Attr) { + StringRef MetaDataName; + if (!S.checkStringLiteralArgumentAttr(Attr, 0, MetaDataName)) + return; + D->addAttr(::new (S.Context) + ObjCRuntimeNameAttr(Attr.getRange(), S.Context, + MetaDataName, 0)); +} + static void handleObjCOwnershipAttr(Sema &S, Decl *D, const AttributeList &Attr) { if (hasDeclarator(D)) return; @@ -4246,6 +4256,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleObjCDesignatedInitializer(S, D, Attr); break; + case AttributeList::AT_ObjCRuntimeName: + handleObjCRuntimeName(S, D, Attr); + break; + case AttributeList::AT_CFAuditedTransfer: handleCFAuditedTransferAttr(S, D, Attr); break; diff --git a/clang/test/CodeGenObjC/exceptions-asm-attribute.m b/clang/test/CodeGenObjC/exceptions-asm-attribute.m new file mode 100644 index 0000000..eb36990 --- /dev/null +++ b/clang/test/CodeGenObjC/exceptions-asm-attribute.m @@ -0,0 +1,86 @@ +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fexceptions -fobjc-exceptions -o %t %s +// RUN: FileCheck -check-prefix=CHECK-X86_64 < %t %s +// RUN: FileCheck -check-prefix=CHECK-EHTYPE < %t %s +// rdar://16462586 + +// We need exactly 3 of these. +// CHECK-EHTYPE: @"OBJC_EHTYPE_$_MySecretNamespace.EH3" +// CHECK-EHTYPE: @"OBJC_EHTYPE_$_MySecretNamespace.EH3" +// CHECK-EHTYPE: @"OBJC_EHTYPE_$_MySecretNamespace.EH3" +// CHECK-EHTYPE-NOT: @"OBJC_EHTYPE_$_MySecretNamespace.EH3" + +// CHECK-X86_64: @"OBJC_CLASS_$_MySecretNamespace.A" = global {{.*}}, section "__DATA, __objc_data", align 8 +// CHECK-X86_64: @"OBJC_METACLASS_$_MySecretNamespace.A" = global {{.*}}, section "__DATA, __objc_data", align 8 +// CHECK-X86_64: @"\01L_OBJC_CLASS_NAME_" = {{.*}}, section "__TEXT,__objc_classname,cstring_literals", align 1 +// CHECK-X86_64: @"OBJC_EHTYPE_$_MySecretNamespace.EH1" = weak global {{.*}}, section "__DATA,__datacoal_nt,coalesced", align 8 +// CHECK-X86_64: @"OBJC_EHTYPE_$_MySecretNamespace.EH2" = external global +// CHECK-X86_64: @"OBJC_EHTYPE_$_MySecretNamespace.EH3" = global {{.*}}, section "__DATA,__objc_const", align 8 +// CHECK-X86_64: @"\01L_OBJC_LABEL_CLASS_$" = private global {{.*}}, section "__DATA, __objc_classlist, regular, no_dead_strip", align 8 +// CHECK-X86_64: define internal void @"\01-[A im0]" +// CHECK-X86_64: define internal void @"\01-[A(Cat) im1]" + +// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-exceptions -fvisibility hidden -emit-llvm -o %t %s +// RUN: FileCheck -check-prefix=CHECK-X86_64-HIDDEN < %t %s + +// CHECK-X86_64-HIDDEN: @"OBJC_CLASS_$_MySecretNamespace.A" = hidden global {{.*}}, section "__DATA, __objc_data", align 8 +// CHECK-X86_64-HIDDEN: @"OBJC_METACLASS_$_MySecretNamespace.A" = hidden global {{.*}}, section "__DATA, __objc_data", align 8 +// CHECK-X86_64-HIDDEN: @"OBJC_EHTYPE_$_MySecretNamespace.EH1" = weak hidden global {{.*}}, section "__DATA,__datacoal_nt,coalesced" +// CHECK-X86_64-HIDDEN: @"OBJC_EHTYPE_$_MySecretNamespace.EH2" = external global +// CHECK-X86_64-HIDDEN: @"OBJC_EHTYPE_$_MySecretNamespace.EH3" = hidden global {{.*}}, section "__DATA,__objc_const", align 8 +// CHECK-X86_64-HIDDEN: define internal void @"\01-[A im0]" +// CHECK-X86_64-HIDDEN: define internal void @"\01-[A(Cat) im1]" + +// RUN: %clang_cc1 -triple armv6-apple-darwin10 -target-abi apcs-gnu -fobjc-exceptions -emit-llvm -o %t %s +// RUN: FileCheck -check-prefix=CHECK-ARMV6 < %t %s + +// CHECK-ARMV6: @"OBJC_CLASS_$_MySecretNamespace.A" = global {{.*}}, section "__DATA, __objc_data", align 4 +// CHECK-ARMV6: @"OBJC_METACLASS_$_MySecretNamespace.A" = global {{.*}}, section "__DATA, __objc_data", align 4 +// CHECK-ARMV6: @"\01L_OBJC_CLASS_NAME_" = {{.*}}, section "__TEXT,__objc_classname,cstring_literals", align 1 +// CHECK-ARMV6: @"OBJC_EHTYPE_$_MySecretNamespace.EH1" = weak global {{.*}}, section "__DATA,__datacoal_nt,coalesced", align 4 +// CHECK-ARMV6: @"OBJC_EHTYPE_$_MySecretNamespace.EH2" = external global +// CHECK-ARMV6: @"OBJC_EHTYPE_$_MySecretNamespace.EH3" = global {{.*}}, section "__DATA,__objc_const", align 4 +// CHECK-ARMV6: @"\01L_OBJC_LABEL_CLASS_$" = private global {{.*}}, section "__DATA, __objc_classlist, regular, no_dead_strip", align 4 +// CHECK-ARMV6: define internal void @"\01-[A im0]" +// CHECK-ARMV6: define internal void @"\01-[A(Cat) im1]" + +__attribute__((objc_runtime_name("MySecretNamespace.A"))) +@interface A +@end + +@implementation A +-(void) im0 { +} +@end + +@implementation A (Cat) +-(void) im1 { +} +@end + +__attribute__((objc_runtime_name("MySecretNamespace.EH1"))) +@interface EH1 +@end + +__attribute__((objc_runtime_name("MySecretNamespace.EH2"))) +__attribute__((__objc_exception__)) +@interface EH2 +@end + +__attribute__((objc_runtime_name("MySecretNamespace.EH3"))) +__attribute__((__objc_exception__)) +@interface EH3 +@end + +void f1(); + +void f0(id x) { + @try { + f1(); + } @catch (EH1 *x) { + } @catch (EH2 *x) { + } @catch (EH3 *x) { + } +} + +@implementation EH3 +@end diff --git a/clang/test/CodeGenObjC/objc-asm-attribute-neg-test.m b/clang/test/CodeGenObjC/objc-asm-attribute-neg-test.m new file mode 100644 index 0000000..e9bef4c --- /dev/null +++ b/clang/test/CodeGenObjC/objc-asm-attribute-neg-test.m @@ -0,0 +1,34 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -Wno-objc-root-class %s +// rdar://16462586 + +__attribute__((objc_runtime_name("MySecretNamespace.Protocol"))) +@protocol Protocol +@end + +__attribute__((objc_runtime_name("MySecretNamespace.Message"))) +@interface Message { +__attribute__((objc_runtime_name("MySecretNamespace.Message"))) // expected-error {{'objc_runtime_name' attribute only applies to interface or protocol declarations}} + id MyIVAR; +} +__attribute__((objc_runtime_name("MySecretNamespace.Message"))) +@property int MyProperty; // expected-error {{prefix attribute must be followed by an interface or protocol}}}} + +- (int) getMyProperty __attribute__((objc_runtime_name("MySecretNamespace.Message"))); // expected-error {{'objc_runtime_name' attribute only applies to interface or protocol declarations}} + +- (void) setMyProperty : (int) arg __attribute__((objc_runtime_name("MySecretNamespace.Message"))); // expected-error {{'objc_runtime_name' attribute only applies to interface or protocol declarations}} + +@end + +__attribute__((objc_runtime_name("MySecretNamespace.ForwardClass"))) +@class ForwardClass; // expected-error {{prefix attribute must be followed by an interface or protocol}} + +__attribute__((objc_runtime_name("MySecretNamespace.ForwardProtocol"))) +@protocol ForwardProtocol; + +__attribute__((objc_runtime_name("MySecretNamespace.Message"))) +@implementation Message // expected-error {{prefix attribute must be followed by an interface or protocol}} +__attribute__((objc_runtime_name("MySecretNamespace.Message"))) +- (id) MyMethod { + return MyIVAR; +} +@end diff --git a/clang/test/CodeGenObjC/objc-asm-attribute-test.m b/clang/test/CodeGenObjC/objc-asm-attribute-test.m new file mode 100644 index 0000000..12903b52 --- /dev/null +++ b/clang/test/CodeGenObjC/objc-asm-attribute-test.m @@ -0,0 +1,54 @@ +// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin %s -o - | FileCheck %s +// rdar://16462586 + +__attribute__((objc_runtime_name("MySecretNamespace.Protocol"))) +@protocol Protocol +- (void) MethodP; ++ (void) ClsMethodP; +@end + +__attribute__((objc_runtime_name("MySecretNamespace.Protocol2"))) +@protocol Protocol2 +- (void) MethodP2; ++ (void) ClsMethodP2; +@end + +__attribute__((objc_runtime_name("MySecretNamespace.Message"))) +@interface Message { + id MyIVAR; +} +@end + +@implementation Message +- (id) MyMethod { + return MyIVAR; +} + ++ (id) MyClsMethod { + return 0; +} + +- (void) MethodP{} +- (void) MethodP2{} + ++ (void) ClsMethodP {} ++ (void) ClsMethodP2 {} +@end + +// rdar://16877359 +__attribute__((objc_runtime_name("foo"))) +@interface SLREarth +- (instancetype)init; ++ (instancetype)alloc; +@end + +id Test16877359() { + return [SLREarth alloc]; +} + +// CHECK: @"OBJC_IVAR_$_MySecretNamespace.Message.MyIVAR" = global i64 +// CHECK: @"OBJC_CLASS_$_MySecretNamespace.Message" = global %struct._class_t +// CHECK: @"OBJC_METACLASS_$_MySecretNamespace.Message" = global %struct._class_t +// CHECK: @"OBJC_CLASS_$_foo" = external global %struct._class_t +// CHECK: define internal i8* @"\01-[Message MyMethod]" +// CHECK: [[IVAR:%.*]] = load i64* @"OBJC_IVAR_$_MySecretNamespace.Message.MyIVAR" -- 2.7.4