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, 4int nonconst = 8; // expected-note 3 {{here}} 5enum NonConstE : unsigned char { NCE = nonconst }; // expected-error {{enumerator value is not a constant expression}} expected-note {{read of non-const}} 6template<int = nonconst> struct NonConstT {}; // expected-error {{non-type template argument is not a constant expression}} expected-note {{read of non-const}} 7void 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 18bool 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, 35struct S { constexpr operator int() const { return 5; } }; 36enum E : unsigned char { E5 = S(), E6, E10 = S() * 2, E1 = E5 / 5 }; 37 38// lvalue-to-rvalue conversions, 39const E e10 = E10; 40template<E> struct T {}; 41T<e10> s10; 42 43// integral promotions, and 44enum class EE { EE32 = ' ', EE65 = 'A', EE1 = (short)1, EE5 = E5 }; 45 46// integral conversions other than narrowing conversions 47int 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} 59enum 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}; 67template<unsigned char> using A = int; 68using Int = A<E6>; 69using Int = A<EE::EE32>; // expected-error {{not implicitly convertible}} 70using Int = A<(int)EE::EE32>; 71using Int = A<200>; 72using Int = A<1000>; // expected-error {{template argument evaluates to 1000, which cannot be narrowed to type 'unsigned char'}} 73using 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. 77template<typename T, T v> struct Val { static constexpr T value = v; }; 78static_assert(Val<bool, E1>::value == 1, ""); // ok 79static_assert(Val<bool, '\0'>::value == 0, ""); // ok 80static_assert(Val<bool, U'\1'>::value == 1, ""); // ok 81static_assert(Val<bool, E5>::value == 1, ""); // expected-error {{5, which cannot be narrowed to type 'bool'}} 82 83// (no other conversions are permitted) 84using Int = A<1.0>; // expected-error {{conversion from 'double' to 'unsigned char' is not allowed in a converted constant expression}} 85enum 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}; 89void 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} 96template <bool B> int f() { return B; } // expected-note {{candidate template ignored: invalid explicitly-specified argument for template parameter 'B'}} 97template int f<&S::operator int>(); // expected-error {{does not refer to a function template}} 98template int f<(bool)&S::operator int>(); 99 100int 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 102namespace NonConstLValue { 103 struct S { 104 constexpr operator int() const { 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} 111