summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/Attr.td5
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td6
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp25
-rw-r--r--clang/test/SemaObjC/attr-designated-init.m32
4 files changed, 68 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index df8c4edc2c8..2268fa64789 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -684,6 +684,11 @@ def ObjCSuppressProtocol : InheritableAttr {
let Args = [IdentifierArgument<"Protocol">];
}
+def ObjCDesignatedInitializer : Attr {
+ let Spellings = [GNU<"objc_designated_initializer">];
+ let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
+}
+
def Overloadable : Attr {
let Spellings = [GNU<"overloadable">];
let Subjects = SubjectList<[Function], ErrorDiag>;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index a22df2b1af6..8315c78f259 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2427,6 +2427,12 @@ def warn_objc_requires_super_protocol : Warning<
def note_protocol_decl : Note<
"protocol is declared here">;
+// objc_designated_initializer attribute diagnostics.
+def err_attr_objc_designated_not_init_family : Error<
+ "'objc_designated_initializer' only applies to methods of the init family">;
+def err_attr_objc_designated_not_interface : Error<
+ "'objc_designated_initializer' only applies to methods of interface declarations">;
+
def err_ns_bridged_not_interface : Error<
"parameter of 'ns_bridged' attribute does not name an Objective-C class">;
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 24f9f5fd252..b732fccacf8 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -3713,6 +3713,28 @@ static void handleObjCBridgeMutableAttr(Sema &S, Scope *Sc, Decl *D,
Attr.getAttributeSpellingListIndex()));
}
+static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ SourceLocation Loc = Attr.getLoc();
+ ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);
+
+ if (Method->getMethodFamily() != OMF_init) {
+ S.Diag(D->getLocStart(), diag::err_attr_objc_designated_not_init_family)
+ << SourceRange(Loc, Loc);
+ return;
+ }
+ DeclContext *DC = Method->getDeclContext();
+ if (!isa<ObjCInterfaceDecl>(DC)) {
+ S.Diag(D->getLocStart(), diag::err_attr_objc_designated_not_interface)
+ << SourceRange(Loc, Loc);
+ return;
+ }
+
+ Method->addAttr(::new (S.Context)
+ ObjCDesignatedInitializerAttr(Attr.getRange(), S.Context,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleObjCOwnershipAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (hasDeclarator(D)) return;
@@ -3963,6 +3985,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case AttributeList::AT_ObjCBridgeMutable:
handleObjCBridgeMutableAttr(S, scope, D, Attr); break;
+ case AttributeList::AT_ObjCDesignatedInitializer:
+ handleObjCDesignatedInitializer(S, D, Attr); break;
+
case AttributeList::AT_CFAuditedTransfer:
handleCFAuditedTransferAttr(S, D, Attr); break;
case AttributeList::AT_CFUnknownTransfer:
diff --git a/clang/test/SemaObjC/attr-designated-init.m b/clang/test/SemaObjC/attr-designated-init.m
new file mode 100644
index 00000000000..f607bb69447
--- /dev/null
+++ b/clang/test/SemaObjC/attr-designated-init.m
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
+
+void fnfoo(void) NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to methods}}
+
+@protocol P1
+-(id)init NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to methods of interface declarations}}
+@end
+
+__attribute__((objc_root_class))
+@interface I1
+-(void)meth NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to methods of the init family}}
+-(id)init NS_DESIGNATED_INITIALIZER;
++(id)init NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to methods of the init family}}
+@end
+
+@interface I1(cat)
+-(id)init2 NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to methods of interface declarations}}
+@end
+
+@interface I1()
+-(id)init3 NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to methods of interface declarations}}
+@end
+
+@implementation I1
+-(void)meth {}
+-(id)init NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to methods of interface declarations}}
++(id)init { return 0; }
+-(id)init3 { return 0; }
+-(id)init4 NS_DESIGNATED_INITIALIZER { return 0; } // expected-error {{only applies to methods of interface declarations}}
+@end
OpenPOWER on IntegriCloud