summaryrefslogtreecommitdiff
path: root/clang/test/CXX/expr/expr.const/p3-0x.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/expr/expr.const/p3-0x.cpp')
-rw-r--r--clang/test/CXX/expr/expr.const/p3-0x.cpp110
1 files changed, 110 insertions, 0 deletions
diff --git a/clang/test/CXX/expr/expr.const/p3-0x.cpp b/clang/test/CXX/expr/expr.const/p3-0x.cpp
new file mode 100644
index 0000000..6ddd11b
--- /dev/null
+++ b/clang/test/CXX/expr/expr.const/p3-0x.cpp
@@ -0,0 +1,110 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+// A converted constant expression of type T is a core constant expression,
+int nonconst = 8; // expected-note 3 {{here}}
+enum NonConstE : unsigned char { NCE = nonconst }; // expected-error {{enumerator value is not a constant expression}} expected-note {{read of non-const}}
+template<int = nonconst> struct NonConstT {}; // expected-error {{non-type template argument is not a constant expression}} expected-note {{read of non-const}}
+void NonConstF() {
+ switch (nonconst) {
+ case nonconst: // expected-error {{case value is not a constant expression}} expected-note {{read of non-const}}
+ break;
+ }
+ return;
+}
+
+// implicitly converted to a prvalue of type T, where the converted expression
+// is a literal constant expression
+
+bool a(int n) {
+ constexpr char vowels[] = "aeiou";
+ switch (n) {
+ case vowels[0]:
+ case vowels[1]:
+ case vowels[2]:
+ case vowels[3]:
+ case vowels[4]:
+ static_assert(!vowels[5], "unexpected number of vowels");
+ return true;
+ }
+ return false;
+}
+
+// and the implicit conversion sequence contains only
+//
+// user-defined conversions,
+struct S { constexpr operator int() const { return 5; } };
+enum E : unsigned char { E5 = S(), E6, E10 = S() * 2, E1 = E5 / 5 };
+
+// lvalue-to-rvalue conversions,
+const E e10 = E10;
+template<E> struct T {};
+T<e10> s10;
+
+// integral promotions, and
+enum class EE { EE32 = ' ', EE65 = 'A', EE1 = (short)1, EE5 = E5 };
+
+// integral conversions other than narrowing conversions
+int b(unsigned n) {
+ switch (n) {
+ case E6:
+ case EE::EE32: // expected-error {{not implicitly convertible}}
+ case (int)EE::EE32:
+ case 1000:
+ case (long long)1e10: // expected-error {{case value evaluates to 10000000000, which cannot be narrowed to type 'unsigned int'}}
+ case -3: // expected-error {{case value evaluates to -3, which cannot be narrowed to type 'unsigned int'}}
+ return n;
+ }
+ return 0;
+}
+enum class EEE : unsigned short {
+ a = E6,
+ b = EE::EE32, // expected-error {{not implicitly convertible}}
+ c = (int)EE::EE32,
+ d = 1000,
+ e = 123456, // expected-error {{enumerator value evaluates to 123456, which cannot be narrowed to type 'unsigned short'}}
+ f = -3 // expected-error {{enumerator value evaluates to -3, which cannot be narrowed to type 'unsigned short'}}
+};
+template<unsigned char> using A = int;
+using Int = A<E6>;
+using Int = A<EE::EE32>; // expected-error {{not implicitly convertible}}
+using Int = A<(int)EE::EE32>;
+using Int = A<200>;
+using Int = A<1000>; // expected-error {{template argument evaluates to 1000, which cannot be narrowed to type 'unsigned char'}}
+using Int = A<-3>; // expected-error {{template argument evaluates to -3, which cannot be narrowed to type 'unsigned char'}}
+
+// Note, conversions from integral or unscoped enumeration types to bool are
+// integral conversions as well as boolean conversions.
+template<typename T, T v> struct Val { static constexpr T value = v; };
+static_assert(Val<bool, E1>::value == 1, ""); // ok
+static_assert(Val<bool, '\0'>::value == 0, ""); // ok
+static_assert(Val<bool, U'\1'>::value == 1, ""); // ok
+static_assert(Val<bool, E5>::value == 1, ""); // expected-error {{5, which cannot be narrowed to type 'bool'}}
+
+// (no other conversions are permitted)
+using Int = A<1.0>; // expected-error {{conversion from 'double' to 'unsigned char' is not allowed in a converted constant expression}}
+enum B : bool {
+ True = &a, // expected-error {{conversion from 'bool (*)(int)' to 'bool' is not allowed in a converted constant expression}}
+ False = nullptr // expected-error {{conversion from 'nullptr_t' to 'bool' is not allowed in a converted constant expression}}
+};
+void c() {
+ // Note, promoted type of switch is 'int'.
+ switch (bool b = a(5)) { // expected-warning {{boolean value}}
+ case 0.0f: // expected-error {{conversion from 'float' to 'int' is not allowed in a converted constant expression}}
+ break;
+ }
+}
+template<bool B> int f() { return B; }
+template int f<&S::operator int>(); // expected-error {{does not refer to a function template}}
+template int f<(bool)&S::operator int>();
+
+int n = Val<bool, &S::operator int>::value; // expected-error {{conversion from 'int (S::*)() const' to 'bool' is not allowed in a converted constant expression}}
+
+namespace NonConstLValue {
+ struct S {
+ constexpr operator int() { return 10; }
+ };
+ S s; // not constexpr
+ // Under the FDIS, this is not a converted constant expression.
+ // Under the new proposed wording, it is.
+ enum E : char { e = s };
+}