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