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