summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/AST/DeclObjC.h7
-rw-r--r--clang/include/clang/Basic/Attr.td4
-rw-r--r--clang/include/clang/Basic/AttrDocs.td19
-rw-r--r--clang/lib/AST/DeclObjC.cpp22
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp13
-rw-r--r--clang/test/SemaObjC/objc-asm-attribute-neg-test.m42
6 files changed, 89 insertions, 18 deletions
diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h
index de5252601aa..db3b0849382 100644
--- a/clang/include/clang/AST/DeclObjC.h
+++ b/clang/include/clang/AST/DeclObjC.h
@@ -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; }
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 964e502716b..11ad93a06b3 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -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 {
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index 947c9ba0149..18c49eefba7 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -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 = [{
diff --git a/clang/lib/AST/DeclObjC.cpp b/clang/lib/AST/DeclObjC.cpp
index f01383a083e..2204dff1373 100644
--- a/clang/lib/AST/DeclObjC.cpp
+++ b/clang/lib/AST/DeclObjC.cpp
@@ -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();
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 29be7033202..61683cd8757 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -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
index 00000000000..2fb6643adde
--- /dev/null
+++ b/clang/test/SemaObjC/objc-asm-attribute-neg-test.m
@@ -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
OpenPOWER on IntegriCloud