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