From 31d5d5d6f0cabd6a8260e743679e28cdbd4a912b Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 3 Dec 2013 21:11:25 +0000 Subject: [PATCH] [objc] Introduce attribute 'objc_designated_initializer'. It only applies to methods of init family in an interface declaration. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@196314 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/Attr.td | 5 ++++ include/clang/Basic/DiagnosticSemaKinds.td | 6 ++++ lib/Sema/SemaDeclAttr.cpp | 25 +++++++++++++++++ test/SemaObjC/attr-designated-init.m | 32 ++++++++++++++++++++++ 4 files changed, 68 insertions(+) create mode 100644 test/SemaObjC/attr-designated-init.m diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index df8c4edc2c..2268fa6478 100644 --- a/include/clang/Basic/Attr.td +++ b/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/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index a22df2b1af..8315c78f25 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/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/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 24f9f5fd25..b732fccacf 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/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(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(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/test/SemaObjC/attr-designated-init.m b/test/SemaObjC/attr-designated-init.m new file mode 100644 index 0000000000..f607bb6944 --- /dev/null +++ b/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 -- 2.40.0