1*f4a2713aSLionel Sambuc// RUN: %clang_cc1 -fsyntax-only -verify %s 2*f4a2713aSLionel Sambuc// <rdar://problem/6212771> 3*f4a2713aSLionel Sambuc 4*f4a2713aSLionel Sambuc#define nil ((void*) 0) 5*f4a2713aSLionel Sambuc 6*f4a2713aSLionel Sambuc@interface A 7*f4a2713aSLionel Sambuc@property int x; 8*f4a2713aSLionel Sambuc@end 9*f4a2713aSLionel Sambuc 10*f4a2713aSLionel Sambuc@interface B : A 11*f4a2713aSLionel Sambuc@end 12*f4a2713aSLionel Sambuc 13*f4a2713aSLionel Sambuc// Basic checks... 14*f4a2713aSLionel Sambucid f0(int cond, id a, void *b) { 15*f4a2713aSLionel Sambuc return cond ? a : b; 16*f4a2713aSLionel Sambuc} 17*f4a2713aSLionel SambucA *f0_a(int cond, A *a, void *b) { 18*f4a2713aSLionel Sambuc return cond ? a : b; 19*f4a2713aSLionel Sambuc} 20*f4a2713aSLionel Sambuc 21*f4a2713aSLionel Sambucid f1(int cond, id a) { 22*f4a2713aSLionel Sambuc return cond ? a : nil; 23*f4a2713aSLionel Sambuc} 24*f4a2713aSLionel SambucA *f1_a(int cond, A *a) { 25*f4a2713aSLionel Sambuc return cond ? a : nil; 26*f4a2713aSLionel Sambuc} 27*f4a2713aSLionel Sambuc 28*f4a2713aSLionel Sambucvoid *f1_const_a(int x, void *p, const A * q) { 29*f4a2713aSLionel Sambuc void *r = x ? p : q; // expected-warning{{initializing 'void *' with an expression of type 'const void *' discards qualifiers}} 30*f4a2713aSLionel Sambuc return r; 31*f4a2713aSLionel Sambuc} 32*f4a2713aSLionel Sambuc 33*f4a2713aSLionel Sambuc// Check interaction with qualified id 34*f4a2713aSLionel Sambuc 35*f4a2713aSLionel Sambuc@protocol P0 @end 36*f4a2713aSLionel Sambuc 37*f4a2713aSLionel Sambucid f2(int cond, id<P0> a, void *b) { 38*f4a2713aSLionel Sambuc return cond ? a : b; 39*f4a2713aSLionel Sambuc} 40*f4a2713aSLionel Sambuc 41*f4a2713aSLionel Sambucid f3(int cond, id<P0> a) { 42*f4a2713aSLionel Sambuc return cond ? a : nil; 43*f4a2713aSLionel Sambuc} 44*f4a2713aSLionel Sambuc 45*f4a2713aSLionel Sambuc// Check that result actually has correct type. 46*f4a2713aSLionel Sambuc 47*f4a2713aSLionel Sambuc// Using properties is one way to find the compiler internal type of a 48*f4a2713aSLionel Sambuc// conditional expression. Simple assignment doesn't work because if 49*f4a2713aSLionel Sambuc// the type is id then it can be implicitly promoted. 50*f4a2713aSLionel Sambuc@protocol P1 51*f4a2713aSLionel Sambuc@property int x; 52*f4a2713aSLionel Sambuc@end 53*f4a2713aSLionel Sambuc 54*f4a2713aSLionel Sambucint f5(int cond, id<P1> a, id<P1> b) { 55*f4a2713aSLionel Sambuc return (cond ? a : b).x; 56*f4a2713aSLionel Sambuc} 57*f4a2713aSLionel Sambucint f5_a(int cond, A *a, A *b) { 58*f4a2713aSLionel Sambuc return (cond ? a : b).x; 59*f4a2713aSLionel Sambuc} 60*f4a2713aSLionel Sambucint f5_b(int cond, A *a, B *b) { 61*f4a2713aSLionel Sambuc return (cond ? a : b).x; 62*f4a2713aSLionel Sambuc} 63*f4a2713aSLionel Sambuc 64*f4a2713aSLionel Sambucint f6(int cond, id<P1> a, void *b) { 65*f4a2713aSLionel Sambuc // This should result in something with id type, currently. 66*f4a2713aSLionel Sambuc return (cond ? a : b).x; // expected-error {{member reference base type 'void *' is not a structure or union}} 67*f4a2713aSLionel Sambuc} 68*f4a2713aSLionel Sambuc 69*f4a2713aSLionel Sambucint f7(int cond, id<P1> a) { 70*f4a2713aSLionel Sambuc return (cond ? a : nil).x; 71*f4a2713aSLionel Sambuc} 72*f4a2713aSLionel Sambuc 73*f4a2713aSLionel Sambucint f8(int cond, id<P1> a, A *b) { 74*f4a2713aSLionel Sambuc return a == b; // expected-warning {{comparison of distinct pointer types ('id<P1>' and 'A *')}} 75*f4a2713aSLionel Sambuc} 76*f4a2713aSLionel Sambuc 77*f4a2713aSLionel Sambucint f9(int cond, id<P1> a, A *b) { 78*f4a2713aSLionel Sambuc return (cond ? a : b).x; // expected-warning {{incompatible operand types ('id<P1>' and 'A *')}} \ 79*f4a2713aSLionel Sambuc expected-error {{property 'x' not found on object of type 'id'}} 80*f4a2713aSLionel Sambuc} 81