aboutsummaryrefslogtreecommitdiff
path: root/clang/test/SemaCXX/cxx23-invalid-constexpr.cpp
blob: 3229a91fbcefbbac9bdd473c3b5317a1242433a4 (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
152
153
154
155
156
157
158
// RUN: %clang_cc1 -fsyntax-only -verify=expected -std=c++23 %s

// This test covers modifications made by P2448R2.

// Check that there is no error when a constexpr function that never produces a
// constant expression, but still an error if such function is called from
// constexpr context.
constexpr int F(int N) {
  double D = 2.0 / 0.0; // expected-note {{division by zero}}
  return 1;
}

constexpr int F0(int N) {
  if (N == 0)
    double d2 = 2.0 / 0.0; // expected-note {{division by zero}}
  return 1;
}

template <typename T>
constexpr int FT(T N) {
  double D = 2.0 / 0.0; // expected-note {{division by zero}}
  return 1;
}

class NonLiteral { // expected-note {{'NonLiteral' is not literal because it is not an aggregate and has no constexpr constructors}}
public:
  NonLiteral() {}
  ~NonLiteral() {} // expected-note {{declared here}}
};

constexpr NonLiteral F1() {
  return NonLiteral{};
}

constexpr int F2(NonLiteral N) { // expected-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}}
  return 8;
}

class Derived : public NonLiteral {
  constexpr ~Derived() {};
};

class Derived1 : public NonLiteral {
  constexpr Derived1() : NonLiteral () {}
};


struct X {
  X(); // expected-note 2{{declared here}}
  X(const X&);
  X(X&&);
  X& operator=(X&);
  X& operator=(X&& other);
  bool operator==(X const&) const;
};

template <typename T>
struct Wrapper {
  constexpr Wrapper() = default;
  constexpr Wrapper(Wrapper const&) = default;
  constexpr Wrapper(T const& t) : t(t) { }
  constexpr Wrapper(Wrapper &&) = default;
  constexpr X get() const { return t; }
  constexpr bool operator==(Wrapper const&) const = default;
  private:
  T t;
};

struct WrapperNonT {
  constexpr WrapperNonT() = default;
  constexpr WrapperNonT(WrapperNonT const&) = default;
  constexpr WrapperNonT(X const& t) : t(t) { }
  constexpr WrapperNonT(WrapperNonT &&) = default;
  constexpr WrapperNonT& operator=(WrapperNonT &) = default;
  constexpr WrapperNonT& operator=(WrapperNonT&& other) = default;
  constexpr X get() const { return t; }
  constexpr bool operator==(WrapperNonT const&) const = default;
  private:
  X t;
};

struct NonDefaultMembers {
  constexpr NonDefaultMembers() {}; // expected-note 2{{non-constexpr constructor 'X' cannot be used in a constant expression}}
  constexpr NonDefaultMembers(NonDefaultMembers const&) {};
  constexpr NonDefaultMembers(NonDefaultMembers &&) {};
  constexpr NonDefaultMembers& operator=(NonDefaultMembers &other) {this->t = other.t; return *this;}
  constexpr NonDefaultMembers& operator=(NonDefaultMembers&& other) {this->t = other.t; return *this;}
  constexpr bool operator==(NonDefaultMembers const& other) const {return this->t == other.t;}
  X t;
};

int Glob = 0;
class C1 {
public:
  constexpr C1() : D(Glob) {};
private:
  int D;
};

void test() {

  constexpr int A = F(3); // expected-error {{constexpr variable 'A' must be initialized by a constant expression}}
                          // expected-note@-1 {{in call}}
  F(3);
  constexpr int B = F0(0); // expected-error {{constexpr variable 'B' must be initialized by a constant expression}}
                           // expected-note@-1 {{in call}}
  F0(0);
  constexpr auto C = F1(); // expected-error {{constexpr variable cannot have non-literal type 'const NonLiteral'}}
  F1();
  NonLiteral L;
  constexpr auto D = F2(L); // expected-error {{constexpr variable 'D' must be initialized by a constant expression}}

  constexpr auto E = FT(1); // expected-error {{constexpr variable 'E' must be initialized by a constant expression}}
                            // expected-note@-1 {{in call}}
  F2(L);

  Wrapper<X> x;
  WrapperNonT x1;
  NonDefaultMembers x2;

  // TODO these produce notes with an invalid source location.
  // static_assert((Wrapper<X>(), true));
  // static_assert((WrapperNonT(), true),"");

  static_assert((NonDefaultMembers(), true),""); // expected-error{{expression is not an integral constant expression}} \
                                                 // expected-note {{in call to}}
  constexpr bool FFF = (NonDefaultMembers() == NonDefaultMembers()); // expected-error {{must be initialized by a constant expression}} \
								     // expected-note {{in call to 'NonDefaultMembers()'}}
}

struct A {
  A ();
  ~A();
};

template <class T>
struct opt
{
  union {
    char c;
    T data;
  };

  constexpr opt() {}

  constexpr ~opt()  {
   if (engaged)
     data.~T();
 }

  bool engaged = false;
};

consteval void foo() {
  opt<A> a;
}

void bar() { foo(); }