Skip to content

Commit c957a99

Browse files
committed
Merging r353976:
------------------------------------------------------------------------ r353976 | epilk | 2019-02-13 21:32:37 +0100 (Wed, 13 Feb 2019) | 11 lines [Sema] Delay checking whether objc_designated_initializer is being applied to an init method This fixes a regression that was caused by r335084, which reversed the order that attributes are applied. objc_method_family can change whether a method is an init method, so the order that these attributes are applied matters. The commit fixes this by delaying the init check until after all attributes have been applied. rdar://47829358 Differential revision: https://reviews.llvm.org/D58152 ------------------------------------------------------------------------ llvm-svn: 354015
1 parent 6e3c4d5 commit c957a99

File tree

5 files changed

+43
-11
lines changed

5 files changed

+43
-11
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,6 @@ def ObjCInstanceMethod : SubsetSubject<ObjCMethod,
103103
[{S->isInstanceMethod()}],
104104
"Objective-C instance methods">;
105105

106-
def ObjCInterfaceDeclInitMethod : SubsetSubject<ObjCMethod,
107-
[{S->getMethodFamily() == OMF_init &&
108-
(isa<ObjCInterfaceDecl>(S->getDeclContext()) ||
109-
(isa<ObjCCategoryDecl>(S->getDeclContext()) &&
110-
cast<ObjCCategoryDecl>(S->getDeclContext())->IsClassExtension()))}],
111-
"init methods of interface or class extension declarations">;
112-
113106
def Struct : SubsetSubject<Record,
114107
[{!S->isUnion()}], "structs">;
115108

@@ -1762,7 +1755,7 @@ def ObjCExplicitProtocolImpl : InheritableAttr {
17621755

17631756
def ObjCDesignatedInitializer : Attr {
17641757
let Spellings = [Clang<"objc_designated_initializer">];
1765-
let Subjects = SubjectList<[ObjCInterfaceDeclInitMethod], ErrorDiag>;
1758+
let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
17661759
let Documentation = [Undocumented];
17671760
}
17681761

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3460,6 +3460,9 @@ def warn_objc_secondary_init_missing_init_call : Warning<
34603460
def warn_objc_implementation_missing_designated_init_override : Warning<
34613461
"method override for the designated initializer of the superclass %objcinstance0 not found">,
34623462
InGroup<ObjCDesignatedInit>;
3463+
def err_designated_init_attr_non_init : Error<
3464+
"'objc_designated_initializer' attribute only applies to init methods "
3465+
"of interface or class extension declarations">;
34633466

34643467
// objc_bridge attribute diagnostics.
34653468
def err_objc_attr_not_id : Error<

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5116,11 +5116,22 @@ static void handleObjCBridgeRelatedAttr(Sema &S, Decl *D,
51165116

51175117
static void handleObjCDesignatedInitializer(Sema &S, Decl *D,
51185118
const ParsedAttr &AL) {
5119+
DeclContext *Ctx = D->getDeclContext();
5120+
5121+
// This attribute can only be applied to methods in interfaces or class
5122+
// extensions.
5123+
if (!isa<ObjCInterfaceDecl>(Ctx) &&
5124+
!(isa<ObjCCategoryDecl>(Ctx) &&
5125+
cast<ObjCCategoryDecl>(Ctx)->IsClassExtension())) {
5126+
S.Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
5127+
return;
5128+
}
5129+
51195130
ObjCInterfaceDecl *IFace;
5120-
if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(D->getDeclContext()))
5131+
if (auto *CatDecl = dyn_cast<ObjCCategoryDecl>(Ctx))
51215132
IFace = CatDecl->getClassInterface();
51225133
else
5123-
IFace = cast<ObjCInterfaceDecl>(D->getDeclContext());
5134+
IFace = cast<ObjCInterfaceDecl>(Ctx);
51245135

51255136
if (!IFace)
51265137
return;
@@ -7067,6 +7078,17 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
70677078
}
70687079
}
70697080
}
7081+
7082+
// Do this check after processing D's attributes because the attribute
7083+
// objc_method_family can change whether the given method is in the init
7084+
// family, and it can be applied after objc_designated_initializer. This is a
7085+
// bit of a hack, but we need it to be compatible with versions of clang that
7086+
// processed the attribute list in the wrong order.
7087+
if (D->hasAttr<ObjCDesignatedInitializerAttr>() &&
7088+
cast<ObjCMethodDecl>(D)->getMethodFamily() != OMF_init) {
7089+
Diag(D->getLocation(), diag::err_designated_init_attr_non_init);
7090+
D->dropAttr<ObjCDesignatedInitializerAttr>();
7091+
}
70707092
}
70717093

70727094
// Helper for delayed processing TransparentUnion attribute.

clang/test/Misc/pragma-attribute-supported-attributes-list.test

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
// CHECK-NEXT: ObjCBridge (SubjectMatchRule_record, SubjectMatchRule_type_alias)
9595
// CHECK-NEXT: ObjCBridgeMutable (SubjectMatchRule_record)
9696
// CHECK-NEXT: ObjCBridgeRelated (SubjectMatchRule_record)
97+
// CHECK-NEXT: ObjCDesignatedInitializer (SubjectMatchRule_objc_method)
9798
// CHECK-NEXT: ObjCException (SubjectMatchRule_objc_interface)
9899
// CHECK-NEXT: ObjCExplicitProtocolImpl (SubjectMatchRule_objc_protocol)
99100
// CHECK-NEXT: ObjCExternallyRetained (SubjectMatchRule_variable_not_is_parameter, SubjectMatchRule_function, SubjectMatchRule_block, SubjectMatchRule_objc_method)

clang/test/SemaObjC/attr-designated-init.m

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
#define NS_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
44
#define NS_UNAVAILABLE __attribute__((unavailable))
55

6-
void fnfoo(void) NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to init methods of interface or class extension declarations}}
6+
void fnfoo(void) NS_DESIGNATED_INITIALIZER; // expected-error {{'objc_designated_initializer' attribute only applies to Objective-C methods}}
77

88
@protocol P1
99
-(id)init NS_DESIGNATED_INITIALIZER; // expected-error {{only applies to init methods of interface or class extension declarations}}
@@ -428,3 +428,16 @@ - (instancetype)init NS_DESIGNATED_INITIALIZER;
428428
@interface CategoryForMissingInterface(Cat) // expected-error{{cannot find interface declaration}}
429429
- (instancetype)init NS_DESIGNATED_INITIALIZER; // expected-error{{only applies to init methods of interface or class extension declarations}}
430430
@end
431+
432+
@interface TwoAttrs
433+
-(instancetype)foo
434+
__attribute__((objc_designated_initializer))
435+
__attribute__((objc_method_family(init)));
436+
-(instancetype)bar
437+
__attribute__((objc_method_family(init)))
438+
__attribute__((objc_designated_initializer));
439+
-(instancetype)baz
440+
__attribute__((objc_designated_initializer, objc_method_family(init)));
441+
-(instancetype)quux
442+
__attribute__((objc_method_family(init), objc_designated_initializer));
443+
@end

0 commit comments

Comments
 (0)