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