aboutsummaryrefslogtreecommitdiff
path: root/clang/test/AST/ByteCode/cxx17.cpp
blob: 0cf3a4f666d631a362bcdfc1a3097921707cae24 (plain)
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);
  }
}