xref: /minix3/external/bsd/llvm/dist/clang/test/SemaCXX/expression-traits.cpp (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc // RUN: %clang_cc1 -fsyntax-only -verify -fcxx-exceptions %s
2*f4a2713aSLionel Sambuc 
3*f4a2713aSLionel Sambuc //
4*f4a2713aSLionel Sambuc // Tests for "expression traits" intrinsics such as __is_lvalue_expr.
5*f4a2713aSLionel Sambuc //
6*f4a2713aSLionel Sambuc // For the time being, these tests are written against the 2003 C++
7*f4a2713aSLionel Sambuc // standard (ISO/IEC 14882:2003 -- see draft at
8*f4a2713aSLionel Sambuc // http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2001/n1316/).
9*f4a2713aSLionel Sambuc //
10*f4a2713aSLionel Sambuc // C++0x has its own, more-refined, idea of lvalues and rvalues.
11*f4a2713aSLionel Sambuc // If/when we need to support those, we'll need to track both
12*f4a2713aSLionel Sambuc // standard documents.
13*f4a2713aSLionel Sambuc 
14*f4a2713aSLionel Sambuc #if !__has_feature(cxx_static_assert)
15*f4a2713aSLionel Sambuc # define CONCAT_(X_, Y_) CONCAT1_(X_, Y_)
16*f4a2713aSLionel Sambuc # define CONCAT1_(X_, Y_) X_ ## Y_
17*f4a2713aSLionel Sambuc 
18*f4a2713aSLionel Sambuc // This emulation can be used multiple times on one line (and thus in
19*f4a2713aSLionel Sambuc // a macro), except at class scope
20*f4a2713aSLionel Sambuc # define static_assert(b_, m_) \
21*f4a2713aSLionel Sambuc   typedef int CONCAT_(sa_, __LINE__)[b_ ? 1 : -1]
22*f4a2713aSLionel Sambuc #endif
23*f4a2713aSLionel Sambuc 
24*f4a2713aSLionel Sambuc // Tests are broken down according to section of the C++03 standard
25*f4a2713aSLionel Sambuc // (ISO/IEC 14882:2003(E))
26*f4a2713aSLionel Sambuc 
27*f4a2713aSLionel Sambuc // Assertion macros encoding the following two paragraphs
28*f4a2713aSLionel Sambuc //
29*f4a2713aSLionel Sambuc // basic.lval/1 Every expression is either an lvalue or an rvalue.
30*f4a2713aSLionel Sambuc //
31*f4a2713aSLionel Sambuc // expr.prim/5 A parenthesized expression is a primary expression whose type
32*f4a2713aSLionel Sambuc // and value are identical to those of the enclosed expression. The
33*f4a2713aSLionel Sambuc // presence of parentheses does not affect whether the expression is
34*f4a2713aSLionel Sambuc // an lvalue.
35*f4a2713aSLionel Sambuc //
36*f4a2713aSLionel Sambuc // Note: these asserts cannot be made at class scope in C++03.  Put
37*f4a2713aSLionel Sambuc // them in a member function instead.
38*f4a2713aSLionel Sambuc #define ASSERT_LVALUE(expr)                                             \
39*f4a2713aSLionel Sambuc     static_assert(__is_lvalue_expr(expr), "should be an lvalue");       \
40*f4a2713aSLionel Sambuc     static_assert(__is_lvalue_expr((expr)),                             \
41*f4a2713aSLionel Sambuc                   "the presence of parentheses should have"             \
42*f4a2713aSLionel Sambuc                   " no effect on lvalueness (expr.prim/5)");            \
43*f4a2713aSLionel Sambuc     static_assert(!__is_rvalue_expr(expr), "should be an lvalue");      \
44*f4a2713aSLionel Sambuc     static_assert(!__is_rvalue_expr((expr)),                            \
45*f4a2713aSLionel Sambuc                   "the presence of parentheses should have"             \
46*f4a2713aSLionel Sambuc                   " no effect on lvalueness (expr.prim/5)")
47*f4a2713aSLionel Sambuc 
48*f4a2713aSLionel Sambuc #define ASSERT_RVALUE(expr);                                            \
49*f4a2713aSLionel Sambuc     static_assert(__is_rvalue_expr(expr), "should be an rvalue");       \
50*f4a2713aSLionel Sambuc     static_assert(__is_rvalue_expr((expr)),                             \
51*f4a2713aSLionel Sambuc                   "the presence of parentheses should have"             \
52*f4a2713aSLionel Sambuc                   " no effect on lvalueness (expr.prim/5)");            \
53*f4a2713aSLionel Sambuc     static_assert(!__is_lvalue_expr(expr), "should be an rvalue");      \
54*f4a2713aSLionel Sambuc     static_assert(!__is_lvalue_expr((expr)),                            \
55*f4a2713aSLionel Sambuc                   "the presence of parentheses should have"             \
56*f4a2713aSLionel Sambuc                   " no effect on lvalueness (expr.prim/5)")
57*f4a2713aSLionel Sambuc 
58*f4a2713aSLionel Sambuc enum Enum { Enumerator };
59*f4a2713aSLionel Sambuc 
60*f4a2713aSLionel Sambuc int ReturnInt();
61*f4a2713aSLionel Sambuc void ReturnVoid();
62*f4a2713aSLionel Sambuc Enum ReturnEnum();
63*f4a2713aSLionel Sambuc 
64*f4a2713aSLionel Sambuc void basic_lval_5()
65*f4a2713aSLionel Sambuc {
66*f4a2713aSLionel Sambuc     // basic.lval/5: The result of calling a function that does not return
67*f4a2713aSLionel Sambuc     // a reference is an rvalue.
68*f4a2713aSLionel Sambuc     ASSERT_RVALUE(ReturnInt());
69*f4a2713aSLionel Sambuc     ASSERT_RVALUE(ReturnVoid());
70*f4a2713aSLionel Sambuc     ASSERT_RVALUE(ReturnEnum());
71*f4a2713aSLionel Sambuc }
72*f4a2713aSLionel Sambuc 
73*f4a2713aSLionel Sambuc int& ReturnIntReference();
74*f4a2713aSLionel Sambuc extern Enum& ReturnEnumReference();
75*f4a2713aSLionel Sambuc 
76*f4a2713aSLionel Sambuc void basic_lval_6()
77*f4a2713aSLionel Sambuc {
78*f4a2713aSLionel Sambuc     // basic.lval/6: An expression which holds a temporary object resulting
79*f4a2713aSLionel Sambuc     // from a cast to a nonreference type is an rvalue (this includes
80*f4a2713aSLionel Sambuc     // the explicit creation of an object using functional notation
81*f4a2713aSLionel Sambuc     struct IntClass
82*f4a2713aSLionel Sambuc     {
83*f4a2713aSLionel Sambuc         explicit IntClass(int = 0);
84*f4a2713aSLionel Sambuc         IntClass(char const*);
85*f4a2713aSLionel Sambuc         operator int() const;
86*f4a2713aSLionel Sambuc     };
87*f4a2713aSLionel Sambuc 
88*f4a2713aSLionel Sambuc     struct ConvertibleToIntClass
89*f4a2713aSLionel Sambuc     {
90*f4a2713aSLionel Sambuc         operator IntClass() const;
91*f4a2713aSLionel Sambuc     };
92*f4a2713aSLionel Sambuc 
93*f4a2713aSLionel Sambuc     ConvertibleToIntClass b;
94*f4a2713aSLionel Sambuc 
95*f4a2713aSLionel Sambuc     // Make sure even trivial conversions are not detected as lvalues
96*f4a2713aSLionel Sambuc     int intLvalue = 0;
97*f4a2713aSLionel Sambuc     ASSERT_RVALUE((int)intLvalue);
98*f4a2713aSLionel Sambuc     ASSERT_RVALUE((short)intLvalue);
99*f4a2713aSLionel Sambuc     ASSERT_RVALUE((long)intLvalue);
100*f4a2713aSLionel Sambuc 
101*f4a2713aSLionel Sambuc     // Same tests with function-call notation
102*f4a2713aSLionel Sambuc     ASSERT_RVALUE(int(intLvalue));
103*f4a2713aSLionel Sambuc     ASSERT_RVALUE(short(intLvalue));
104*f4a2713aSLionel Sambuc     ASSERT_RVALUE(long(intLvalue));
105*f4a2713aSLionel Sambuc 
106*f4a2713aSLionel Sambuc     char charLValue = 'x';
107*f4a2713aSLionel Sambuc     ASSERT_RVALUE((signed char)charLValue);
108*f4a2713aSLionel Sambuc     ASSERT_RVALUE((unsigned char)charLValue);
109*f4a2713aSLionel Sambuc 
110*f4a2713aSLionel Sambuc     ASSERT_RVALUE(static_cast<int>(IntClass()));
111*f4a2713aSLionel Sambuc     IntClass intClassLValue;
112*f4a2713aSLionel Sambuc     ASSERT_RVALUE(static_cast<int>(intClassLValue));
113*f4a2713aSLionel Sambuc     ASSERT_RVALUE(static_cast<IntClass>(ConvertibleToIntClass()));
114*f4a2713aSLionel Sambuc     ConvertibleToIntClass convertibleToIntClassLValue;
115*f4a2713aSLionel Sambuc     ASSERT_RVALUE(static_cast<IntClass>(convertibleToIntClassLValue));
116*f4a2713aSLionel Sambuc 
117*f4a2713aSLionel Sambuc 
118*f4a2713aSLionel Sambuc     typedef signed char signed_char;
119*f4a2713aSLionel Sambuc     typedef unsigned char unsigned_char;
120*f4a2713aSLionel Sambuc     ASSERT_RVALUE(signed_char(charLValue));
121*f4a2713aSLionel Sambuc     ASSERT_RVALUE(unsigned_char(charLValue));
122*f4a2713aSLionel Sambuc 
123*f4a2713aSLionel Sambuc     ASSERT_RVALUE(int(IntClass()));
124*f4a2713aSLionel Sambuc     ASSERT_RVALUE(int(intClassLValue));
125*f4a2713aSLionel Sambuc     ASSERT_RVALUE(IntClass(ConvertibleToIntClass()));
126*f4a2713aSLionel Sambuc     ASSERT_RVALUE(IntClass(convertibleToIntClassLValue));
127*f4a2713aSLionel Sambuc }
128*f4a2713aSLionel Sambuc 
129*f4a2713aSLionel Sambuc void conv_ptr_1()
130*f4a2713aSLionel Sambuc {
131*f4a2713aSLionel Sambuc     // conv.ptr/1: A null pointer constant is an integral constant
132*f4a2713aSLionel Sambuc     // expression (5.19) rvalue of integer type that evaluates to
133*f4a2713aSLionel Sambuc     // zero.
134*f4a2713aSLionel Sambuc     ASSERT_RVALUE(0);
135*f4a2713aSLionel Sambuc }
136*f4a2713aSLionel Sambuc 
137*f4a2713aSLionel Sambuc void expr_6()
138*f4a2713aSLionel Sambuc {
139*f4a2713aSLionel Sambuc     // expr/6: If an expression initially has the type "reference to T"
140*f4a2713aSLionel Sambuc     // (8.3.2, 8.5.3), ... the expression is an lvalue.
141*f4a2713aSLionel Sambuc     int x = 0;
142*f4a2713aSLionel Sambuc     int& referenceToInt = x;
143*f4a2713aSLionel Sambuc     ASSERT_LVALUE(referenceToInt);
144*f4a2713aSLionel Sambuc     ASSERT_LVALUE(ReturnIntReference());
145*f4a2713aSLionel Sambuc }
146*f4a2713aSLionel Sambuc 
147*f4a2713aSLionel Sambuc void expr_prim_2()
148*f4a2713aSLionel Sambuc {
149*f4a2713aSLionel Sambuc     // 5.1/2 A string literal is an lvalue; all other
150*f4a2713aSLionel Sambuc     // literals are rvalues.
151*f4a2713aSLionel Sambuc     ASSERT_LVALUE("foo");
152*f4a2713aSLionel Sambuc     ASSERT_RVALUE(1);
153*f4a2713aSLionel Sambuc     ASSERT_RVALUE(1.2);
154*f4a2713aSLionel Sambuc     ASSERT_RVALUE(10UL);
155*f4a2713aSLionel Sambuc }
156*f4a2713aSLionel Sambuc 
157*f4a2713aSLionel Sambuc void expr_prim_3()
158*f4a2713aSLionel Sambuc {
159*f4a2713aSLionel Sambuc     // 5.1/3: The keyword "this" names a pointer to the object for
160*f4a2713aSLionel Sambuc     // which a nonstatic member function (9.3.2) is invoked. ...The
161*f4a2713aSLionel Sambuc     // expression is an rvalue.
162*f4a2713aSLionel Sambuc     struct ThisTest
163*f4a2713aSLionel Sambuc     {
164*f4a2713aSLionel Sambuc         void f() { ASSERT_RVALUE(this); }
165*f4a2713aSLionel Sambuc     };
166*f4a2713aSLionel Sambuc }
167*f4a2713aSLionel Sambuc 
168*f4a2713aSLionel Sambuc extern int variable;
169*f4a2713aSLionel Sambuc void Function();
170*f4a2713aSLionel Sambuc 
171*f4a2713aSLionel Sambuc struct BaseClass
172*f4a2713aSLionel Sambuc {
173*f4a2713aSLionel Sambuc     virtual ~BaseClass();
174*f4a2713aSLionel Sambuc 
175*f4a2713aSLionel Sambuc     int BaseNonstaticMemberFunction();
176*f4a2713aSLionel Sambuc     static int BaseStaticMemberFunction();
177*f4a2713aSLionel Sambuc     int baseDataMember;
178*f4a2713aSLionel Sambuc };
179*f4a2713aSLionel Sambuc 
180*f4a2713aSLionel Sambuc struct Class : BaseClass
181*f4a2713aSLionel Sambuc {
182*f4a2713aSLionel Sambuc     static void function();
183*f4a2713aSLionel Sambuc     static int variable;
184*f4a2713aSLionel Sambuc 
185*f4a2713aSLionel Sambuc     template <class T>
186*f4a2713aSLionel Sambuc     struct NestedClassTemplate {};
187*f4a2713aSLionel Sambuc 
188*f4a2713aSLionel Sambuc     template <class T>
189*f4a2713aSLionel Sambuc     static int& NestedFuncTemplate() { return variable; }  // expected-note{{possible target for call}}
190*f4a2713aSLionel Sambuc 
191*f4a2713aSLionel Sambuc     template <class T>
192*f4a2713aSLionel Sambuc     int& NestedMemfunTemplate() { return variable; } // expected-note{{possible target for call}}
193*f4a2713aSLionel Sambuc 
194*f4a2713aSLionel Sambuc     int operator*() const;
195*f4a2713aSLionel Sambuc 
196*f4a2713aSLionel Sambuc     template <class T>
197*f4a2713aSLionel Sambuc     int operator+(T) const; // expected-note{{possible target for call}}
198*f4a2713aSLionel Sambuc 
199*f4a2713aSLionel Sambuc     int NonstaticMemberFunction();
200*f4a2713aSLionel Sambuc     static int StaticMemberFunction();
201*f4a2713aSLionel Sambuc     int dataMember;
202*f4a2713aSLionel Sambuc 
203*f4a2713aSLionel Sambuc     int& referenceDataMember;
204*f4a2713aSLionel Sambuc     static int& staticReferenceDataMember;
205*f4a2713aSLionel Sambuc     static int staticNonreferenceDataMember;
206*f4a2713aSLionel Sambuc 
207*f4a2713aSLionel Sambuc     enum Enum { Enumerator };
208*f4a2713aSLionel Sambuc 
209*f4a2713aSLionel Sambuc     operator long() const;
210*f4a2713aSLionel Sambuc 
211*f4a2713aSLionel Sambuc     Class();
212*f4a2713aSLionel Sambuc     Class(int,int);
213*f4a2713aSLionel Sambuc 
214*f4a2713aSLionel Sambuc     void expr_prim_4()
215*f4a2713aSLionel Sambuc     {
216*f4a2713aSLionel Sambuc         // 5.1/4: The operator :: followed by an identifier, a
217*f4a2713aSLionel Sambuc         // qualified-id, or an operator-function-id is a primary-
218*f4a2713aSLionel Sambuc         // expression. ...The result is an lvalue if the entity is
219*f4a2713aSLionel Sambuc         // a function or variable.
220*f4a2713aSLionel Sambuc         ASSERT_LVALUE(::Function);         // identifier: function
221*f4a2713aSLionel Sambuc         ASSERT_LVALUE(::variable);         // identifier: variable
222*f4a2713aSLionel Sambuc 
223*f4a2713aSLionel Sambuc         // the only qualified-id form that can start without "::" (and thus
224*f4a2713aSLionel Sambuc         // be legal after "::" ) is
225*f4a2713aSLionel Sambuc         //
226*f4a2713aSLionel Sambuc         // ::<sub>opt</sub> nested-name-specifier template<sub>opt</sub> unqualified-id
227*f4a2713aSLionel Sambuc         ASSERT_LVALUE(::Class::function);  // qualified-id: function
228*f4a2713aSLionel Sambuc         ASSERT_LVALUE(::Class::variable);  // qualified-id: variable
229*f4a2713aSLionel Sambuc 
230*f4a2713aSLionel Sambuc         // The standard doesn't give a clear answer about whether these
231*f4a2713aSLionel Sambuc         // should really be lvalues or rvalues without some surrounding
232*f4a2713aSLionel Sambuc         // context that forces them to be interpreted as naming a
233*f4a2713aSLionel Sambuc         // particular function template specialization (that situation
234*f4a2713aSLionel Sambuc         // doesn't come up in legal pure C++ programs). This language
235*f4a2713aSLionel Sambuc         // extension simply rejects them as requiring additional context
236*f4a2713aSLionel Sambuc         __is_lvalue_expr(::Class::NestedFuncTemplate);    // qualified-id: template \
237*f4a2713aSLionel Sambuc         // expected-error{{reference to overloaded function could not be resolved; did you mean to call it?}}
238*f4a2713aSLionel Sambuc 
239*f4a2713aSLionel Sambuc         __is_lvalue_expr(::Class::NestedMemfunTemplate);  // qualified-id: template \
240*f4a2713aSLionel Sambuc         // expected-error{{reference to non-static member function must be called}}
241*f4a2713aSLionel Sambuc 
242*f4a2713aSLionel Sambuc         __is_lvalue_expr(::Class::operator+);             // operator-function-id: template \
243*f4a2713aSLionel Sambuc         // expected-error{{reference to non-static member function must be called}}
244*f4a2713aSLionel Sambuc 
245*f4a2713aSLionel Sambuc         //ASSERT_RVALUE(::Class::operator*);         // operator-function-id: member function
246*f4a2713aSLionel Sambuc     }
247*f4a2713aSLionel Sambuc 
248*f4a2713aSLionel Sambuc     void expr_prim_7()
249*f4a2713aSLionel Sambuc     {
250*f4a2713aSLionel Sambuc         // expr.prim/7 An identifier is an id-expression provided it has been
251*f4a2713aSLionel Sambuc         // suitably declared (clause 7). [Note: ... ] The type of the
252*f4a2713aSLionel Sambuc         // expression is the type of the identifier. The result is the
253*f4a2713aSLionel Sambuc         // entity denoted by the identifier. The result is an lvalue if
254*f4a2713aSLionel Sambuc         // the entity is a function, variable, or data member... (cont'd)
255*f4a2713aSLionel Sambuc         ASSERT_LVALUE(Function);        // identifier: function
256*f4a2713aSLionel Sambuc         ASSERT_LVALUE(StaticMemberFunction);        // identifier: function
257*f4a2713aSLionel Sambuc         ASSERT_LVALUE(variable);        // identifier: variable
258*f4a2713aSLionel Sambuc         ASSERT_LVALUE(dataMember);      // identifier: data member
259*f4a2713aSLionel Sambuc         //ASSERT_RVALUE(NonstaticMemberFunction); // identifier: member function
260*f4a2713aSLionel Sambuc 
261*f4a2713aSLionel Sambuc         // (cont'd)...A nested-name-specifier that names a class,
262*f4a2713aSLionel Sambuc         // optionally followed by the keyword template (14.2), and then
263*f4a2713aSLionel Sambuc         // followed by the name of a member of either that class (9.2) or
264*f4a2713aSLionel Sambuc         // one of its base classes... is a qualified-id... The result is
265*f4a2713aSLionel Sambuc         // the member. The type of the result is the type of the
266*f4a2713aSLionel Sambuc         // member. The result is an lvalue if the member is a static
267*f4a2713aSLionel Sambuc         // member function or a data member.
268*f4a2713aSLionel Sambuc         ASSERT_LVALUE(Class::dataMember);
269*f4a2713aSLionel Sambuc         ASSERT_LVALUE(Class::StaticMemberFunction);
270*f4a2713aSLionel Sambuc         //ASSERT_RVALUE(Class::NonstaticMemberFunction); // identifier: member function
271*f4a2713aSLionel Sambuc 
272*f4a2713aSLionel Sambuc         ASSERT_LVALUE(Class::baseDataMember);
273*f4a2713aSLionel Sambuc         ASSERT_LVALUE(Class::BaseStaticMemberFunction);
274*f4a2713aSLionel Sambuc         //ASSERT_RVALUE(Class::BaseNonstaticMemberFunction); // identifier: member function
275*f4a2713aSLionel Sambuc     }
276*f4a2713aSLionel Sambuc };
277*f4a2713aSLionel Sambuc 
278*f4a2713aSLionel Sambuc void expr_call_10()
279*f4a2713aSLionel Sambuc {
280*f4a2713aSLionel Sambuc     // expr.call/10: A function call is an lvalue if and only if the
281*f4a2713aSLionel Sambuc     // result type is a reference.  This statement is partially
282*f4a2713aSLionel Sambuc     // redundant with basic.lval/5
283*f4a2713aSLionel Sambuc     basic_lval_5();
284*f4a2713aSLionel Sambuc 
285*f4a2713aSLionel Sambuc     ASSERT_LVALUE(ReturnIntReference());
286*f4a2713aSLionel Sambuc     ASSERT_LVALUE(ReturnEnumReference());
287*f4a2713aSLionel Sambuc }
288*f4a2713aSLionel Sambuc 
289*f4a2713aSLionel Sambuc namespace Namespace
290*f4a2713aSLionel Sambuc {
291*f4a2713aSLionel Sambuc   int x;
292*f4a2713aSLionel Sambuc   void function();
293*f4a2713aSLionel Sambuc }
294*f4a2713aSLionel Sambuc 
295*f4a2713aSLionel Sambuc void expr_prim_8()
296*f4a2713aSLionel Sambuc {
297*f4a2713aSLionel Sambuc     // expr.prim/8 A nested-name-specifier that names a namespace
298*f4a2713aSLionel Sambuc     // (7.3), followed by the name of a member of that namespace (or
299*f4a2713aSLionel Sambuc     // the name of a member of a namespace made visible by a
300*f4a2713aSLionel Sambuc     // using-directive ) is a qualified-id; 3.4.3.2 describes name
301*f4a2713aSLionel Sambuc     // lookup for namespace members that appear in qualified-ids. The
302*f4a2713aSLionel Sambuc     // result is the member. The type of the result is the type of the
303*f4a2713aSLionel Sambuc     // member. The result is an lvalue if the member is a function or
304*f4a2713aSLionel Sambuc     // a variable.
305*f4a2713aSLionel Sambuc     ASSERT_LVALUE(Namespace::x);
306*f4a2713aSLionel Sambuc     ASSERT_LVALUE(Namespace::function);
307*f4a2713aSLionel Sambuc }
308*f4a2713aSLionel Sambuc 
309*f4a2713aSLionel Sambuc void expr_sub_1(int* pointer)
310*f4a2713aSLionel Sambuc {
311*f4a2713aSLionel Sambuc     // expr.sub/1 A postfix expression followed by an expression in
312*f4a2713aSLionel Sambuc     // square brackets is a postfix expression. One of the expressions
313*f4a2713aSLionel Sambuc     // shall have the type "pointer to T" and the other shall have
314*f4a2713aSLionel Sambuc     // enumeration or integral type. The result is an lvalue of type
315*f4a2713aSLionel Sambuc     // "T."
316*f4a2713aSLionel Sambuc     ASSERT_LVALUE(pointer[1]);
317*f4a2713aSLionel Sambuc 
318*f4a2713aSLionel Sambuc     // The expression E1[E2] is identical (by definition) to *((E1)+(E2)).
319*f4a2713aSLionel Sambuc     ASSERT_LVALUE(*(pointer+1));
320*f4a2713aSLionel Sambuc }
321*f4a2713aSLionel Sambuc 
322*f4a2713aSLionel Sambuc void expr_type_conv_1()
323*f4a2713aSLionel Sambuc {
324*f4a2713aSLionel Sambuc     // expr.type.conv/1 A simple-type-specifier (7.1.5) followed by a
325*f4a2713aSLionel Sambuc     // parenthesized expression-list constructs a value of the specified
326*f4a2713aSLionel Sambuc     // type given the expression list. ... If the expression list
327*f4a2713aSLionel Sambuc     // specifies more than a single value, the type shall be a class with
328*f4a2713aSLionel Sambuc     // a suitably declared constructor (8.5, 12.1), and the expression
329*f4a2713aSLionel Sambuc     // T(x1, x2, ...) is equivalent in effect to the declaration T t(x1,
330*f4a2713aSLionel Sambuc     // x2, ...); for some invented temporary variable t, with the result
331*f4a2713aSLionel Sambuc     // being the value of t as an rvalue.
332*f4a2713aSLionel Sambuc     ASSERT_RVALUE(Class(2,2));
333*f4a2713aSLionel Sambuc }
334*f4a2713aSLionel Sambuc 
335*f4a2713aSLionel Sambuc void expr_type_conv_2()
336*f4a2713aSLionel Sambuc {
337*f4a2713aSLionel Sambuc     // expr.type.conv/2 The expression T(), where T is a
338*f4a2713aSLionel Sambuc     // simple-type-specifier (7.1.5.2) for a non-array complete object
339*f4a2713aSLionel Sambuc     // type or the (possibly cv-qualified) void type, creates an
340*f4a2713aSLionel Sambuc     // rvalue of the specified type,
341*f4a2713aSLionel Sambuc     ASSERT_RVALUE(int());
342*f4a2713aSLionel Sambuc     ASSERT_RVALUE(Class());
343*f4a2713aSLionel Sambuc     ASSERT_RVALUE(void());
344*f4a2713aSLionel Sambuc }
345*f4a2713aSLionel Sambuc 
346*f4a2713aSLionel Sambuc 
347*f4a2713aSLionel Sambuc void expr_ref_4()
348*f4a2713aSLionel Sambuc {
349*f4a2713aSLionel Sambuc     // Applies to expressions of the form E1.E2
350*f4a2713aSLionel Sambuc 
351*f4a2713aSLionel Sambuc     // If E2 is declared to have type "reference to T", then E1.E2 is
352*f4a2713aSLionel Sambuc     // an lvalue;.... Otherwise, one of the following rules applies.
353*f4a2713aSLionel Sambuc     ASSERT_LVALUE(Class().staticReferenceDataMember);
354*f4a2713aSLionel Sambuc     ASSERT_LVALUE(Class().referenceDataMember);
355*f4a2713aSLionel Sambuc 
356*f4a2713aSLionel Sambuc     // - If E2 is a static data member, and the type of E2 is T, then
357*f4a2713aSLionel Sambuc     // E1.E2 is an lvalue; ...
358*f4a2713aSLionel Sambuc     ASSERT_LVALUE(Class().staticNonreferenceDataMember);
359*f4a2713aSLionel Sambuc     ASSERT_LVALUE(Class().staticReferenceDataMember);
360*f4a2713aSLionel Sambuc 
361*f4a2713aSLionel Sambuc 
362*f4a2713aSLionel Sambuc     // - If E2 is a non-static data member, ... If E1 is an lvalue,
363*f4a2713aSLionel Sambuc     // then E1.E2 is an lvalue...
364*f4a2713aSLionel Sambuc     Class lvalue;
365*f4a2713aSLionel Sambuc     ASSERT_LVALUE(lvalue.dataMember);
366*f4a2713aSLionel Sambuc     ASSERT_RVALUE(Class().dataMember);
367*f4a2713aSLionel Sambuc 
368*f4a2713aSLionel Sambuc     // - If E1.E2 refers to a static member function, ... then E1.E2
369*f4a2713aSLionel Sambuc     // is an lvalue
370*f4a2713aSLionel Sambuc     ASSERT_LVALUE(Class().StaticMemberFunction);
371*f4a2713aSLionel Sambuc 
372*f4a2713aSLionel Sambuc     // - Otherwise, if E1.E2 refers to a non-static member function,
373*f4a2713aSLionel Sambuc     // then E1.E2 is not an lvalue.
374*f4a2713aSLionel Sambuc     //ASSERT_RVALUE(Class().NonstaticMemberFunction);
375*f4a2713aSLionel Sambuc 
376*f4a2713aSLionel Sambuc     // - If E2 is a member enumerator, and the type of E2 is T, the
377*f4a2713aSLionel Sambuc     // expression E1.E2 is not an lvalue. The type of E1.E2 is T.
378*f4a2713aSLionel Sambuc     ASSERT_RVALUE(Class().Enumerator);
379*f4a2713aSLionel Sambuc     ASSERT_RVALUE(lvalue.Enumerator);
380*f4a2713aSLionel Sambuc }
381*f4a2713aSLionel Sambuc 
382*f4a2713aSLionel Sambuc 
383*f4a2713aSLionel Sambuc void expr_post_incr_1(int x)
384*f4a2713aSLionel Sambuc {
385*f4a2713aSLionel Sambuc     // expr.post.incr/1 The value obtained by applying a postfix ++ is
386*f4a2713aSLionel Sambuc     // the value that the operand had before applying the
387*f4a2713aSLionel Sambuc     // operator... The result is an rvalue.
388*f4a2713aSLionel Sambuc     ASSERT_RVALUE(x++);
389*f4a2713aSLionel Sambuc }
390*f4a2713aSLionel Sambuc 
391*f4a2713aSLionel Sambuc void expr_dynamic_cast_2()
392*f4a2713aSLionel Sambuc {
393*f4a2713aSLionel Sambuc     // expr.dynamic.cast/2: If T is a pointer type, v shall be an
394*f4a2713aSLionel Sambuc     // rvalue of a pointer to complete class type, and the result is
395*f4a2713aSLionel Sambuc     // an rvalue of type T.
396*f4a2713aSLionel Sambuc     Class instance;
397*f4a2713aSLionel Sambuc     ASSERT_RVALUE(dynamic_cast<Class*>(&instance));
398*f4a2713aSLionel Sambuc 
399*f4a2713aSLionel Sambuc     // If T is a reference type, v shall be an
400*f4a2713aSLionel Sambuc     // lvalue of a complete class type, and the result is an lvalue of
401*f4a2713aSLionel Sambuc     // the type referred to by T.
402*f4a2713aSLionel Sambuc     ASSERT_LVALUE(dynamic_cast<Class&>(instance));
403*f4a2713aSLionel Sambuc }
404*f4a2713aSLionel Sambuc 
405*f4a2713aSLionel Sambuc void expr_dynamic_cast_5()
406*f4a2713aSLionel Sambuc {
407*f4a2713aSLionel Sambuc     // expr.dynamic.cast/5: If T is "reference to cv1 B" and v has type
408*f4a2713aSLionel Sambuc     // "cv2 D" such that B is a base class of D, the result is an
409*f4a2713aSLionel Sambuc     // lvalue for the unique B sub-object of the D object referred
410*f4a2713aSLionel Sambuc     // to by v.
411*f4a2713aSLionel Sambuc     typedef BaseClass B;
412*f4a2713aSLionel Sambuc     typedef Class D;
413*f4a2713aSLionel Sambuc     D object;
414*f4a2713aSLionel Sambuc     ASSERT_LVALUE(dynamic_cast<B&>(object));
415*f4a2713aSLionel Sambuc }
416*f4a2713aSLionel Sambuc 
417*f4a2713aSLionel Sambuc // expr.dynamic.cast/8: The run-time check logically executes as follows:
418*f4a2713aSLionel Sambuc //
419*f4a2713aSLionel Sambuc // - If, in the most derived object pointed (referred) to by v, v
420*f4a2713aSLionel Sambuc // points (refers) to a public base class subobject of a T object, and
421*f4a2713aSLionel Sambuc // if only one object of type T is derived from the sub-object pointed
422*f4a2713aSLionel Sambuc // (referred) to by v, the result is a pointer (an lvalue referring)
423*f4a2713aSLionel Sambuc // to that T object.
424*f4a2713aSLionel Sambuc //
425*f4a2713aSLionel Sambuc // - Otherwise, if v points (refers) to a public base class sub-object
426*f4a2713aSLionel Sambuc // of the most derived object, and the type of the most derived object
427*f4a2713aSLionel Sambuc // has a base class, of type T, that is unambiguous and public, the
428*f4a2713aSLionel Sambuc // result is a pointer (an lvalue referring) to the T sub-object of
429*f4a2713aSLionel Sambuc // the most derived object.
430*f4a2713aSLionel Sambuc //
431*f4a2713aSLionel Sambuc // The mention of "lvalue" in the text above appears to be a
432*f4a2713aSLionel Sambuc // defect that is being corrected by the response to UK65 (see
433*f4a2713aSLionel Sambuc // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2841.html).
434*f4a2713aSLionel Sambuc 
435*f4a2713aSLionel Sambuc #if 0
436*f4a2713aSLionel Sambuc void expr_typeid_1()
437*f4a2713aSLionel Sambuc {
438*f4a2713aSLionel Sambuc     // expr.typeid/1: The result of a typeid expression is an lvalue...
439*f4a2713aSLionel Sambuc     ASSERT_LVALUE(typeid(1));
440*f4a2713aSLionel Sambuc }
441*f4a2713aSLionel Sambuc #endif
442*f4a2713aSLionel Sambuc 
443*f4a2713aSLionel Sambuc void expr_static_cast_1(int x)
444*f4a2713aSLionel Sambuc {
445*f4a2713aSLionel Sambuc     // expr.static.cast/1: The result of the expression
446*f4a2713aSLionel Sambuc     // static_cast<T>(v) is the result of converting the expression v
447*f4a2713aSLionel Sambuc     // to type T. If T is a reference type, the result is an lvalue;
448*f4a2713aSLionel Sambuc     // otherwise, the result is an rvalue.
449*f4a2713aSLionel Sambuc     ASSERT_LVALUE(static_cast<int&>(x));
450*f4a2713aSLionel Sambuc     ASSERT_RVALUE(static_cast<int>(x));
451*f4a2713aSLionel Sambuc }
452*f4a2713aSLionel Sambuc 
453*f4a2713aSLionel Sambuc void expr_reinterpret_cast_1()
454*f4a2713aSLionel Sambuc {
455*f4a2713aSLionel Sambuc     // expr.reinterpret.cast/1: The result of the expression
456*f4a2713aSLionel Sambuc     // reinterpret_cast<T>(v) is the result of converting the
457*f4a2713aSLionel Sambuc     // expression v to type T. If T is a reference type, the result is
458*f4a2713aSLionel Sambuc     // an lvalue; otherwise, the result is an rvalue
459*f4a2713aSLionel Sambuc     ASSERT_RVALUE(reinterpret_cast<int*>(0));
460*f4a2713aSLionel Sambuc     char const v = 0;
461*f4a2713aSLionel Sambuc     ASSERT_LVALUE(reinterpret_cast<char const&>(v));
462*f4a2713aSLionel Sambuc }
463*f4a2713aSLionel Sambuc 
464*f4a2713aSLionel Sambuc void expr_unary_op_1(int* pointer, struct incomplete* pointerToIncompleteType)
465*f4a2713aSLionel Sambuc {
466*f4a2713aSLionel Sambuc     // expr.unary.op/1: The unary * operator performs indirection: the
467*f4a2713aSLionel Sambuc     // expression to which it is applied shall be a pointer to an
468*f4a2713aSLionel Sambuc     // object type, or a pointer to a function type and the result is
469*f4a2713aSLionel Sambuc     // an lvalue referring to the object or function to which the
470*f4a2713aSLionel Sambuc     // expression points.
471*f4a2713aSLionel Sambuc     ASSERT_LVALUE(*pointer);
472*f4a2713aSLionel Sambuc     ASSERT_LVALUE(*Function);
473*f4a2713aSLionel Sambuc 
474*f4a2713aSLionel Sambuc     // [Note: a pointer to an incomplete type
475*f4a2713aSLionel Sambuc     // (other than cv void ) can be dereferenced. ]
476*f4a2713aSLionel Sambuc     ASSERT_LVALUE(*pointerToIncompleteType);
477*f4a2713aSLionel Sambuc }
478*f4a2713aSLionel Sambuc 
479*f4a2713aSLionel Sambuc void expr_pre_incr_1(int operand)
480*f4a2713aSLionel Sambuc {
481*f4a2713aSLionel Sambuc     // expr.pre.incr/1: The operand of prefix ++ ... shall be a
482*f4a2713aSLionel Sambuc     // modifiable lvalue.... The value is the new value of the
483*f4a2713aSLionel Sambuc     // operand; it is an lvalue.
484*f4a2713aSLionel Sambuc     ASSERT_LVALUE(++operand);
485*f4a2713aSLionel Sambuc }
486*f4a2713aSLionel Sambuc 
487*f4a2713aSLionel Sambuc void expr_cast_1(int x)
488*f4a2713aSLionel Sambuc {
489*f4a2713aSLionel Sambuc     // expr.cast/1: The result of the expression (T) cast-expression
490*f4a2713aSLionel Sambuc     // is of type T. The result is an lvalue if T is a reference type,
491*f4a2713aSLionel Sambuc     // otherwise the result is an rvalue.
492*f4a2713aSLionel Sambuc     ASSERT_LVALUE((void(&)())expr_cast_1);
493*f4a2713aSLionel Sambuc     ASSERT_LVALUE((int&)x);
494*f4a2713aSLionel Sambuc     ASSERT_RVALUE((void(*)())expr_cast_1);
495*f4a2713aSLionel Sambuc     ASSERT_RVALUE((int)x);
496*f4a2713aSLionel Sambuc }
497*f4a2713aSLionel Sambuc 
498*f4a2713aSLionel Sambuc void expr_mptr_oper()
499*f4a2713aSLionel Sambuc {
500*f4a2713aSLionel Sambuc     // expr.mptr.oper/6: The result of a .* expression is an lvalue
501*f4a2713aSLionel Sambuc     // only if its first operand is an lvalue and its second operand
502*f4a2713aSLionel Sambuc     // is a pointer to data member... (cont'd)
503*f4a2713aSLionel Sambuc     typedef Class MakeRValue;
504*f4a2713aSLionel Sambuc     ASSERT_RVALUE(MakeRValue().*(&Class::dataMember));
505*f4a2713aSLionel Sambuc     //ASSERT_RVALUE(MakeRValue().*(&Class::NonstaticMemberFunction));
506*f4a2713aSLionel Sambuc     Class lvalue;
507*f4a2713aSLionel Sambuc     ASSERT_LVALUE(lvalue.*(&Class::dataMember));
508*f4a2713aSLionel Sambuc     //ASSERT_RVALUE(lvalue.*(&Class::NonstaticMemberFunction));
509*f4a2713aSLionel Sambuc 
510*f4a2713aSLionel Sambuc     // (cont'd)...The result of an ->* expression is an lvalue only
511*f4a2713aSLionel Sambuc     // if its second operand is a pointer to data member. If the
512*f4a2713aSLionel Sambuc     // second operand is the null pointer to member value (4.11), the
513*f4a2713aSLionel Sambuc     // behavior is undefined.
514*f4a2713aSLionel Sambuc     ASSERT_LVALUE((&lvalue)->*(&Class::dataMember));
515*f4a2713aSLionel Sambuc     //ASSERT_RVALUE((&lvalue)->*(&Class::NonstaticMemberFunction));
516*f4a2713aSLionel Sambuc }
517*f4a2713aSLionel Sambuc 
518*f4a2713aSLionel Sambuc void expr_cond(bool cond)
519*f4a2713aSLionel Sambuc {
520*f4a2713aSLionel Sambuc     // 5.16 Conditional operator [expr.cond]
521*f4a2713aSLionel Sambuc     //
522*f4a2713aSLionel Sambuc     // 2 If either the second or the third operand has type (possibly
523*f4a2713aSLionel Sambuc     // cv-qualified) void, then the lvalue-to-rvalue (4.1),
524*f4a2713aSLionel Sambuc     // array-to-pointer (4.2), and function-to-pointer (4.3) standard
525*f4a2713aSLionel Sambuc     // conversions are performed on the second and third operands, and one
526*f4a2713aSLionel Sambuc     // of the following shall hold:
527*f4a2713aSLionel Sambuc     //
528*f4a2713aSLionel Sambuc     // - The second or the third operand (but not both) is a
529*f4a2713aSLionel Sambuc     // throw-expression (15.1); the result is of the type of the other and
530*f4a2713aSLionel Sambuc     // is an rvalue.
531*f4a2713aSLionel Sambuc 
532*f4a2713aSLionel Sambuc     Class classLvalue;
533*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? throw 1 : (void)0);
534*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? (void)0 : throw 1);
535*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? throw 1 : classLvalue);
536*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? classLvalue : throw 1);
537*f4a2713aSLionel Sambuc 
538*f4a2713aSLionel Sambuc     // - Both the second and the third operands have type void; the result
539*f4a2713aSLionel Sambuc     // is of type void and is an rvalue. [Note: this includes the case
540*f4a2713aSLionel Sambuc     // where both operands are throw-expressions. ]
541*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? (void)1 : (void)0);
542*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? throw 1 : throw 0);
543*f4a2713aSLionel Sambuc 
544*f4a2713aSLionel Sambuc     // expr.cond/4: If the second and third operands are lvalues and
545*f4a2713aSLionel Sambuc     // have the same type, the result is of that type and is an
546*f4a2713aSLionel Sambuc     // lvalue.
547*f4a2713aSLionel Sambuc     ASSERT_LVALUE(cond ? classLvalue : classLvalue);
548*f4a2713aSLionel Sambuc     int intLvalue = 0;
549*f4a2713aSLionel Sambuc     ASSERT_LVALUE(cond ? intLvalue : intLvalue);
550*f4a2713aSLionel Sambuc 
551*f4a2713aSLionel Sambuc     // expr.cond/5:Otherwise, the result is an rvalue.
552*f4a2713aSLionel Sambuc     typedef Class MakeRValue;
553*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? MakeRValue() : classLvalue);
554*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? classLvalue : MakeRValue());
555*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? MakeRValue() : MakeRValue());
556*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? classLvalue : intLvalue);
557*f4a2713aSLionel Sambuc     ASSERT_RVALUE(cond ? intLvalue : int());
558*f4a2713aSLionel Sambuc }
559*f4a2713aSLionel Sambuc 
560*f4a2713aSLionel Sambuc void expr_ass_1(int x)
561*f4a2713aSLionel Sambuc {
562*f4a2713aSLionel Sambuc     // expr.ass/1: There are several assignment operators, all of
563*f4a2713aSLionel Sambuc     // which group right-to-left. All require a modifiable lvalue as
564*f4a2713aSLionel Sambuc     // their left operand, and the type of an assignment expression is
565*f4a2713aSLionel Sambuc     // that of its left operand. The result of the assignment
566*f4a2713aSLionel Sambuc     // operation is the value stored in the left operand after the
567*f4a2713aSLionel Sambuc     // assignment has taken place; the result is an lvalue.
568*f4a2713aSLionel Sambuc     ASSERT_LVALUE(x = 1);
569*f4a2713aSLionel Sambuc     ASSERT_LVALUE(x += 1);
570*f4a2713aSLionel Sambuc     ASSERT_LVALUE(x -= 1);
571*f4a2713aSLionel Sambuc     ASSERT_LVALUE(x *= 1);
572*f4a2713aSLionel Sambuc     ASSERT_LVALUE(x /= 1);
573*f4a2713aSLionel Sambuc     ASSERT_LVALUE(x %= 1);
574*f4a2713aSLionel Sambuc     ASSERT_LVALUE(x ^= 1);
575*f4a2713aSLionel Sambuc     ASSERT_LVALUE(x &= 1);
576*f4a2713aSLionel Sambuc     ASSERT_LVALUE(x |= 1);
577*f4a2713aSLionel Sambuc }
578*f4a2713aSLionel Sambuc 
579*f4a2713aSLionel Sambuc void expr_comma(int x)
580*f4a2713aSLionel Sambuc {
581*f4a2713aSLionel Sambuc     // expr.comma: A pair of expressions separated by a comma is
582*f4a2713aSLionel Sambuc     // evaluated left-to-right and the value of the left expression is
583*f4a2713aSLionel Sambuc     // discarded... result is an lvalue if its right operand is.
584*f4a2713aSLionel Sambuc 
585*f4a2713aSLionel Sambuc     // Can't use the ASSERT_XXXX macros without adding parens around
586*f4a2713aSLionel Sambuc     // the comma expression.
587*f4a2713aSLionel Sambuc     static_assert(__is_lvalue_expr(x,x), "expected an lvalue");
588*f4a2713aSLionel Sambuc     static_assert(__is_rvalue_expr(x,1), "expected an rvalue");
589*f4a2713aSLionel Sambuc     static_assert(__is_lvalue_expr(1,x), "expected an lvalue");
590*f4a2713aSLionel Sambuc     static_assert(__is_rvalue_expr(1,1), "expected an rvalue");
591*f4a2713aSLionel Sambuc }
592*f4a2713aSLionel Sambuc 
593*f4a2713aSLionel Sambuc #if 0
594*f4a2713aSLionel Sambuc template<typename T> void f();
595*f4a2713aSLionel Sambuc 
596*f4a2713aSLionel Sambuc // FIXME These currently fail
597*f4a2713aSLionel Sambuc void expr_fun_lvalue()
598*f4a2713aSLionel Sambuc {
599*f4a2713aSLionel Sambuc   ASSERT_LVALUE(&f<int>);
600*f4a2713aSLionel Sambuc }
601*f4a2713aSLionel Sambuc 
602*f4a2713aSLionel Sambuc void expr_fun_rvalue()
603*f4a2713aSLionel Sambuc {
604*f4a2713aSLionel Sambuc   ASSERT_RVALUE(f<int>);
605*f4a2713aSLionel Sambuc }
606*f4a2713aSLionel Sambuc #endif
607*f4a2713aSLionel Sambuc 
608*f4a2713aSLionel Sambuc template <int NonTypeNonReferenceParameter, int& NonTypeReferenceParameter>
609*f4a2713aSLionel Sambuc void check_temp_param_6()
610*f4a2713aSLionel Sambuc {
611*f4a2713aSLionel Sambuc     ASSERT_RVALUE(NonTypeNonReferenceParameter);
612*f4a2713aSLionel Sambuc     ASSERT_LVALUE(NonTypeReferenceParameter);
613*f4a2713aSLionel Sambuc }
614*f4a2713aSLionel Sambuc 
615*f4a2713aSLionel Sambuc int AnInt = 0;
616*f4a2713aSLionel Sambuc 
617*f4a2713aSLionel Sambuc void temp_param_6()
618*f4a2713aSLionel Sambuc {
619*f4a2713aSLionel Sambuc     check_temp_param_6<3,AnInt>();
620*f4a2713aSLionel Sambuc }
621