// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=expected,both %s // RUN: %clang_cc1 -std=c++17 -verify=ref,both %s 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 struct Tuple { T first; T second; constexpr Tuple(T a, T b) : first(a), second(b) {} }; template constexpr T addTuple(const Tuple &Tu) { auto [a, b] = Tu; return a + b; } template constexpr T addTuple2(const Tuple &Tu) { auto [a, b] = Tu; return Tu.first + Tu.second; } constexpr Tuple T1 = Tuple(1,2); static_assert(addTuple(T1) == 3); static_assert(addTuple2(T1) == 3); constexpr Tuple T2 = Tuple(11,2); static_assert(addTuple(T2) == 13); static_assert(addTuple2(T2) == 13); constexpr int Modify() { auto T = Tuple(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 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().f(); // both-error {{must be initialized by a constant expression}} \ // both-note {{non-literal type 'A' 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 struct tuple_size; } namespace std { template struct tuple_element; } namespace constant { struct Q {}; template constexpr int get(Q &&) { return N * N; } } template<> struct std::tuple_size { static const int value = 3; }; template struct std::tuple_element { 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()); }