blob: aa71f60dc1664ee1fe9e853282d4f3a19691723a [file] [log] [blame]
Sebastian Redl3201f6b2009-04-16 17:51:27 +00001// 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
7struct ToBool { explicit operator bool(); };
8
9struct B;
10struct A { A(); A(const B&); };
11struct B { operator A() const; };
12struct I { operator int(); };
13struct J { operator I(); };
14struct K { operator double(); };
15typedef void (*vfn)();
16struct F { operator vfn(); };
17struct G { operator vfn(); };
18
19struct Base {
20 int trick();
21 A trick() const;
Sebastian Redl76458502009-04-17 16:30:52 +000022 void fn1();
Sebastian Redl3201f6b2009-04-16 17:51:27 +000023};
Sebastian Redl76458502009-04-17 16:30:52 +000024struct Derived : Base {
25 void fn2();
26};
Sebastian Redl3201f6b2009-04-16 17:51:27 +000027struct Convertible { operator Base&(); };
28struct Priv : private Base {};
29struct Mid : Base {};
30struct Fin : Mid, Derived {};
Sebastian Redl76458502009-04-17 16:30:52 +000031typedef void (Derived::*DFnPtr)();
32struct ToMemPtr { operator DFnPtr(); };
Sebastian Redl3201f6b2009-04-16 17:51:27 +000033
34struct BadDerived;
35struct BadBase { operator BadDerived&(); };
36struct BadDerived : BadBase {};
37
38struct Fields {
39 int i1, i2, b1 : 3, b2 : 3;
40};
41
42enum Enum { EVal };
43
44struct Ambig {
45 operator short();
46 operator signed char();
47};
48
49void 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;
Sebastian Redl76458502009-04-17 16:30:52 +000073 Base &bar1 = i1 ? base : derived;
74 Base &bar2 = i1 ? derived : base;
75 Base &bar3 = i1 ? base : conv;
76 Base &bar4 = i1 ? conv : base;
Sebastian Redl3201f6b2009-04-16 17:51:27 +000077 // 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')}}
Sebastian Redl76458502009-04-17 16:30:52 +0000103 // FIXME: should fail: private or ambiguous base
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000104 (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}}
Sebastian Redl76458502009-04-17 16:30:52 +0000122 // By the way, this isn't an lvalue:
123 &(i1 ? i1 : i2); // expected-error {{address expression must be an lvalue or a function designator}}
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000124
125 // p4 (lvalue, same type)
Sebastian Redl76458502009-04-17 16:30:52 +0000126 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;
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000131
132 // p5 (conversion to built-in types)
133 // GCC 4.3 fails these
134 double d1 = i1 ? I() : K();
135 pfn = i1 ? F() : G();
Sebastian Redl76458502009-04-17 16:30:52 +0000136 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();
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000140
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';
Sebastian Redld1bd7fc2009-04-19 19:26:31 +0000149 Base *pb = i1 ? (Base*)0 : (Derived*)0;
150 pb = i1 ? (Derived*)0 : (Base*)0;
151 // FIXME: member pointer conversions don't work yet.
Sebastian Redl76458502009-04-17 16:30:52 +0000152 //pfm = i1 ? &Base::fn1 : &Derived::fn2;
153 //pfm = i1 ? &Derived::fn2 : &Base::fn1;
Sebastian Redld1bd7fc2009-04-19 19:26:31 +0000154 //pfm = i1 ? &Derived::fn2 : 0;
155 //pfm = i1 ? 0 : &Derived::fn2;
Sebastian Redl76458502009-04-17 16:30:52 +0000156 // 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
Sebastian Redl3201f6b2009-04-16 17:51:27 +0000159
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}