[objc] Introduce attribute 'objc_designated_initializer'.

It only applies to methods of init family in an interface declaration.

llvm-svn: 196314
This commit is contained in:
Argyrios Kyrtzidis 2013-12-03 21:11:25 +00:00
parent fd9acf6a48
commit d1438b446e
4 changed files with 68 additions and 0 deletions

View File

@ -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>;

View File

@ -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">;

View File

@ -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:

View File

@ -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