summaryrefslogtreecommitdiff
path: root/clang/test/SemaCXX/constant-expression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/SemaCXX/constant-expression.cpp')
-rw-r--r--clang/test/SemaCXX/constant-expression.cpp119
1 files changed, 119 insertions, 0 deletions
diff --git a/clang/test/SemaCXX/constant-expression.cpp b/clang/test/SemaCXX/constant-expression.cpp
new file mode 100644
index 0000000..23a4dda
--- /dev/null
+++ b/clang/test/SemaCXX/constant-expression.cpp
@@ -0,0 +1,119 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %s
+// C++ [expr.const]p1:
+// In several places, C++ requires expressions that evaluate to an integral
+// or enumeration constant: as array bounds, as case expressions, as
+// bit-field lengths, as enumerator initializers, as static member
+// initializers, and as integral or enumeration non-type template arguments.
+// An integral constant-expression can involve only literals, enumerators,
+// const variables or static data members of integral or enumeration types
+// initialized with constant expressions, and sizeof expressions. Floating
+// literals can appear only if they are cast to integral or enumeration types.
+
+enum Enum { eval = 1 };
+const int cval = 2;
+const Enum ceval = eval;
+struct Struct {
+ static const int sval = 3;
+ static const Enum seval = eval;
+};
+
+template <int itval, Enum etval> struct C {
+ enum E {
+ v1 = 1,
+ v2 = eval,
+ v3 = cval,
+ v4 = ceval,
+ v5 = Struct::sval,
+ v6 = Struct::seval,
+ v7 = itval,
+ v8 = etval,
+ v9 = (int)1.5,
+ v10 = sizeof(Struct),
+ v11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0
+ };
+ unsigned
+ b1 : 1,
+ b2 : eval,
+ b3 : cval,
+ b4 : ceval,
+ b5 : Struct::sval,
+ b6 : Struct::seval,
+ b7 : itval,
+ b8 : etval,
+ b9 : (int)1.5,
+ b10 : sizeof(Struct),
+ b11 : true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0
+ ;
+ static const int
+ i1 = 1,
+ i2 = eval,
+ i3 = cval,
+ i4 = ceval,
+ i5 = Struct::sval,
+ i6 = Struct::seval,
+ i7 = itval,
+ i8 = etval,
+ i9 = (int)1.5,
+ i10 = sizeof(Struct),
+ i11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0
+ ;
+ void f(int cond) {
+ switch(cond) {
+ case 0 + 1:
+ case 100 + eval:
+ case 200 + cval:
+ case 300 + ceval:
+ case 400 + Struct::sval:
+ case 500 + Struct::seval:
+ case 600 + itval:
+ case 700 + etval:
+ case 800 + (int)1.5:
+ case 900 + sizeof(Struct):
+ case 1000 + (true? 1 + cval * Struct::sval ^
+ itval / (int)1.5 - sizeof(Struct) : 0):
+ ;
+ }
+ }
+ typedef C<itval, etval> T0;
+};
+
+template struct C<1, eval>;
+template struct C<cval, ceval>;
+template struct C<Struct::sval, Struct::seval>;
+
+enum {
+ a = sizeof(int) == 8,
+ b = a? 8 : 4
+};
+
+void diags(int n) {
+ switch (n) {
+ case (1/0, 1): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
+ case (int)(1/0, 2.0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
+ case __imag(1/0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
+ case (int)__imag((double)(1/0)): // expected-error {{not an integral constant expression}} expected-note {{division by zero}}
+ ;
+ }
+}
+
+namespace IntOrEnum {
+ const int k = 0;
+ const int &p = k;
+ template<int n> struct S {};
+ S<p> s; // expected-error {{not an integral constant expression}}
+}
+
+extern const int recurse1;
+// recurse2 cannot be used in a constant expression because it is not
+// initialized by a constant expression. The same expression appearing later in
+// the TU would be a constant expression, but here it is not.
+const int recurse2 = recurse1;
+const int recurse1 = 1;
+int array1[recurse1]; // ok
+int array2[recurse2]; // expected-warning {{variable length array}} expected-warning {{integer constant expression}}
+
+namespace FloatConvert {
+ typedef int a[(int)42.3];
+ typedef int a[(int)42.997];
+ typedef int b[(int)4e10]; // expected-warning {{variable length}} expected-error {{variable length}}
+}