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