llvm-project/clang/test/SemaCXX/constexpr-printing.cpp
Richard Smith 0c6124ba82 PR17381: Treat undefined behavior during expression evaluation as an unmodeled
side-effect, so that we don't allow speculative evaluation of such expressions
during code generation.

This caused a diagnostic quality regression, so fix constant expression
diagnostics to prefer either the first "can't be constant folded" diagnostic or
the first "not a constant expression" diagnostic depending on the kind of
evaluation we're doing. This was always the intent, but didn't quite work
correctly before.

This results in certain initializers that used to be constant initializers to
no longer be; in particular, things like:

  float f = 1e100;

are no longer accepted in C. This seems appropriate, as such constructs would
lead to code being executed if sanitizers are enabled.

llvm-svn: 254574
2015-12-03 01:36:22 +00:00

105 lines
4.6 KiB
C++

// RUN: %clang_cc1 %s -std=c++11 -fsyntax-only -verify -triple x86_64-linux-gnu
struct S;
constexpr int extract(const S &s);
struct S {
constexpr S() : n(extract(*this)), m(0) {} // expected-note {{in call to 'extract(s1)'}}
constexpr S(int k) : n(k), m(extract(*this)) {}
int n, m;
};
constexpr int extract(const S &s) { return s.n; } // expected-note {{read of object outside its lifetime is not allowed in a constant expression}}
constexpr S s1; // ok
void f() {
constexpr S s1; // expected-error {{constant expression}} expected-note {{in call to 'S()'}}
constexpr S s2(10);
}
typedef __attribute__((vector_size(16))) int vector_int;
struct T {
constexpr T() : arr() {}
int arr[4];
};
struct U : T {
constexpr U(const int *p) : T(), another(), p(p) {}
constexpr U(const U &u) : T(), another(), p(u.p) {}
T another;
const int *p;
};
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 {{read of non-constexpr variable 'u2'}}
}
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]})'}}
struct V {
// FIXME: when we can generate these as constexpr constructors, remove the
// explicit definitions.
constexpr V() : arr{[255] = 42} {}
constexpr V(const V &v) : arr{[255] = 42} {}
int arr[256];
};
constexpr V v;
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, ...}})'}}
union Union {
constexpr Union(int n) : b(n) {}
constexpr Union(const Union &u) : b(u.b) {}
int a, b;
};
constexpr Union myUnion = 76;
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})'}}
struct MemPtrTest {
int n;
void f();
};
MemPtrTest mpt; // expected-note {{here}}
constexpr int MemPtr(int (MemPtrTest::*a), void (MemPtrTest::*b)(), int &c) {
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)'}}
template<typename CharT>
constexpr CharT get(const CharT *p) { return p[-1]; } // expected-note 5{{}}
constexpr char c = get("test\0\\\"\t\a\b\234"); // \
expected-error {{}} expected-note {{"test\000\\\"\t\a\b\234"}}
constexpr char c8 = get(u8"test\0\\\"\t\a\b\234"); // \
expected-error {{}} expected-note {{u8"test\000\\\"\t\a\b\234"}}
constexpr char16_t c16 = get(u"test\0\\\"\t\a\b\234\u1234"); // \
expected-error {{}} expected-note {{u"test\000\\\"\t\a\b\234\u1234"}}
constexpr char32_t c32 = get(U"test\0\\\"\t\a\b\234\u1234\U0010ffff"); // \
expected-error {{}} expected-note {{U"test\000\\\"\t\a\b\234\u1234\U0010FFFF"}}
constexpr wchar_t wc = get(L"test\0\\\"\t\a\b\234\u1234\xffffffff"); // \
expected-error {{}} expected-note {{L"test\000\\\"\t\a\b\234\x1234\xFFFFFFFF"}}
constexpr char32_t c32_err = get(U"\U00110000"); // expected-error {{invalid universal character}}
#define fold(x) (__builtin_constant_p(x) ? (x) : (x))
typedef decltype(sizeof(int)) LabelDiffTy;
constexpr LabelDiffTy mulBy3(LabelDiffTy x) { return x * 3; } // expected-note {{subexpression}}
void LabelDiffTest() {
static_assert(mulBy3(fold((LabelDiffTy)&&a-(LabelDiffTy)&&b)) == 3, ""); // expected-error {{constant expression}} expected-note {{call to 'mulBy3(&&a - &&b)'}}
a:b:return;
}
constexpr bool test_bool_printing(bool b) { return 1 / !(2*b | !(2*b)); } // expected-note 2{{division by zero}}
constexpr bool test_bool_0 = test_bool_printing(false); // expected-error {{constant expr}} expected-note {{in call to 'test_bool_printing(false)'}}
constexpr bool test_bool_1 = test_bool_printing(true); // expected-error {{constant expr}} expected-note {{in call to 'test_bool_printing(true)'}}