1// RUN: clang-cc -fsyntax-only -verify -pedantic %s
2@protocol NSObject
3@end
4
5@protocol DTOutputStreams <NSObject>
6@end
7
8@interface DTFilterOutputStream <DTOutputStreams>
9- nextOutputStream;
10@end
11
12@implementation DTFilterOutputStream
13- (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream {
14  id <DTOutputStreams> nextOutputStream = [self nextOutputStream];
15  self = nextOutputStream;
16  return nextOutputStream ? nextOutputStream : self;
17}
18- nextOutputStream {
19  return self;
20}
21@end
22
23@interface DTFilterOutputStream2
24- nextOutputStream;
25@end
26
27@implementation DTFilterOutputStream2 // expected-warning {{incomplete implementation}} expected-warning {{method definition for 'nextOutputStream' not found}}
28- (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream {
29  id <DTOutputStreams> nextOutputStream = [self nextOutputStream];
30  // GCC warns about both of these.
31  self = nextOutputStream; // expected-warning {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream2 *'}}
32  return nextOutputStream ? nextOutputStream : self;
33}
34@end
35
36// No @interface declaration for DTFilterOutputStream3
37@implementation DTFilterOutputStream3 // expected-warning {{cannot find interface declaration for 'DTFilterOutputStream3'}}
38- (id)initWithNextOutputStream:(id <DTOutputStreams>) outputStream {
39  id <DTOutputStreams> nextOutputStream = [self nextOutputStream]; // expected-warning {{method '-nextOutputStream' not found (return type defaults to 'id')}}
40  // GCC warns about both of these as well (no errors).
41  self = nextOutputStream; // expected-warning {{incompatible type assigning 'id<DTOutputStreams>', expected 'DTFilterOutputStream3 *'}}
42  return nextOutputStream ? nextOutputStream : self;
43}
44@end
45
46//
47
48@protocol P0
49@property int intProp;
50@end
51@protocol P1
52@end
53@protocol P2
54@end
55
56@interface A <P0>
57@end
58
59@interface B : A
60@end
61
62@interface C
63@end
64
65@interface D
66@end
67
68void f0(id<P0> x) {
69  x.intProp = 1;
70}
71
72void f1(int cond, id<P0> x, id<P0> y) {
73  (cond ? x : y).intProp = 1;
74}
75
76void f2(int cond, id<P0> x, A *y) {
77  (cond ? x : y).intProp = 1;
78}
79
80void f3(int cond, id<P0> x, B *y) {
81  (cond ? x : y).intProp = 1;
82}
83
84void f4(int cond, id x, B *y) {
85  (cond ? x : y).intProp = 1; // expected-error {{property 'intProp' not found on object of type 'id'}}
86}
87
88void f5(int cond, id<P0> x, C *y) {
89  (cond ? x : y).intProp = 1; // expected-error {{property 'intProp' not found on object of type 'C *'}}
90}
91
92void f6(int cond, C *x, D *y) {
93  (cond ? x : y).intProp = 1; // expected-warning {{incompatible operand types}}, expected-error {{property 'intProp' not found on object of type 'id'}}
94}
95
96id f7(int a, id<P0> x, A* p) {
97  return a ? x : p;
98}
99
100void f8(int a, A<P0> *x, A *y) {
101  [ (a ? x : y ) intProp ];
102}
103
104void f9(int a, A<P0> *x, A<P1> *y) {
105  id l0 = (a ? x : y ); // expected-warning {{incompatible operand types ('A<P0> *' and 'A<P1> *')'}}
106  A<P0> *l1 = (a ? x : y ); // expected-warning {{incompatible operand types ('A<P0> *' and 'A<P1> *')}}
107  A<P1> *l2 = (a ? x : y ); // expected-warning {{incompatible operand types ('A<P0> *' and 'A<P1> *')}}
108  [ (a ? x : y ) intProp ]; // expected-warning {{incompatible operand types ('A<P0> *' and 'A<P1> *')}}
109}
110
111void f10(int a, id<P0> x, id y) {
112  [ (a ? x : y ) intProp ];
113}
114
115void f11(int a, id<P0> x, id<P1> y) {
116  [ (a ? x : y ) intProp ]; // expected-warning {{incompatible operand types ('id<P0>' and 'id<P1>')}}
117}
118
119void f12(int a, A<P0> *x, A<P1> *y) {
120  A<P1>* l0 = (a ? x : y ); // expected-warning {{incompatible operand types ('A<P0> *' and 'A<P1> *')}}
121}
122