1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
// RUN: %clang_cc1 -std=c++17 -verify=expected,both %s -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 -std=c++17 -verify=ref,both %s
[[clang::require_constant_initialization]] int cc = cc; // both-error {{variable does not have a constant initializer}} \
// both-note {{attribute here}} \
// both-note {{ead of object outside its lifetime}}
struct F { int a; int b;};
constexpr F getF() {
return {12, 3};
}
constexpr int f() {
auto [a1, b1] = getF();
auto [a2, b2] = getF();
return a1 + a2 + b1 + b2;
}
static_assert(f() == 30);
constexpr int structRefs() {
const auto &[a, b] = getF();
return a + b;
}
static_assert(structRefs() == 15);
constexpr int structRefs2() {
F f = getF();
const auto &[a, b] = f;
return a + b;
}
static_assert(structRefs2() == 15);
template<typename T>
struct Tuple {
T first;
T second;
constexpr Tuple(T a, T b) : first(a), second(b) {}
};
template<typename T>
constexpr T addTuple(const Tuple<T> &Tu) {
auto [a, b] = Tu;
return a + b;
}
template<typename T>
constexpr T addTuple2(const Tuple<T> &Tu) {
auto [a, b] = Tu;
return Tu.first + Tu.second;
}
constexpr Tuple<int> T1 = Tuple(1,2);
static_assert(addTuple(T1) == 3);
static_assert(addTuple2(T1) == 3);
constexpr Tuple<short> T2 = Tuple<short>(11,2);
static_assert(addTuple(T2) == 13);
static_assert(addTuple2(T2) == 13);
constexpr int Modify() {
auto T = Tuple<int>(10, 20);
auto &[x, y] = T;
x += 1;
y += 1;
return T.first + T.second;
}
static_assert(Modify() == 32, "");
constexpr int a() {
int a[2] = {5, 3};
auto [x, y] = a;
return x + y;
}
static_assert(a() == 8);
constexpr int b() {
int a[2] = {5, 3};
auto &[x, y] = a;
x += 1;
y += 2;
return a[0] + a[1];
}
static_assert(b() == 11);
namespace cwg1872 {
template<typename T> struct A : T {
constexpr int f() const { return 0; }
};
struct X {};
struct Y { virtual int f() const; };
struct Z : virtual X {};
constexpr int z = A<Z>().f(); // both-error {{must be initialized by a constant expression}} \
// both-note {{non-literal type 'A<Z>' cannot be used in a constant expression}}
}
/// The diagnostics between the two interpreters used to be different here.
struct S { int a; };
constexpr S getS() { // both-error {{constexpr function never produces a constant expression}}
(void)(1/0); // both-note 2{{division by zero}} \
// both-warning {{division by zero}}
return S{12};
}
constexpr S s = getS(); // both-error {{must be initialized by a constant expression}} \
// both-note {{in call to 'getS()'}} \
// both-note {{declared here}}
static_assert(s.a == 12, ""); // both-error {{not an integral constant expression}} \
// both-note {{initializer of 's' is not a constant expression}}
using size_t = decltype(sizeof(0));
namespace std { template<typename T> struct tuple_size; }
namespace std { template<size_t, typename> struct tuple_element; }
namespace constant {
struct Q {};
template<int N> constexpr int get(Q &&) { return N * N; }
}
template<> struct std::tuple_size<constant::Q> { static const int value = 3; };
template<int N> struct std::tuple_element<N, constant::Q> { typedef int type; };
namespace constant {
Q q;
constexpr bool f() {
auto [a, b, c] = q;
return a == 0 && b == 1 && c == 4;
}
static_assert(f());
}
template <int a> struct i; // both-note {{template is declared here}}
template <> struct i<0> {};
template <int x> constexpr auto c() {
i<x> g; // both-error {{implicit instantiation of undefined template 'i<1>'}}
return 0;
}
auto y = c<1>(); // both-note {{in instantiation of function template specialization 'c<1>' requested here}}
namespace NonConstexprStructuredBinding {
void f1() {
int arr[2] = {};
auto [a, b] = arr;
static_assert(&a != &b);
}
}
|