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