This is an archive of the discontinued LLVM Phabricator instance.

[Sema][ObjC] Issue a warning when a method declared in a protocol is non-escaping but the corresponding method in the implementation is escaping.
ClosedPublic

Authored by ahatanak on Jul 9 2018, 7:03 PM.

Details

Summary

This patch makes Sema issue a warning when there is an extension that conforms to a protocol that declares a non-escaping method and the corresponding method in the implementation isn't non-escaping.

rdar://problem/39548196

Diff Detail

Repository
rC Clang

Event Timeline

ahatanak created this revision.Jul 9 2018, 7:03 PM

Overall looks good to me. Maybe add a test when a protocol is declared for an interface, not for a category. Something like

__attribute__((objc_root_class))
@interface C4 <NoescapeProt>
-(void) m0:(int*) p; // expected-warning {{parameter of overriding method should be annotated with __attribute__((noescape))}}
@end

@implementation C4
-(void) m0:(int*) p {
}
@end

Looks like there is no such test already and it seems different enough to be worth adding. The idea for this test was triggered by code for (auto *C : IDecl->visible_categories()) and the goal is to cover a case when protocol is not for a category.

Also I had a few ideas for tests when the warning isn't required and it is absent. But I'm not sure they are actually valuable. If you are interested, we can discuss it in more details.

Another feedback is an idea for potential improvement: have a note pointing to the place where protocol conformity is declared. Currently the warning looks like

code_review.m:16:19: warning: parameter of overriding method should be annotated with __attribute__((noescape))
      [-Wmissing-noescape]
-(void) m0:(int*) p { // expected-warning {{parameter of overriding method should be annotated with __attri...
                  ^
code_review.m:2:44: note: parameter of overridden method is annotated with __attribute__((noescape))
-(void) m0:(int*)__attribute__((noescape)) p; // expected-note {{parameter of overridden method is annotate...
                                           ^

and we can see the method both in implementation and in protocol. But in some cases it might be unclear where exactly that protocol was added to your class. I'm not sure this change is sufficiently useful, it's more for discussion.

ahatanak updated this revision to Diff 157398.Jul 25 2018, 4:50 PM

Add a test case for an interface conforming to a non-escaping protocol.

Also I had a few ideas for tests when the warning isn't required and it is absent. But I'm not sure they are actually valuable. If you are interested, we can discuss it in more details.

Could you elaborate on what kind of tests you have in mind?

Another feedback is an idea for potential improvement: have a note pointing to the place where protocol conformity is declared. Currently the warning looks like

code_review.m:16:19: warning: parameter of overriding method should be annotated with __attribute__((noescape))
      [-Wmissing-noescape]
-(void) m0:(int*) p { // expected-warning {{parameter of overriding method should be annotated with __attri...
                  ^
code_review.m:2:44: note: parameter of overridden method is annotated with __attribute__((noescape))
-(void) m0:(int*)__attribute__((noescape)) p; // expected-note {{parameter of overridden method is annotate...
                                           ^

and we can see the method both in implementation and in protocol. But in some cases it might be unclear where exactly that protocol was added to your class. I'm not sure this change is sufficiently useful, it's more for discussion.

I think it's possible to add a note that helps the user find where the category conforming to the non-escaping protocol is declared.

Also I had a few ideas for tests when the warning isn't required and it is absent. But I'm not sure they are actually valuable. If you are interested, we can discuss it in more details.

Could you elaborate on what kind of tests you have in mind?

  • declaring noescape on implementation when nothing like that was mentioned in interface or protocols;
  • have class method and instance method with the same name, only one of them is noescape, test that we don't show spurious warning in this case;
  • try selector names that look similar but are different, like -foo, -foo:, -foo:: This test suggestion isn't really related to noescape, I just got carried away.
vsapsai accepted this revision.Jul 27 2018, 3:18 PM

Looks good to me. Any further improvements are up to you.

This revision is now accepted and ready to land.Jul 27 2018, 3:18 PM

Thanks, I'll update the patch and commit it today.

Also I had a few ideas for tests when the warning isn't required and it is absent. But I'm not sure they are actually valuable. If you are interested, we can discuss it in more details.

Could you elaborate on what kind of tests you have in mind?

  • declaring noescape on implementation when nothing like that was mentioned in interface or protocols;

Maybe we should consider this, but I don't think this is incorrect functionally. If you pass an object to such methods, clang's IRGen will just emit the unoptimized code that is emitted for calls to functions/methods taking escaping parameters (e.g., no 'nocapture' on parameters, no stack block optimization implemented in r337580). The opposite case (non-escaping interface and escaping implementation) is incorrect and can cause problems, so we need some diagnostics.

  • have class method and instance method with the same name, only one of them is noescape, test that we don't show spurious warning in this case;

I can add a test case for this.

  • try selector names that look similar but are different, like -foo, -foo:, -foo:: This test suggestion isn't really related to noescape, I just got carried away.
ahatanak updated this revision to Diff 157815.Jul 27 2018, 5:21 PM
  • Produce a note that tells users where the class extension conforming to the protocol containing the non-escaping method is declared.
  • Add a class method that has the same name as the instance method and check that no spurious warnings are issued.
This revision was automatically updated to reflect the committed changes.