xref: /llvm-project/clang/test/SemaCXX/conditional-expr.cpp (revision 3b7ef5e3743810896a832fa798a687ea682e4e49)
1 // RUN: clang-cc -fsyntax-only -verify -std=c++0x %s
2 
3 // C++ rules for ?: are a lot stricter than C rules, and have to take into
4 // account more conversion options.
5 // This test runs in C++0x mode for the contextual conversion of the condition.
6 
7 struct ToBool { explicit operator bool(); };
8 
9 struct B;
10 struct A { A(); A(const B&); };
11 struct B { operator A() const; };
12 struct I { operator int(); };
13 struct J { operator I(); };
14 struct K { operator double(); };
15 typedef void (*vfn)();
16 struct F { operator vfn(); };
17 struct G { operator vfn(); };
18 
19 struct Base {
20   int trick();
21   A trick() const;
22   void fn1();
23 };
24 struct Derived : Base {
25   void fn2();
26 };
27 struct Convertible { operator Base&(); };
28 struct Priv : private Base {};
29 struct Mid : Base {};
30 struct Fin : Mid, Derived {};
31 typedef void (Derived::*DFnPtr)();
32 struct ToMemPtr { operator DFnPtr(); };
33 
34 struct BadDerived;
35 struct BadBase { operator BadDerived&(); };
36 struct BadDerived : BadBase {};
37 
38 struct Fields {
39   int i1, i2, b1 : 3, b2 : 3;
40 };
41 
42 enum Enum { EVal };
43 
44 struct Ambig {
45   operator short();
46   operator signed char();
47 };
48 
49 void test()
50 {
51   // This function tests C++0x 5.16
52 
53   // p1 (contextually convert to bool)
54   int i1 = ToBool() ? 0 : 1;
55 
56   // p2 (one or both void, and throwing)
57   i1 ? throw 0 : throw 1;
58   i1 ? test() : throw 1;
59   i1 ? throw 0 : test();
60   i1 ? test() : test();
61   i1 = i1 ? throw 0 : 0;
62   i1 = i1 ? 0 : throw 0;
63   i1 ? 0 : test(); // expected-error {{right operand to ? is void, but left operand is of type 'int'}}
64   i1 ? test() : 0; // expected-error {{left operand to ? is void, but right operand is of type 'int'}}
65   (i1 ? throw 0 : i1) = 0; // expected-error {{expression is not assignable}}
66   (i1 ? i1 : throw 0) = 0; // expected-error {{expression is not assignable}}
67 
68   // p3 (one or both class type, convert to each other)
69   // b1 (lvalues)
70   Base base;
71   Derived derived;
72   Convertible conv;
73   Base &bar1 = i1 ? base : derived;
74   Base &bar2 = i1 ? derived : base;
75   Base &bar3 = i1 ? base : conv;
76   Base &bar4 = i1 ? conv : base;
77   // these are ambiguous
78   BadBase bb;
79   BadDerived bd;
80   (void)(i1 ? bb : bd); // expected-error {{conditional expression is ambiguous; 'struct BadBase' can be converted to 'struct BadDerived' and vice versa}}
81   (void)(i1 ? bd : bb); // expected-error {{conditional expression is ambiguous}}
82   // curiously enough (and a defect?), these are not
83   // for rvalues, hierarchy takes precedence over other conversions
84   (void)(i1 ? BadBase() : BadDerived());
85   (void)(i1 ? BadDerived() : BadBase());
86 
87   // b2.1 (hierarchy stuff)
88   const Base constret();
89   const Derived constder();
90   // should use const overload
91   A a1((i1 ? constret() : Base()).trick());
92   A a2((i1 ? Base() : constret()).trick());
93   A a3((i1 ? constret() : Derived()).trick());
94   A a4((i1 ? Derived() : constret()).trick());
95   // should use non-const overload
96   i1 = (i1 ? Base() : Base()).trick();
97   i1 = (i1 ? Base() : Base()).trick();
98   i1 = (i1 ? Base() : Derived()).trick();
99   i1 = (i1 ? Derived() : Base()).trick();
100   // should fail: const lost
101   (void)(i1 ? Base() : constder()); // expected-error {{incompatible operand types ('struct Base' and 'struct Derived const')}}
102   (void)(i1 ? constder() : Base()); // expected-error {{incompatible operand types ('struct Derived const' and 'struct Base')}}
103   // FIXME: should fail: private or ambiguous base
104   (void)(i1 ? Base() : Priv()); // xpected-error private base
105   (void)(i1 ? Priv() : Base()); // xpected-error private base
106   (void)(i1 ? Base() : Fin()); // xpected-error ambiguous base
107   (void)(i1 ? Fin() : Base()); // xpected-error ambiguous base
108 
109   // b2.2 (non-hierarchy)
110   i1 = i1 ? I() : i1;
111   i1 = i1 ? i1 : I();
112   I i2(i1 ? I() : J());
113   I i3(i1 ? J() : I());
114   // "the type [it] woud have if E2 were converted to an rvalue"
115   vfn pfn = i1 ? F() : test;
116   pfn = i1 ? test : F();
117   // these are ambiguous - better messages would be nice
118   (void)(i1 ? A() : B()); // expected-error {{incompatible operand types}}
119   (void)(i1 ? B() : A()); // expected-error {{incompatible operand types}}
120   (void)(i1 ? 1 : Ambig()); // expected-error {{incompatible operand types}}
121   (void)(i1 ? Ambig() : 1); // expected-error {{incompatible operand types}}
122   // By the way, this isn't an lvalue:
123   &(i1 ? i1 : i2); // expected-error {{address expression must be an lvalue or a function designator}}
124 
125   // p4 (lvalue, same type)
126   Fields flds;
127   int &ir1 = i1 ? flds.i1 : flds.i2;
128   (i1 ? flds.b1 : flds.i2) = 0;
129   (i1 ? flds.i1 : flds.b2) = 0;
130   (i1 ? flds.b1 : flds.b2) = 0;
131 
132   // p5 (conversion to built-in types)
133   // GCC 4.3 fails these
134   double d1 = i1 ? I() : K();
135   pfn = i1 ? F() : G();
136   DFnPtr pfm;
137   // FIXME: Overload resolution won't choose the member pointer yet.
138   //pfm = i1 ? DFnPtr() : &Base::fn1;
139   //pfm = i1 ? &Base::fn1 : DFnPtr();
140 
141   // p6 (final conversions)
142   i1 = i1 ? i1 : ir1;
143   int *pi1 = i1 ? &i1 : 0;
144   pi1 = i1 ? 0 : &i1;
145   i1 = i1 ? i1 : EVal;
146   i1 = i1 ? EVal : i1;
147   d1 = i1 ? 'c' : 4.0;
148   d1 = i1 ? 4.0 : 'c';
149   Base *pb = i1 ? (Base*)0 : (Derived*)0;
150   pb = i1 ? (Derived*)0 : (Base*)0;
151   // FIXME: member pointer conversions don't work yet.
152   //pfm = i1 ? &Base::fn1 : &Derived::fn2;
153   //pfm = i1 ? &Derived::fn2 : &Base::fn1;
154   //pfm = i1 ? &Derived::fn2 : 0;
155   //pfm = i1 ? 0 : &Derived::fn2;
156   // Conversion of primitives does not result in an lvalue.
157   &(i1 ? i1 : d1); // expected-error {{address expression must be an lvalue or a function designator}}
158 
159 
160   // Note the thing that this does not test: since DR446, various situations
161   // *must* create a separate temporary copy of class objects. This can only
162   // be properly tested at runtime, though.
163 }
164