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