summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2011-12-21 05:04:46 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2011-12-21 05:04:46 +0000
commitf2b681b4d81942a62d725a95553271afd1e86a42 (patch)
tree2279f9911d6b0c8fdf21dfcd7f29408d4d2a6ab8 /clang/test
parentf243e0df95dcd0bfb81263f9c39c397202cb8d8e (diff)
downloadbcm5719-llvm-f2b681b4d81942a62d725a95553271afd1e86a42.tar.gz
bcm5719-llvm-f2b681b4d81942a62d725a95553271afd1e86a42.zip
constexpr: diagnostic improvements for invalid lvalue-to-rvalue conversions in
constant expressions. llvm-svn: 147035
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp6
-rw-r--r--clang/test/CXX/expr/expr.const/p2-0x.cpp63
-rw-r--r--clang/test/SemaCXX/constant-expression-cxx11.cpp65
-rw-r--r--clang/test/SemaCXX/constexpr-printing.cpp16
4 files changed, 101 insertions, 49 deletions
diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
index 4145e9b2245..34114cb0771 100644
--- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
+++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p9.cpp
@@ -5,7 +5,7 @@
constexpr int a = 0;
extern const int a;
-int i;
+int i; // expected-note 2{{here}}
constexpr int *b = &i;
extern int *const b;
@@ -21,11 +21,11 @@ constexpr int ni1; // expected-error {{default initialization of an object of co
constexpr struct C { C(); } ni2; // expected-error {{constexpr variable 'ni2' must be initialized by a constant expression}} expected-note {{non-literal type 'const struct C' cannot be used in a constant expression}}
constexpr double &ni3; // expected-error {{declaration of reference variable 'ni3' requires an initializer}}
-constexpr int nc1 = i; // expected-error {{constexpr variable 'nc1' must be initialized by a constant expression}}
+constexpr int nc1 = i; // expected-error {{constexpr variable 'nc1' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
constexpr C nc2 = C(); // expected-error {{constexpr variable 'nc2' must be initialized by a constant expression}} expected-note {{non-literal type}}
int &f(); // expected-note {{declared here}}
constexpr int &nc3 = f(); // expected-error {{constexpr variable 'nc3' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f' cannot be used in a constant expression}}
-constexpr int nc4(i); // expected-error {{constexpr variable 'nc4' must be initialized by a constant expression}}
+constexpr int nc4(i); // expected-error {{constexpr variable 'nc4' must be initialized by a constant expression}} expected-note {{read of non-const variable 'i' is not allowed in a constant expression}}
constexpr C nc5((C())); // expected-error {{constexpr variable 'nc5' must be initialized by a constant expression}} expected-note {{non-literal type 'const C'}}
int &f(); // expected-note {{here}}
constexpr int &nc6(f()); // expected-error {{constexpr variable 'nc6' must be initialized by a constant expression}} expected-note {{non-constexpr function 'f'}}
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index aa83fc7fa99..157645fc521 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -146,26 +146,50 @@ struct Lambda {
//int n : []{ return 1; }();
};
-// FIXME:
// - an lvalue-to-rvalue conversion (4.1) unless it is applied to
-//
-// - a non-volatile glvalue of integral or enumeration type that refers to a
-// non-volatile const object with a preceding initialization, initialized with
-// a constant expression [Note: a string literal (2.14.5 [lex.string])
-// corresponds to an array of such objects. -end note], or
-//
-// - a non-volatile glvalue of literal type that refers to a non-volatile
-// object defined with constexpr, or that refers to a sub-object of such an
-// object, or
-//
-// - a non-volatile glvalue of literal type that refers to a non-volatile
-// temporary object whose lifetime has not ended, initialized with a constant
-// expression;
+namespace LValueToRValue {
+ // - a non-volatile glvalue of integral or enumeration type that refers to a
+ // non-volatile const object with a preceding initialization, initialized
+ // with a constant expression [Note: a string literal (2.14.5 [lex.string])
+ // corresponds to an array of such objects. -end note], or
+ volatile const int vi = 1; // expected-note {{here}}
+ const int ci = 1;
+ volatile const int &vrci = ci;
+ static_assert(vi, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type 'const volatile int'}}
+ static_assert(const_cast<int&>(vi), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vi'}}
+ static_assert(vrci, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
+
+ // - a non-volatile glvalue of literal type that refers to a non-volatile
+ // object defined with constexpr, or that refers to a sub-object of such an
+ // object, or
+ struct S {
+ constexpr S(int=0) : i(1), v(1) {}
+ constexpr S(const S &s) : i(2), v(2) {}
+ int i;
+ volatile int v;
+ };
+ constexpr S s;
+ constexpr volatile S vs; // expected-note {{here}}
+ constexpr const volatile S &vrs = s;
+ static_assert(s.i, "");
+ static_assert(s.v, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
+ static_assert(vs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
+ static_assert(const_cast<int&>(vs.i), ""); // expected-error {{constant expression}} expected-note {{read of volatile object 'vs'}}
+ static_assert(vrs.i, ""); // expected-error {{constant expression}} expected-note {{read of volatile-qualified type}}
+
+ // - a non-volatile glvalue of literal type that refers to a non-volatile
+ // temporary object whose lifetime has not ended, initialized with a
+ // constant expression;
+ constexpr volatile S f() { return S(); }
+ static_assert(f().i, ""); // ok! there's no lvalue-to-rvalue conversion here!
+ static_assert(((volatile const S&&)(S)0).i, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
+}
// FIXME:
//
-// DR1312: The proposed wording for this defect has issues, so we instead
-// prohibit casts from pointers to cv void (see core-20842 and core-20845).
+// DR1312: The proposed wording for this defect has issues, so we ignore this
+// bullet and instead prohibit casts from pointers to cv void (see core-20842
+// and core-20845).
//
// - an lvalue-to-rvalue conversion (4.1 [conv.lval]) that is applied to a
// glvalue of type cv1 T that refers to an object of type cv2 U, where T and U
@@ -175,14 +199,13 @@ struct Lambda {
// - an lvalue-to-rvalue conversion (4.1) that is applied to a glvalue that
// refers to a non-active member of a union or a subobject thereof;
-// FIXME:
// - an id-expression that refers to a variable or data member of reference type
// unless the reference has a preceding initialization, initialized with a
// constant expression;
namespace References {
const int a = 2;
int &b = *const_cast<int*>(&a);
- int c = 10;
+ int c = 10; // expected-note 2 {{here}}
int &d = c;
constexpr int e = 42;
int &f = const_cast<int&>(e);
@@ -195,8 +218,8 @@ namespace References {
struct S {
int A : a;
int B : b;
- int C : c; // expected-error {{constant expression}}
- int D : d; // expected-error {{constant expression}}
+ int C : c; // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}}
+ int D : d; // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}}
int D2 : &d - &c + 1;
int E : e / 2;
int F : f - 11;
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index b470c80619d..af0d5f3e1c3 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -143,8 +143,8 @@ static_assert(F(0) == 0, "");
static_assert(F(1, 0) == 1, "");
static_assert(F(2, "test") == 2, "");
static_assert(F(3, &F) == 3, "");
-int k = 0;
-static_assert(F(4, k) == 3, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
+int k = 0; // expected-note {{here}}
+static_assert(F(4, k) == 3, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'k'}}
}
@@ -362,8 +362,9 @@ static_assert(MangleChars(U"constexpr!") == 1768383, "");
constexpr char c0 = "nought index"[0];
constexpr char c1 = "nice index"[10];
-constexpr char c2 = "nasty index"[12]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is past the end}}
-constexpr char c3 = "negative index"[-1]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is before the beginning}}
+constexpr char c2 = "nasty index"[12]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is past the end}} expected-note {{read of dereferenced one-past-the-end pointer}}
+// FIXME: block the pointer arithmetic with undefined behavior here
+constexpr char c3 = "negative index"[-1]; // expected-error {{must be initialized by a constant expression}} expected-warning {{is before the beginning}} expected-note {{read of dereferenced one-past-the-end pointer}}
constexpr char c4 = ((char*)(int*)"no reinterpret_casts allowed")[14]; // expected-error {{must be initialized by a constant expression}}
constexpr const char *p = "test" + 2;
@@ -386,6 +387,10 @@ static_assert(strcmp_ce("hello world", "hello clang") > 0, "");
static_assert(strcmp_ce("constexpr", "test") < 0, "");
static_assert(strcmp_ce("", " ") < 0, "");
+struct S {
+ int n : "foo"[4]; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer is not allowed in a constant expression}}
+};
+
}
namespace Array {
@@ -403,7 +408,7 @@ static_assert(sum_xs == 15, "");
constexpr int ZipFoldR(int (*F)(int x, int y, int c), int n,
const int *xs, const int *ys, int c) {
return n ? F(
- *xs, // expected-note {{subexpression not valid}}
+ *xs, // expected-note {{read of dereferenced one-past-the-end pointer}}
*ys,
ZipFoldR(F, n-1, xs+1, ys+1, c)) // \
expected-note {{in call to 'ZipFoldR(&SubMul, 2, &xs[4], &ys[4], 1)'}} \
@@ -423,20 +428,21 @@ static_assert(ZipFoldR(SubMul, 3, xs+3, ys+3, 1), ""); // \
constexpr const int *p = xs + 3;
constexpr int xs4 = p[1]; // ok
-constexpr int xs5 = p[2]; // expected-error {{constant expression}}
+constexpr int xs5 = p[2]; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
constexpr int xs0 = p[-3]; // ok
-constexpr int xs_1 = p[-4]; // expected-error {{constant expression}}
+// FIXME: check pointer arithmetic here
+constexpr int xs_1 = p[-4]; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
static_assert(zs[0][0][0][0] == 1, "");
static_assert(zs[1][1][1][1] == 16, "");
-static_assert(zs[0][0][0][2] == 3, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
+static_assert(zs[0][0][0][2] == 3, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
static_assert((&zs[0][0][0][2])[-1] == 2, "");
static_assert(**(**(zs + 1) + 1) == 11, "");
static_assert(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][-1] + 1) == 11, "");
constexpr int fail(const int &p) {
- return (&p)[64]; // expected-note {{subexpression}}
+ return (&p)[64]; // expected-note {{read of dereferenced one-past-the-end pointer}}
}
static_assert(fail(*(&(&(*(*&(&zs[2] - 1)[0] + 2 - 2))[2])[-1][-1] + 1)) == 11, ""); // \
expected-error {{static_assert expression is not an integral constant expression}} \
@@ -532,10 +538,10 @@ struct G {
constexpr G() : t(&t) {}
} constexpr g;
-static_assert(g.t.u1.a == 42, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
+static_assert(g.t.u1.a == 42, ""); // expected-error {{constant expression}} expected-note {{read of member 'a' of union with active member 'b'}}
static_assert(g.t.u1.b == 42, "");
static_assert(g.t.u2.c == 42, "");
-static_assert(g.t.u2.d == 42, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
+static_assert(g.t.u2.d == 42, ""); // expected-error {{constant expression}} expected-note {{read of member 'd' of union with active member 'c'}}
struct S {
int a, b;
@@ -579,10 +585,11 @@ constexpr AggregateInit agg1 = { "hello"[0] };
static_assert(strcmp_ce(&agg1.c, "hello") == 0, "");
static_assert(agg1.n == 0, "");
static_assert(agg1.d == 0.0, "");
-static_assert(agg1.arr[-1] == 0, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
+// FIXME: check pointer arithmetic here.
+static_assert(agg1.arr[-1] == 0, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end}}
static_assert(agg1.arr[0] == 0, "");
static_assert(agg1.arr[4] == 0, "");
-static_assert(agg1.arr[5] == 0, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
+static_assert(agg1.arr[5] == 0, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end}}
static_assert(agg1.p == nullptr, "");
namespace SimpleDerivedClass {
@@ -700,9 +707,9 @@ union U {
constexpr U u[4] = { { .a = 0 }, { .b = 1 }, { .a = 2 }, { .b = 3 } }; // expected-warning 4{{extension}}
static_assert(u[0].a == 0, "");
-static_assert(u[0].b, ""); // expected-error {{constant expression}}
+static_assert(u[0].b, ""); // expected-error {{constant expression}} expected-note {{read of member 'b' of union with active member 'a'}}
static_assert(u[1].b == 1, "");
-static_assert((&u[1].b)[1] == 2, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
+static_assert((&u[1].b)[1] == 2, ""); // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
static_assert(*(&(u[1].b) + 1 + 1) == 3, ""); // expected-error {{constant expression}} expected-note {{subexpression}}
static_assert((&(u[1]) + 1 + 1)->b == 3, "");
@@ -830,9 +837,10 @@ namespace ArrayBaseDerived {
constexpr Derived *pd9 = pd6 + 3;
constexpr Derived *pd10 = pd6 + 4;
constexpr int pd9n = pd9->n; // ok
- constexpr int err_pd10n = pd10->n; // expected-error {{constant expression}}
+ constexpr int err_pd10n = pd10->n; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
constexpr int pd0n = pd10[-10].n;
- constexpr int err_pdminus1n = pd10[-11].n; // expected-error {{constant expression}}
+ // FIXME: check pointer arithmetic here.
+ constexpr int err_pdminus1n = pd10[-11].n; // expected-error {{constant expression}} expected-note {{read of dereferenced one-past-the-end pointer}}
constexpr Base *pb9 = pd9;
constexpr const int *(Base::*pfb)() const =
@@ -917,3 +925,26 @@ namespace ExprWithCleanups {
constexpr int get(bool FromA) { return FromA ? A().get() : 1; }
constexpr int n = get(false);
}
+
+namespace Volatile {
+
+volatile constexpr int n1 = 0; // expected-note {{here}}
+volatile const int n2 = 0; // expected-note {{here}}
+int n3 = 37; // expected-note {{declared here}}
+
+constexpr int m1 = n1; // expected-error {{constant expression}} expected-note {{read of volatile object 'n1'}}
+constexpr int m2 = n2; // expected-error {{constant expression}} expected-note {{read of volatile object 'n2'}}
+
+struct T { int n; };
+const T t = { 42 }; // expected-note {{declared here}}
+
+constexpr int f(volatile int &&r) {
+ return r; // expected-note {{read of volatile temporary is not allowed in a constant expression}}
+}
+struct S {
+ int k : f(0); // expected-error {{constant expression}} expected-note {{temporary created here}} expected-note {{in call to 'f(0)'}}
+ int l : n3; // expected-error {{constant expression}} expected-note {{read of non-const variable}}
+ int m : t.n; // expected-error {{constant expression}} expected-note {{read of non-constexpr variable}}
+};
+
+}
diff --git a/clang/test/SemaCXX/constexpr-printing.cpp b/clang/test/SemaCXX/constexpr-printing.cpp
index 726d1770fae..e6cf209819a 100644
--- a/clang/test/SemaCXX/constexpr-printing.cpp
+++ b/clang/test/SemaCXX/constexpr-printing.cpp
@@ -9,10 +9,8 @@ struct S {
int n, m;
};
-constexpr int extract(const S &s) { return s.n; } // expected-note {{subexpression}}
+constexpr int extract(const S &s) { return s.n; } // expected-note {{read of uninitialized object is not allowed in a constant expression}}
-// FIXME: once we produce notes for constexpr variable declarations, this should
-// produce a note indicating that S.n is used uninitialized.
constexpr S s1; // expected-error {{constant expression}} expected-note {{in call to 'S()'}}
constexpr S s2(10);
@@ -32,9 +30,9 @@ constexpr U u1(&u1.arr[2]);
constexpr int test_printing(int a, float b, _Complex int c, _Complex float d,
int *e, int &f, vector_int g, U h) {
- return *e; // expected-note {{subexpression}}
+ return *e; // expected-note {{read of non-constexpr variable 'u2'}}
}
-U u2(0);
+U u2(0); // expected-note {{here}}
static_assert(test_printing(12, 39.762, 3 + 4i, 12.9 + 3.6i, &u2.arr[4], u2.another.arr[2], (vector_int){5, 1, 2, 3}, u1) == 0, ""); // \
expected-error {{constant expression}} \
expected-note {{in call to 'test_printing(12, 3.976200e+01, 3+4i, 1.290000e+01+3.600000e+00i, &u2.T::arr[4], u2.another.arr[2], {5, 1, 2, 3}, {{{}}, {{}}, &u1.T::arr[2]})'}}
@@ -47,7 +45,7 @@ struct V {
int arr[256];
};
constexpr V v;
-constexpr int get(const int *p) { return *p; } // expected-note {{subexpression}}
+constexpr int get(const int *p) { return *p; } // expected-note {{read of dereferenced one-past-the-end pointer}}
constexpr int passLargeArray(V v) { return get(v.arr+256); } // expected-note {{in call to 'get(&v.arr[256])'}}
static_assert(passLargeArray(v) == 0, ""); // expected-error {{constant expression}} expected-note {{in call to 'passLargeArray({{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...}})'}}
@@ -58,7 +56,7 @@ union Union {
};
constexpr Union myUnion = 76;
-constexpr int badness(Union u) { return u.a + u.b; } // expected-note {{subexpression}}
+constexpr int badness(Union u) { return u.a + u.b; } // expected-note {{read of member 'a' of union with active member 'b'}}
static_assert(badness(myUnion), ""); // expected-error {{constant expression}} \
expected-note {{in call to 'badness({.b = 76})'}}
@@ -66,9 +64,9 @@ struct MemPtrTest {
int n;
void f();
};
-MemPtrTest mpt;
+MemPtrTest mpt; // expected-note {{here}}
constexpr int MemPtr(int (MemPtrTest::*a), void (MemPtrTest::*b)(), int &c) {
- return c; // expected-note {{subexpression}}
+ return c; // expected-note {{read of non-constexpr variable 'mpt'}}
}
static_assert(MemPtr(&MemPtrTest::n, &MemPtrTest::f, mpt.*&MemPtrTest::n), ""); // expected-error {{constant expression}} \
expected-note {{in call to 'MemPtr(&MemPtrTest::n, &MemPtrTest::f, mpt.n)'}}
OpenPOWER on IntegriCloud