xref: /minix3/external/bsd/llvm/dist/clang/test/SemaCXX/expression-traits.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
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