@@ -109,6 +109,30 @@ bool Sema::checkInitMethod(ObjCMethodDecl *method,
109
109
return true ;
110
110
}
111
111
112
+ // / Issue a warning if the parameter of the overridden method is non-escaping
113
+ // / but the parameter of the overriding method is not.
114
+ static bool diagnoseNoescape (const ParmVarDecl *NewD, const ParmVarDecl *OldD,
115
+ Sema &S) {
116
+ if (OldD->hasAttr <NoEscapeAttr>() && !NewD->hasAttr <NoEscapeAttr>()) {
117
+ S.Diag (NewD->getLocation (), diag::warn_overriding_method_missing_noescape);
118
+ S.Diag (OldD->getLocation (), diag::note_overridden_marked_noescape);
119
+ return false ;
120
+ }
121
+
122
+ return true ;
123
+ }
124
+
125
+ // / Produce additional diagnostics if a category conforms to a protocol that
126
+ // / defines a method taking a non-escaping parameter.
127
+ static void diagnoseNoescape (const ParmVarDecl *NewD, const ParmVarDecl *OldD,
128
+ const ObjCCategoryDecl *CD,
129
+ const ObjCProtocolDecl *PD, Sema &S) {
130
+ if (!diagnoseNoescape (NewD, OldD, S))
131
+ S.Diag (CD->getLocation (), diag::note_cat_conform_to_noescape_prot)
132
+ << CD->IsClassExtension () << PD
133
+ << cast<ObjCMethodDecl>(NewD->getDeclContext ());
134
+ }
135
+
112
136
void Sema::CheckObjCMethodOverride (ObjCMethodDecl *NewMethod,
113
137
const ObjCMethodDecl *Overridden) {
114
138
if (Overridden->hasRelatedResultType () &&
@@ -192,13 +216,7 @@ void Sema::CheckObjCMethodOverride(ObjCMethodDecl *NewMethod,
192
216
Diag (oldDecl->getLocation (), diag::note_previous_decl) << " parameter" ;
193
217
}
194
218
195
- // A parameter of the overriding method should be annotated with noescape
196
- // if the corresponding parameter of the overridden method is annotated.
197
- if (oldDecl->hasAttr <NoEscapeAttr>() && !newDecl->hasAttr <NoEscapeAttr>()) {
198
- Diag (newDecl->getLocation (),
199
- diag::warn_overriding_method_missing_noescape);
200
- Diag (oldDecl->getLocation (), diag::note_overridden_marked_noescape);
201
- }
219
+ diagnoseNoescape (newDecl, oldDecl, *this );
202
220
}
203
221
}
204
222
@@ -4643,6 +4661,22 @@ Decl *Sema::ActOnMethodDeclaration(
4643
4661
<< ObjCMethod->getDeclName ();
4644
4662
}
4645
4663
}
4664
+
4665
+ // Warn if a method declared in a protocol to which a category or
4666
+ // extension conforms is non-escaping and the implementation's method is
4667
+ // escaping.
4668
+ for (auto *C : IDecl->visible_categories ())
4669
+ for (auto &P : C->protocols ())
4670
+ if (auto *IMD = P->lookupMethod (ObjCMethod->getSelector (),
4671
+ ObjCMethod->isInstanceMethod ())) {
4672
+ assert (ObjCMethod->parameters ().size () ==
4673
+ IMD->parameters ().size () &&
4674
+ " Methods have different number of parameters" );
4675
+ auto OI = IMD->param_begin (), OE = IMD->param_end ();
4676
+ auto NI = ObjCMethod->param_begin ();
4677
+ for (; OI != OE; ++OI, ++NI)
4678
+ diagnoseNoescape (*NI, *OI, C, P, *this );
4679
+ }
4646
4680
}
4647
4681
} else {
4648
4682
cast<DeclContext>(ClassDecl)->addDecl (ObjCMethod);
0 commit comments