Objective-C. Changes per A. Ballman's comment
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 16 Jul 2014 19:44:34 +0000 (19:44 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 16 Jul 2014 19:44:34 +0000 (19:44 +0000)
for my last patch. // rdar://17631257

llvm-svn: 213185

clang/include/clang/AST/DeclObjC.h
clang/include/clang/Basic/Attr.td
clang/include/clang/Basic/AttrDocs.td
clang/lib/AST/DeclObjC.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/test/SemaObjC/objc-asm-attribute-neg-test.m [new file with mode: 0644]

index de52526..db3b084 100644 (file)
@@ -955,6 +955,9 @@ public:
   void mergeClassExtensionProtocolList(ObjCProtocolDecl *const* List,
                                        unsigned Num,
                                        ASTContext &C);
+
+  /// Produce a name to be used for class's metadata. It comes either via
+  /// objc_runtime_name attribute or class name.
   StringRef getObjCRuntimeNameAsString() const;
 
   /// Returns the designated initializers for the interface.
@@ -1654,6 +1657,8 @@ public:
   /// \brief Starts the definition of this Objective-C protocol.
   void startDefinition();
 
+  /// Produce a name to be used for protocol's metadata. It comes either via
+  /// objc_runtime_name attribute or protocol name.
   StringRef getObjCRuntimeNameAsString() const;
 
   SourceRange getSourceRange() const override LLVM_READONLY {
@@ -2104,6 +2109,8 @@ public:
     return getName();
   }
     
+  /// Produce a name to be used for class's metadata. It comes either via
+  /// class's objc_runtime_name attribute or class name.
   StringRef getObjCRuntimeNameAsString() const;
 
   const ObjCInterfaceDecl *getSuperClass() const { return SuperClass; }
index 964e502..11ad93a 100644 (file)
@@ -993,8 +993,8 @@ def ObjCRuntimeName : Attr {
     let Spellings = [GNU<"objc_runtime_name">];
     let Subjects = SubjectList<[ObjCInterface, ObjCProtocol], ErrorDiag,
     "ExpectedObjectiveCInterfaceOrProtocol">;
-    let Args = [StringArgument<"MetadataName", 1>];
-    let Documentation = [Undocumented];
+    let Args = [StringArgument<"MetadataName">];
+    let Documentation = [ObjCRuntimeNameDocs];
 }
 
 def OptimizeNone : InheritableAttr {
index 947c9ba..18c49ee 100644 (file)
@@ -426,6 +426,25 @@ implementation of an override in a subclass does not call super.  For example:
   }];
 }
 
+def ObjCRuntimeNameDocs : Documentation {
+    let Category = DocCatFunction;
+    let Content = [{
+        Annotation of Objective-C classes and protocols with this attribute allow to
+        use an alternative name for metadata names which normally use class or protocol
+        names as part of their names.
+        
+        **Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``.  This attribute
+        can only be placed before an @protocol or @interface declaration:
+        
+        .. code-block:: objc
+        
+        __attribute__((objc_runtime_name("MyLocalName")))
+        @interface Message
+        @end
+        
+    }];
+}
+
 def AvailabilityDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
index f01383a..2204dff 100644 (file)
@@ -1201,18 +1201,19 @@ bool ObjCInterfaceDecl::hasDesignatedInitializers() const {
 
 StringRef
 ObjCInterfaceDecl::getObjCRuntimeNameAsString() const {
-    if (ObjCRuntimeNameAttr *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
-        return ObjCRTName->getMetadataName();
-    return getName();
+  if (ObjCRuntimeNameAttr *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
+    return ObjCRTName->getMetadataName();
+
+  return getName();
 }
 
 StringRef
 ObjCImplementationDecl::getObjCRuntimeNameAsString() const {
-    if (ObjCInterfaceDecl *ID =
-        const_cast<ObjCImplementationDecl*>(this)->getClassInterface())
-        return ID->getObjCRuntimeNameAsString();
+  if (ObjCInterfaceDecl *ID =
+      const_cast<ObjCImplementationDecl*>(this)->getClassInterface())
+    return ID->getObjCRuntimeNameAsString();
     
-    return getName();
+  return getName();
 }
 
 ObjCImplementationDecl *ObjCInterfaceDecl::getImplementation() const {
@@ -1621,9 +1622,10 @@ void ObjCProtocolDecl::collectInheritedProtocolProperties(
 
 StringRef
 ObjCProtocolDecl::getObjCRuntimeNameAsString() const {
-    if (ObjCRuntimeNameAttr *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
-        return ObjCRTName->getMetadataName();
-    return getName();
+  if (ObjCRuntimeNameAttr *ObjCRTName = getAttr<ObjCRuntimeNameAttr>())
+    return ObjCRTName->getMetadataName();
+
+  return getName();
 }
 
 //===----------------------------------------------------------------------===//
index 29be703..61683cd 100644 (file)
@@ -3599,12 +3599,13 @@ static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
 
 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));
+  StringRef MetaDataName;
+  if (!S.checkStringLiteralArgumentAttr(Attr, 0, MetaDataName))
+    return;
+  D->addAttr(::new (S.Context)
+             ObjCRuntimeNameAttr(Attr.getRange(), S.Context,
+                                 MetaDataName,
+                                 Attr.getAttributeSpellingListIndex()));
 }
 
 static void handleObjCOwnershipAttr(Sema &S, Decl *D,
diff --git a/clang/test/SemaObjC/objc-asm-attribute-neg-test.m b/clang/test/SemaObjC/objc-asm-attribute-neg-test.m
new file mode 100644 (file)
index 0000000..2fb6643
--- /dev/null
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1  -fsyntax-only -verify -Wno-objc-root-class %s
+// rdar://16462586
+
+__attribute__((objc_runtime_name)) // expected-error {{'objc_runtime_name' attribute takes one argument}}
+@interface BInterface
+@end
+
+__attribute__((objc_runtime_name(123))) // expected-error {{'objc_runtime_name' attribute requires a string}}
+@protocol BProtocol1
+@end
+
+__attribute__((objc_runtime_name("MySecretNamespace.Protocol")))
+@protocol Protocol
+@end
+
+__attribute__((objc_runtime_name("MySecretNamespace.Message")))
+@interface Message <Protocol> { 
+__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