Richard Smith | f8379a0 | 2012-01-18 23:55:52 +0000 | [diff] [blame^] | 1 | // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s |
| 2 | |
| 3 | // A converted constant expression of type T is a core constant expression, |
| 4 | int nonconst = 8; // expected-note 3 {{here}} |
| 5 | enum NonConstE : unsigned char { NCE = nonconst }; // expected-error {{enumerator value is not a constant expression}} expected-note {{read of non-const}} |
| 6 | template<int = nonconst> struct NonConstT {}; // expected-error {{non-type template argument is not a constant expression}} expected-note {{read of non-const}} |
| 7 | void NonConstF() { |
| 8 | switch (nonconst) { |
| 9 | case nonconst: // expected-error {{case value is not a constant expression}} expected-note {{read of non-const}} |
| 10 | break; |
| 11 | } |
| 12 | return; |
| 13 | } |
| 14 | |
| 15 | // implicitly converted to a prvalue of type T, where the converted expression |
| 16 | // is a literal constant expression |
| 17 | |
| 18 | bool a(int n) { |
| 19 | constexpr char vowels[] = "aeiou"; |
| 20 | switch (n) { |
| 21 | case vowels[0]: |
| 22 | case vowels[1]: |
| 23 | case vowels[2]: |
| 24 | case vowels[3]: |
| 25 | case vowels[4]: |
| 26 | static_assert(!vowels[5], "unexpected number of vowels"); |
| 27 | return true; |
| 28 | } |
| 29 | return false; |
| 30 | } |
| 31 | |
| 32 | // and the implicit conversion sequence contains only |
| 33 | // |
| 34 | // user-defined conversions, |
| 35 | struct S { constexpr operator int() const { return 5; } }; |
| 36 | enum E : unsigned char { E5 = S(), E6, E10 = S() * 2, E1 = E5 / 5 }; |
| 37 | |
| 38 | // lvalue-to-rvalue conversions, |
| 39 | const E e10 = E10; |
| 40 | template<E> struct T {}; |
| 41 | T<e10> s10; |
| 42 | |
| 43 | // integral promotions, and |
| 44 | enum class EE { EE32 = ' ', EE65 = 'A', EE1 = (short)1, EE5 = E5 }; |
| 45 | |
| 46 | // integral conversions other than narrowing conversions |
| 47 | int b(unsigned n) { |
| 48 | switch (n) { |
| 49 | case E6: |
| 50 | case EE::EE32: // expected-error {{not implicitly convertible}} |
| 51 | case (int)EE::EE32: |
| 52 | case 1000: |
| 53 | case (long long)1e10: // expected-error {{case value evaluates to 10000000000, which cannot be narrowed to type 'unsigned int'}} |
| 54 | case -3: // expected-error {{case value evaluates to -3, which cannot be narrowed to type 'unsigned int'}} |
| 55 | return n; |
| 56 | } |
| 57 | return 0; |
| 58 | } |
| 59 | enum class EEE : unsigned short { |
| 60 | a = E6, |
| 61 | b = EE::EE32, // expected-error {{not implicitly convertible}} |
| 62 | c = (int)EE::EE32, |
| 63 | d = 1000, |
| 64 | e = 123456, // expected-error {{enumerator value evaluates to 123456, which cannot be narrowed to type 'unsigned short'}} |
| 65 | f = -3 // expected-error {{enumerator value evaluates to -3, which cannot be narrowed to type 'unsigned short'}} |
| 66 | }; |
| 67 | template<unsigned char> using A = int; |
| 68 | using Int = A<E6>; |
| 69 | using Int = A<EE::EE32>; // expected-error {{not implicitly convertible}} |
| 70 | using Int = A<(int)EE::EE32>; |
| 71 | using Int = A<200>; |
| 72 | using Int = A<1000>; // expected-error {{template argument evaluates to 1000, which cannot be narrowed to type 'unsigned char'}} |
| 73 | using Int = A<-3>; // expected-error {{template argument evaluates to -3, which cannot be narrowed to type 'unsigned char'}} |
| 74 | |
| 75 | // Note, conversions from integral or unscoped enumeration types to bool are |
| 76 | // integral conversions as well as boolean conversions. |
| 77 | template<typename T, T v> struct Val { static constexpr T value = v; }; |
| 78 | static_assert(Val<bool, E1>::value == 1, ""); // ok |
| 79 | static_assert(Val<bool, '\0'>::value == 0, ""); // ok |
| 80 | static_assert(Val<bool, U'\1'>::value == 1, ""); // ok |
| 81 | static_assert(Val<bool, E5>::value == 1, ""); // expected-error {{5, which cannot be narrowed to type 'bool'}} |
| 82 | |
| 83 | // (no other conversions are permitted) |
| 84 | using Int = A<1.0>; // expected-error {{conversion from 'double' to 'unsigned char' is not allowed in a converted constant expression}} |
| 85 | enum B : bool { |
| 86 | True = &a, // expected-error {{conversion from 'bool (*)(int)' to 'bool' is not allowed in a converted constant expression}} |
| 87 | False = nullptr // expected-error {{conversion from 'nullptr_t' to 'bool' is not allowed in a converted constant expression}} |
| 88 | }; |
| 89 | void c() { |
| 90 | // Note, promoted type of switch is 'int'. |
| 91 | switch (bool b = a(5)) { // expected-warning {{boolean value}} |
| 92 | case 0.0f: // expected-error {{conversion from 'float' to 'int' is not allowed in a converted constant expression}} |
| 93 | break; |
| 94 | } |
| 95 | } |
| 96 | template<bool B> int f() { return B; } |
| 97 | template int f<&S::operator int>(); // expected-error {{does not refer to a function template}} |
| 98 | template int f<(bool)&S::operator int>(); |
| 99 | |
| 100 | int n = Val<bool, &S::operator int>::value; // expected-error {{conversion from 'int (S::*)() const' to 'bool' is not allowed in a converted constant expression}} |
| 101 | |
| 102 | namespace NonConstLValue { |
| 103 | struct S { |
| 104 | constexpr operator int() { return 10; } |
| 105 | }; |
| 106 | S s; // not constexpr |
| 107 | // Under the FDIS, this is not a converted constant expression. |
| 108 | // Under the new proposed wording, it is. |
| 109 | enum E : char { e = s }; |
| 110 | } |