blob: dca20c90c2e6a6e06365c800d8d425428e76b6e2 [file] [log] [blame]
Richard Smithf8379a02012-01-18 23:55:52 +00001// 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
Richard Smithb67ada62012-09-13 19:55:13 +000076// boolean conversions, not integral conversions, so are not permitted. See
77// core issue 1407.
Richard Smithf8379a02012-01-18 23:55:52 +000078template<typename T, T v> struct Val { static constexpr T value = v; };
Richard Smithb67ada62012-09-13 19:55:13 +000079static_assert(Val<bool, E1>::value == 1, ""); // expected-error {{conversion from 'E' to 'bool' is not allowed in a converted constant expression}}
80static_assert(Val<bool, '\0'>::value == 0, ""); // expected-error {{conversion from 'char' to 'bool' is not allowed in a converted constant expression}}
81static_assert(Val<bool, U'\1'>::value == 1, ""); // expected-error {{conversion from 'char32_t' to 'bool' is not allowed in a converted constant expression}}
82static_assert(Val<bool, E5>::value == 1, ""); // expected-error {{conversion from 'E' to 'bool' is not allowed in a converted constant expression}}
Richard Smithf8379a02012-01-18 23:55:52 +000083
84// (no other conversions are permitted)
85using Int = A<1.0>; // expected-error {{conversion from 'double' to 'unsigned char' is not allowed in a converted constant expression}}
86enum B : bool {
87 True = &a, // expected-error {{conversion from 'bool (*)(int)' to 'bool' is not allowed in a converted constant expression}}
88 False = nullptr // expected-error {{conversion from 'nullptr_t' to 'bool' is not allowed in a converted constant expression}}
89};
90void c() {
91 // Note, promoted type of switch is 'int'.
92 switch (bool b = a(5)) { // expected-warning {{boolean value}}
93 case 0.0f: // expected-error {{conversion from 'float' to 'int' is not allowed in a converted constant expression}}
94 break;
95 }
96}
97template<bool B> int f() { return B; }
98template int f<&S::operator int>(); // expected-error {{does not refer to a function template}}
99template int f<(bool)&S::operator int>();
100
101int n = Val<bool, &S::operator int>::value; // expected-error {{conversion from 'int (S::*)() const' to 'bool' is not allowed in a converted constant expression}}
102
103namespace NonConstLValue {
104 struct S {
105 constexpr operator int() { return 10; }
106 };
107 S s; // not constexpr
108 // Under the FDIS, this is not a converted constant expression.
109 // Under the new proposed wording, it is.
110 enum E : char { e = s };
111}