1 | // RUN: rm -rf %t |
2 | // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c -fmodule-name=category_top -emit-module %S/Inputs/module.map |
3 | // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c -fmodule-name=category_left -emit-module %S/Inputs/module.map |
4 | // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c -fmodule-name=category_right -emit-module %S/Inputs/module.map |
5 | // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c -fmodule-name=category_bottom -emit-module %S/Inputs/module.map |
6 | // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c -fmodule-name=category_other -emit-module %S/Inputs/module.map |
7 | // RUN: %clang_cc1 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -I %S/Inputs %s -verify |
8 | |
9 | @import category_bottom; |
10 | |
11 | // expected-note@Inputs/category_left.h:14 {{previous definition}} |
12 | // expected-warning@Inputs/category_right.h:12 {{duplicate definition of category}} |
13 | // expected-note@Inputs/category_top.h:1 {{receiver is instance of class declared here}} |
14 | |
15 | @interface Foo(Source) |
16 | -(void)source; |
17 | @end |
18 | |
19 | void test(Foo *foo, LeftFoo *leftFoo) { |
20 | [foo source]; |
21 | [foo bottom]; |
22 | [foo left]; |
23 | [foo right1]; |
24 | [foo right2]; |
25 | [foo top]; |
26 | [foo top2]; |
27 | [foo top3]; |
28 | |
29 | [leftFoo left]; |
30 | [leftFoo bottom]; |
31 | } |
32 | |
33 | // Load another module that also adds categories to Foo, verify that |
34 | // we see those categories. |
35 | @import category_other; |
36 | |
37 | void test_other(Foo *foo) { |
38 | [foo other]; |
39 | } |
40 | |
41 | // Make sure we don't see categories that should be hidden |
42 | void test_hidden_all_errors(Foo *foo) { |
43 | [foo left_sub]; // expected-warning{{instance method '-left_sub' not found (return type defaults to 'id')}} |
44 | foo.right_sub_prop = foo; // expected-error{{property 'right_sub_prop' not found on object of type 'Foo *'}} |
45 | int i = foo->right_sub_ivar; // expected-error{{'Foo' does not have a member named 'right_sub_ivar'}} |
46 | id<P1> p1 = foo; // expected-warning{{initializing 'id<P1>' with an expression of incompatible type 'Foo *'}} |
47 | id<P2> p2 = foo; // expected-warning{{initializing 'id<P2>' with an expression of incompatible type 'Foo *'}} |
48 | id<P3> p3; |
49 | [p3 p3_method]; // expected-warning{{instance method '-p3_method' not found (return type defaults to 'id')}} |
50 | id<P4> p4; |
51 | [p4 p4_method]; // expected-warning{{instance method '-p4_method' not found (return type defaults to 'id')}} |
52 | id p3p = p3.p3_prop; // expected-error{{property 'p3_prop' not found on object of type 'id<P3>'}} |
53 | p3p = foo.p3_prop; // expected-error{{property 'p3_prop' not found on object of type 'Foo *'}} |
54 | id p4p = p4.p4_prop; // expected-error{{property 'p4_prop' not found on object of type 'id<P4>'}} |
55 | p4p = foo.p4_prop; // expected-error{{property 'p4_prop' not found on object of type 'Foo *'}} |
56 | |
57 | if (foo.hiddenPropertyFromExtension) { // expected-error {{property 'hiddenPropertyFromExtension' not found on object of type 'Foo *'}} |
58 | } |
59 | } |
60 | |
61 | @import category_left.sub; |
62 | |
63 | void test_hidden_right_errors(Foo *foo) { |
64 | // These are okay |
65 | [foo left_sub]; // okay |
66 | id<P1> p1 = foo; |
67 | id<P3> p3; |
68 | [p3 p3_method]; |
69 | id p3p = p3.p3_prop; |
70 | p3p = foo.p3_prop; |
71 | // These should fail |
72 | foo.right_sub_prop = foo; // expected-error{{property 'right_sub_prop' not found on object of type 'Foo *'}} |
73 | int i = foo->right_sub_ivar; // expected-error{{'Foo' does not have a member named 'right_sub_ivar'}} |
74 | id<P2> p2 = foo; // expected-warning{{initializing 'id<P2>' with an expression of incompatible type 'Foo *'}} |
75 | id<P4> p4; |
76 | [p4 p4_method]; // expected-warning{{instance method '-p4_method' not found (return type defaults to 'id')}} |
77 | id p4p = p4.p4_prop; // expected-error{{property 'p4_prop' not found on object of type 'id<P4>'}} |
78 | p4p = foo.p4_prop; // expected-error{{property 'p4_prop' not found on object of type 'Foo *'; did you mean 'p3_prop'?}} |
79 | // expected-note@Inputs/category_left_sub.h:7{{'p3_prop' declared here}} |
80 | int hiddenFromExtension = foo.hiddenPropertyFromExtension; // expected-error {{property 'hiddenPropertyFromExtension' not found on object of type 'Foo *'}} |
81 | } |
82 | |
83 | @import category_right.sub; |
84 | |
85 | void test_hidden_okay(Foo *foo) { |
86 | [foo left_sub]; |
87 | foo.right_sub_prop = foo; |
88 | int i = foo->right_sub_ivar; |
89 | id<P1> p1 = foo; |
90 | id<P2> p2 = foo; |
91 | id<P3> p3; |
92 | [p3 p3_method]; |
93 | id<P4> p4; |
94 | [p4 p4_method]; |
95 | id p3p = p3.p3_prop; |
96 | p3p = foo.p3_prop; |
97 | id p4p = p4.p4_prop; |
98 | p4p = foo.p4_prop; |
99 | if (foo.hiddenPropertyFromExtension) { |
100 | } |
101 | } |
102 | |