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