expression-traits.cpp revision 552622067dc45013d240f73952fece703f5e63bd
1552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// RUN: %clang_cc1 -fsyntax-only -verify -fcxx-exceptions %s
2552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
3552622067dc45013d240f73952fece703f5e63bdJohn Wiegley//
4552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// Tests for "expression traits" intrinsics such as __is_lvalue_expr.
5552622067dc45013d240f73952fece703f5e63bdJohn Wiegley//
6552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// For the time being, these tests are written against the 2003 C++
7552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// standard (ISO/IEC 14882:2003 -- see draft at
8552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2001/n1316/).
9552622067dc45013d240f73952fece703f5e63bdJohn Wiegley//
10552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// C++0x has its own, more-refined, idea of lvalues and rvalues.
11552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// If/when we need to support those, we'll need to track both
12552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// standard documents.
13552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
14552622067dc45013d240f73952fece703f5e63bdJohn Wiegley#if !__has_feature(cxx_static_assert)
15552622067dc45013d240f73952fece703f5e63bdJohn Wiegley# define CONCAT_(X_, Y_) CONCAT1_(X_, Y_)
16552622067dc45013d240f73952fece703f5e63bdJohn Wiegley# define CONCAT1_(X_, Y_) X_ ## Y_
17552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
18552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// This emulation can be used multiple times on one line (and thus in
19552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// a macro), except at class scope
20552622067dc45013d240f73952fece703f5e63bdJohn Wiegley# define static_assert(b_, m_) \
21552622067dc45013d240f73952fece703f5e63bdJohn Wiegley  typedef int CONCAT_(sa_, __LINE__)[b_ ? 1 : -1]
22552622067dc45013d240f73952fece703f5e63bdJohn Wiegley#endif
23552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
24552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// Tests are broken down according to section of the C++03 standard
25552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// (ISO/IEC 14882:2003(E))
26552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
27552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// Assertion macros encoding the following two paragraphs
28552622067dc45013d240f73952fece703f5e63bdJohn Wiegley//
29552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// basic.lval/1 Every expression is either an lvalue or an rvalue.
30552622067dc45013d240f73952fece703f5e63bdJohn Wiegley//
31552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// expr.prim/5 A parenthesized expression is a primary expression whose type
32552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// and value are identical to those of the enclosed expression. The
33552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// presence of parentheses does not affect whether the expression is
34552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// an lvalue.
35552622067dc45013d240f73952fece703f5e63bdJohn Wiegley//
36552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// Note: these asserts cannot be made at class scope in C++03.  Put
37552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// them in a member function instead.
38552622067dc45013d240f73952fece703f5e63bdJohn Wiegley#define ASSERT_LVALUE(expr)                                             \
39552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(__is_lvalue_expr(expr), "should be an lvalue");       \
40552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(__is_lvalue_expr((expr)),                             \
41552622067dc45013d240f73952fece703f5e63bdJohn Wiegley                  "the presence of parentheses should have"             \
42552622067dc45013d240f73952fece703f5e63bdJohn Wiegley                  " no effect on lvalueness (expr.prim/5)");            \
43552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(!__is_rvalue_expr(expr), "should be an lvalue");      \
44552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(!__is_rvalue_expr((expr)),                            \
45552622067dc45013d240f73952fece703f5e63bdJohn Wiegley                  "the presence of parentheses should have"             \
46552622067dc45013d240f73952fece703f5e63bdJohn Wiegley                  " no effect on lvalueness (expr.prim/5)")
47552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
48552622067dc45013d240f73952fece703f5e63bdJohn Wiegley#define ASSERT_RVALUE(expr);                                            \
49552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(__is_rvalue_expr(expr), "should be an rvalue");       \
50552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(__is_rvalue_expr((expr)),                             \
51552622067dc45013d240f73952fece703f5e63bdJohn Wiegley                  "the presence of parentheses should have"             \
52552622067dc45013d240f73952fece703f5e63bdJohn Wiegley                  " no effect on lvalueness (expr.prim/5)");            \
53552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(!__is_lvalue_expr(expr), "should be an rvalue");      \
54552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(!__is_lvalue_expr((expr)),                            \
55552622067dc45013d240f73952fece703f5e63bdJohn Wiegley                  "the presence of parentheses should have"             \
56552622067dc45013d240f73952fece703f5e63bdJohn Wiegley                  " no effect on lvalueness (expr.prim/5)")
57552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
58552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyenum Enum { Enumerator };
59552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
60552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyint ReturnInt();
61552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid ReturnVoid();
62552622067dc45013d240f73952fece703f5e63bdJohn WiegleyEnum ReturnEnum();
63552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
64552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid basic_lval_5()
65552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
66552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // basic.lval/5: The result of calling a function that does not return
67552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // a reference is an rvalue.
68552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(ReturnInt());
69552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(ReturnVoid());
70552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(ReturnEnum());
71552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
72552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
73552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyint& ReturnIntReference();
74552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyextern Enum& ReturnEnumReference();
75552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
76552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid basic_lval_6()
77552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
78552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // basic.lval/6: An expression which holds a temporary object resulting
79552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // from a cast to a nonreference type is an rvalue (this includes
80552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // the explicit creation of an object using functional notation
81552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    struct IntClass
82552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    {
83552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        explicit IntClass(int = 0);
84552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        IntClass(char const*);
85552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        operator int() const;
86552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    };
87552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
88552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    struct ConvertibleToIntClass
89552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    {
90552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        operator IntClass() const;
91552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    };
92552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
93552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ConvertibleToIntClass b;
94552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
95552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // Make sure even trivial conversions are not detected as lvalues
96552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int intLvalue = 0;
97552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE((int)intLvalue);
98552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE((short)intLvalue);
99552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE((long)intLvalue);
100552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
101552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // Same tests with function-call notation
102552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(int(intLvalue));
103552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(short(intLvalue));
104552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(long(intLvalue));
105552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
106552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    char charLValue = 'x';
107552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE((signed char)charLValue);
108552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE((unsigned char)charLValue);
109552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
110552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(static_cast<int>(IntClass()));
111552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    IntClass intClassLValue;
112552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(static_cast<int>(intClassLValue));
113552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(static_cast<IntClass>(ConvertibleToIntClass()));
114552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ConvertibleToIntClass convertibleToIntClassLValue;
115552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(static_cast<IntClass>(convertibleToIntClassLValue));
116552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
117552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
118552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    typedef signed char signed_char;
119552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    typedef unsigned char unsigned_char;
120552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(signed_char(charLValue));
121552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(unsigned_char(charLValue));
122552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
123552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(int(IntClass()));
124552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(int(intClassLValue));
125552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(IntClass(ConvertibleToIntClass()));
126552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(IntClass(convertibleToIntClassLValue));
127552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
128552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
129552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid conv_ptr_1()
130552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
131552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // conv.ptr/1: A null pointer constant is an integral constant
132552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expression (5.19) rvalue of integer type that evaluates to
133552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // zero.
134552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(0);
135552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
136552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
137552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_6()
138552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
139552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr/6: If an expression initially has the type “reference to T”
140552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // (8.3.2, 8.5.3), ... the expression is an lvalue.
141552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int x = 0;
142552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int& referenceToInt = x;
143552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(referenceToInt);
144552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(ReturnIntReference());
145552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
146552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
147552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_prim_2()
148552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
149552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // 5.1/2 A string literal is an lvalue; all other
150552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // literals are rvalues.
151552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE("foo");
152552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(1);
153552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(1.2);
154552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(10UL);
155552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
156552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
157552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_prim_3()
158552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
159552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // 5.1/3: The keyword "this" names a pointer to the object for
160552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // which a nonstatic member function (9.3.2) is invoked. ...The
161552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expression is an rvalue.
162552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    struct ThisTest
163552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    {
164552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        void f() { ASSERT_RVALUE(this); }
165552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    };
166552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
167552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
168552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyextern int variable;
169552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid Function();
170552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
171552622067dc45013d240f73952fece703f5e63bdJohn Wiegleystruct BaseClass
172552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
173552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    virtual ~BaseClass();
174552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
175552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int BaseNonstaticMemberFunction();
176552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static int BaseStaticMemberFunction();
177552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int baseDataMember;
178552622067dc45013d240f73952fece703f5e63bdJohn Wiegley};
179552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
180552622067dc45013d240f73952fece703f5e63bdJohn Wiegleystruct Class : BaseClass
181552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
182552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static void function();
183552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static int variable;
184552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
185552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    template <class T>
186552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    struct NestedClassTemplate {};
187552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
188552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    template <class T>
189552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static int& NestedFuncTemplate() { return variable; } // expected-note{{candidate function}}
190552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
191552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    template <class T>
192552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int& NestedMemfunTemplate() { return variable; } // expected-note{{candidate function}}
193552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
194552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int operator*() const;
195552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
196552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    template <class T>
197552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int operator+(T) const; // expected-note{{candidate function}}
198552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
199552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int NonstaticMemberFunction();
200552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static int StaticMemberFunction();
201552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int dataMember;
202552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
203552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int& referenceDataMember;
204552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static int& staticReferenceDataMember;
205552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static int staticNonreferenceDataMember;
206552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
207552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    enum Enum { Enumerator };
208552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
209552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    operator long() const;
210552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
211552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    Class();
212552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    Class(int,int);
213552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
214552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    void expr_prim_4()
215552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    {
216552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // 5.1/4: The operator :: followed by an identifier, a
217552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // qualified-id, or an operator-function-id is a primary-
218552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // expression. ...The result is an lvalue if the entity is
219552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // a function or variable.
220552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(::Function);         // identifier: function
221552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(::variable);         // identifier: variable
222552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
223552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // the only qualified-id form that can start without "::" (and thus
224552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // be legal after "::" ) is
225552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        //
226552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // ::<sub>opt</sub> nested-name-specifier template<sub>opt</sub> unqualified-id
227552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(::Class::function);  // qualified-id: function
228552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(::Class::variable);  // qualified-id: variable
229552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
230552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // The standard doesn't give a clear answer about whether these
231552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // should really be lvalues or rvalues without some surrounding
232552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // context that forces them to be interpreted as naming a
233552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // particular function template specialization (that situation
234552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // doesn't come up in legal pure C++ programs). This language
235552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // extension simply rejects them as requiring additional context
236552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        __is_lvalue_expr(::Class::NestedFuncTemplate);    // qualified-id: template \
237552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // expected-error{{cannot resolve overloaded function 'NestedFuncTemplate' from context}}
238552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
239552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        __is_lvalue_expr(::Class::NestedMemfunTemplate);  // qualified-id: template \
240552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // expected-error{{cannot resolve overloaded function 'NestedMemfunTemplate' from context}}
241552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
242552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        __is_lvalue_expr(::Class::operator+);             // operator-function-id: template \
243552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // expected-error{{cannot resolve overloaded function 'operator+' from context}}
244552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
245552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_RVALUE(::Class::operator*);         // operator-function-id: member function
246552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    }
247552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
248552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    void expr_prim_7()
249552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    {
250552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // expr.prim/7 An identifier is an id-expression provided it has been
251552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // suitably declared (clause 7). [Note: ... ] The type of the
252552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // expression is the type of the identifier. The result is the
253552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // entity denoted by the identifier. The result is an lvalue if
254552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // the entity is a function, variable, or data member... (cont'd)
255552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(Function);        // identifier: function
256552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(StaticMemberFunction);        // identifier: function
257552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(variable);        // identifier: variable
258552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(dataMember);      // identifier: data member
259552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_RVALUE(NonstaticMemberFunction); // identifier: member function
260552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
261552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // (cont'd)...A nested-name-specifier that names a class,
262552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // optionally followed by the keyword template (14.2), and then
263552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // followed by the name of a member of either that class (9.2) or
264552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // one of its base classes... is a qualified-id... The result is
265552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // the member. The type of the result is the type of the
266552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // member. The result is an lvalue if the member is a static
267552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        // member function or a data member.
268552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(Class::dataMember);
269552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(Class::StaticMemberFunction);
270552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_RVALUE(Class::NonstaticMemberFunction); // identifier: member function
271552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
272552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(Class::baseDataMember);
273552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_LVALUE(Class::BaseStaticMemberFunction);
274552622067dc45013d240f73952fece703f5e63bdJohn Wiegley        ASSERT_RVALUE(Class::BaseNonstaticMemberFunction); // identifier: member function
275552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    }
276552622067dc45013d240f73952fece703f5e63bdJohn Wiegley};
277552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
278552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_call_10()
279552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
280552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.call/10: A function call is an lvalue if and only if the
281552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // result type is a reference.  This statement is partially
282552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // redundant with basic.lval/5
283552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    basic_lval_5();
284552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
285552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(ReturnIntReference());
286552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(ReturnEnumReference());
287552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
288552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
289552622067dc45013d240f73952fece703f5e63bdJohn Wiegleynamespace Namespace
290552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
291552622067dc45013d240f73952fece703f5e63bdJohn Wiegley  int x;
292552622067dc45013d240f73952fece703f5e63bdJohn Wiegley  void function();
293552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
294552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
295552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_prim_8()
296552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
297552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.prim/8 A nested-name-specifier that names a namespace
298552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // (7.3), followed by the name of a member of that namespace (or
299552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // the name of a member of a namespace made visible by a
300552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // using-directive ) is a qualified-id; 3.4.3.2 describes name
301552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // lookup for namespace members that appear in qualified-ids. The
302552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // result is the member. The type of the result is the type of the
303552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // member. The result is an lvalue if the member is a function or
304552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // a variable.
305552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(Namespace::x);
306552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(Namespace::function);
307552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
308552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
309552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_sub_1(int* pointer)
310552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
311552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.sub/1 A postfix expression followed by an expression in
312552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // square brackets is a postfix expression. One of the expressions
313552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // shall have the type “pointer to T” and the other shall have
314552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // enumeration or integral type. The result is an lvalue of type
315552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // “T.”
316552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(pointer[1]);
317552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
318552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // The expression E1[E2] is identical (by definition) to *((E1)+(E2)).
319552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(*(pointer+1));
320552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
321552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
322552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_type_conv_1()
323552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
324552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.type.conv/1 A simple-type-specifier (7.1.5) followed by a
325552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // parenthesized expression-list constructs a value of the specified
326552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // type given the expression list. ... If the expression list
327552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // specifies more than a single value, the type shall be a class with
328552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // a suitably declared constructor (8.5, 12.1), and the expression
329552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // T(x1, x2, ...) is equivalent in effect to the declaration T t(x1,
330552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // x2, ...); for some invented temporary variable t, with the result
331552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // being the value of t as an rvalue.
332552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(Class(2,2));
333552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
334552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
335552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_type_conv_2()
336552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
337552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.type.conv/2 The expression T(), where T is a
338552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // simple-type-specifier (7.1.5.2) for a non-array complete object
339552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // type or the (possibly cv-qualified) void type, creates an
340552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // rvalue of the specified type,
341552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(int());
342552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(Class());
343552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(void());
344552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
345552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
346552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
347552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_ref_4()
348552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
349552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // Applies to expressions of the form E1.E2
350552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
351552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // If E2 is declared to have type “reference to T”, then E1.E2 is
352552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // an lvalue;.... Otherwise, one of the following rules applies.
353552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(Class().staticReferenceDataMember);
354552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(Class().referenceDataMember);
355552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
356552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // — If E2 is a static data member, and the type of E2 is T, then
357552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // E1.E2 is an lvalue; ...
358552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(Class().staticNonreferenceDataMember);
359552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(Class().staticReferenceDataMember);
360552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
361552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
362552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // — If E2 is a non-static data member, ... If E1 is an lvalue,
363552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // then E1.E2 is an lvalue...
364552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    Class lvalue;
365552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(lvalue.dataMember);
366552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(Class().dataMember);
367552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
368552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // — If E1.E2 refers to a static member function, ... then E1.E2
369552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // is an lvalue
370552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(Class().StaticMemberFunction);
371552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
372552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // — Otherwise, if E1.E2 refers to a non-static member function,
373552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // then E1.E2 is not an lvalue.
374552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(Class().NonstaticMemberFunction);
375552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
376552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // — If E2 is a member enumerator, and the type of E2 is T, the
377552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expression E1.E2 is not an lvalue. The type of E1.E2 is T.
378552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(Class().Enumerator);
379552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(lvalue.Enumerator);
380552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
381552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
382552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
383552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_post_incr_1(int x)
384552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
385552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.post.incr/1 The value obtained by applying a postfix ++ is
386552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // the value that the operand had before applying the
387552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // operator... The result is an rvalue.
388552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(x++);
389552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
390552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
391552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_dynamic_cast_2()
392552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
393552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.dynamic.cast/2: If T is a pointer type, v shall be an
394552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // rvalue of a pointer to complete class type, and the result is
395552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // an rvalue of type T.
396552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    Class instance;
397552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(dynamic_cast<Class*>(&instance));
398552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
399552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // If T is a reference type, v shall be an
400552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // lvalue of a complete class type, and the result is an lvalue of
401552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // the type referred to by T.
402552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(dynamic_cast<Class&>(instance));
403552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
404552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
405552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_dynamic_cast_5()
406552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
407552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.dynamic.cast/5: If T is “reference to cv1 B” and v has type
408552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // “cv2 D” such that B is a base class of D, the result is an
409552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // lvalue for the unique B sub-object of the D object referred
410552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // to by v.
411552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    typedef BaseClass B;
412552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    typedef Class D;
413552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    D object;
414552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(dynamic_cast<B&>(object));
415552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
416552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
417552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// expr.dynamic.cast/8: The run-time check logically executes as follows:
418552622067dc45013d240f73952fece703f5e63bdJohn Wiegley//
419552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// — If, in the most derived object pointed (referred) to by v, v
420552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// points (refers) to a public base class subobject of a T object, and
421552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// if only one object of type T is derived from the sub-object pointed
422552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// (referred) to by v, the result is a pointer (an lvalue referring)
423552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// to that T object.
424552622067dc45013d240f73952fece703f5e63bdJohn Wiegley//
425552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// — Otherwise, if v points (refers) to a public base class sub-object
426552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// of the most derived object, and the type of the most derived object
427552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// has a base class, of type T, that is unambiguous and public, the
428552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// result is a pointer (an lvalue referring) to the T sub-object of
429552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// the most derived object.
430552622067dc45013d240f73952fece703f5e63bdJohn Wiegley//
431552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// The mention of "lvalue" in the text above appears to be a
432552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// defect that is being corrected by the response to UK65 (see
433552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2841.html).
434552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
435552622067dc45013d240f73952fece703f5e63bdJohn Wiegley#if 0
436552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_typeid_1()
437552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
438552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.typeid/1: The result of a typeid expression is an lvalue...
439552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(typeid(1));
440552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
441552622067dc45013d240f73952fece703f5e63bdJohn Wiegley#endif
442552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
443552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_static_cast_1(int x)
444552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
445552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.static.cast/1: The result of the expression
446552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // static_cast<T>(v) is the result of converting the expression v
447552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // to type T. If T is a reference type, the result is an lvalue;
448552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // otherwise, the result is an rvalue.
449552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(static_cast<int&>(x));
450552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(static_cast<int>(x));
451552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
452552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
453552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_reinterpret_cast_1()
454552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
455552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.reinterpret.cast/1: The result of the expression
456552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // reinterpret_cast<T>(v) is the result of converting the
457552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expression v to type T. If T is a reference type, the result is
458552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // an lvalue; otherwise, the result is an rvalue
459552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(reinterpret_cast<int*>(0));
460552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    char const v = 0;
461552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(reinterpret_cast<char const&>(v));
462552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
463552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
464552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_unary_op_1(int* pointer, struct incomplete* pointerToIncompleteType)
465552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
466552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.unary.op/1: The unary * operator performs indirection: the
467552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expression to which it is applied shall be a pointer to an
468552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // object type, or a pointer to a function type and the result is
469552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // an lvalue referring to the object or function to which the
470552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expression points.
471552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(*pointer);
472552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(*Function);
473552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
474552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // [Note: a pointer to an incomplete type
475552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // (other than cv void ) can be dereferenced. ]
476552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(*pointerToIncompleteType);
477552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
478552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
479552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_pre_incr_1(int operand)
480552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
481552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.pre.incr/1: The operand of prefix ++ ... shall be a
482552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // modifiable lvalue.... The value is the new value of the
483552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // operand; it is an lvalue.
484552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(++operand);
485552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
486552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
487552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_cast_1(int x)
488552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
489552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.cast/1: The result of the expression (T) cast-expression
490552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // is of type T. The result is an lvalue if T is a reference type,
491552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // otherwise the result is an rvalue.
492552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE((void(&)())expr_cast_1);
493552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE((int&)x);
494552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE((void(*)())expr_cast_1);
495552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE((int)x);
496552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
497552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
498552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_mptr_oper()
499552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
500552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.mptr.oper/6: The result of a .* expression is an lvalue
501552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // only if its first operand is an lvalue and its second operand
502552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // is a pointer to data member... (cont'd)
503552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    typedef Class MakeRValue;
504552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(MakeRValue().*(&Class::dataMember));
505552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(MakeRValue().*(&Class::NonstaticMemberFunction));
506552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    Class lvalue;
507552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(lvalue.*(&Class::dataMember));
508552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(lvalue.*(&Class::NonstaticMemberFunction));
509552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
510552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // (cont'd)...The result of an ->* expression is an lvalue only
511552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // if its second operand is a pointer to data member. If the
512552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // second operand is the null pointer to member value (4.11), the
513552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // behavior is undefined.
514552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE((&lvalue)->*(&Class::dataMember));
515552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE((&lvalue)->*(&Class::NonstaticMemberFunction));
516552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
517552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
518552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_cond(bool cond)
519552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
520552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // 5.16 Conditional operator [expr.cond]
521552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    //
522552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // 2 If either the second or the third operand has type (possibly
523552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // cv-qualified) void, then the lvalue-to-rvalue (4.1),
524552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // array-to-pointer (4.2), and function-to-pointer (4.3) standard
525552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // conversions are performed on the second and third operands, and one
526552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // of the following shall hold:
527552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    //
528552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // — The second or the third operand (but not both) is a
529552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // throw-expression (15.1); the result is of the type of the other and
530552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // is an rvalue.
531552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
532552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    Class classLvalue;
533552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? throw 1 : (void)0);
534552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? (void)0 : throw 1);
535552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? throw 1 : classLvalue);
536552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? classLvalue : throw 1);
537552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
538552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // — Both the second and the third operands have type void; the result
539552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // is of type void and is an rvalue. [Note: this includes the case
540552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // where both operands are throw-expressions. ]
541552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? (void)1 : (void)0);
542552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? throw 1 : throw 0);
543552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
544552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.cond/4: If the second and third operands are lvalues and
545552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // have the same type, the result is of that type and is an
546552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // lvalue.
547552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(cond ? classLvalue : classLvalue);
548552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    int intLvalue = 0;
549552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(cond ? intLvalue : intLvalue);
550552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
551552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.cond/5:Otherwise, the result is an rvalue.
552552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    typedef Class MakeRValue;
553552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? MakeRValue() : classLvalue);
554552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? classLvalue : MakeRValue());
555552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? MakeRValue() : MakeRValue());
556552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? classLvalue : intLvalue);
557552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(cond ? intLvalue : int());
558552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
559552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
560552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_ass_1(int x)
561552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
562552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.ass/1: There are several assignment operators, all of
563552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // which group right-to-left. All require a modifiable lvalue as
564552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // their left operand, and the type of an assignment expression is
565552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // that of its left operand. The result of the assignment
566552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // operation is the value stored in the left operand after the
567552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // assignment has taken place; the result is an lvalue.
568552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(x = 1);
569552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(x += 1);
570552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(x -= 1);
571552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(x *= 1);
572552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(x /= 1);
573552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(x %= 1);
574552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(x ^= 1);
575552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(x &= 1);
576552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(x |= 1);
577552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
578552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
579552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_comma(int x)
580552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
581552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // expr.comma: A pair of expressions separated by a comma is
582552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // evaluated left-to-right and the value of the left expression is
583552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // discarded... result is an lvalue if its right operand is.
584552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
585552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // Can't use the ASSERT_XXXX macros without adding parens around
586552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    // the comma expression.
587552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(__is_lvalue_expr(x,x), "expected an lvalue");
588552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(__is_rvalue_expr(x,1), "expected an rvalue");
589552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(__is_lvalue_expr(1,x), "expected an lvalue");
590552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    static_assert(__is_rvalue_expr(1,1), "expected an rvalue");
591552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
592552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
593552622067dc45013d240f73952fece703f5e63bdJohn Wiegley#if 0
594552622067dc45013d240f73952fece703f5e63bdJohn Wiegleytemplate<typename T> void f();
595552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
596552622067dc45013d240f73952fece703f5e63bdJohn Wiegley// FIXME These currently fail
597552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_fun_lvalue()
598552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
599552622067dc45013d240f73952fece703f5e63bdJohn Wiegley  ASSERT_LVALUE(&f<int>);
600552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
601552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
602552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid expr_fun_rvalue()
603552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
604552622067dc45013d240f73952fece703f5e63bdJohn Wiegley  ASSERT_RVALUE(f<int>);
605552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
606552622067dc45013d240f73952fece703f5e63bdJohn Wiegley#endif
607552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
608552622067dc45013d240f73952fece703f5e63bdJohn Wiegleytemplate <int NonTypeNonReferenceParameter, int& NonTypeReferenceParameter>
609552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid check_temp_param_6()
610552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
611552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_RVALUE(NonTypeNonReferenceParameter);
612552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    ASSERT_LVALUE(NonTypeReferenceParameter);
613552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
614552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
615552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyint AnInt = 0;
616552622067dc45013d240f73952fece703f5e63bdJohn Wiegley
617552622067dc45013d240f73952fece703f5e63bdJohn Wiegleyvoid temp_param_6()
618552622067dc45013d240f73952fece703f5e63bdJohn Wiegley{
619552622067dc45013d240f73952fece703f5e63bdJohn Wiegley    check_temp_param_6<3,AnInt>();
620552622067dc45013d240f73952fece703f5e63bdJohn Wiegley}
621