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