File: cxx23-invalid-constexpr.cpp

package info (click to toggle)
llvm-toolchain-19 1%3A19.1.7-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,998,520 kB
  • sloc: cpp: 6,951,680; ansic: 1,486,157; asm: 913,598; python: 232,024; f90: 80,126; objc: 75,281; lisp: 37,276; pascal: 16,990; sh: 10,009; ml: 5,058; perl: 4,724; awk: 3,523; makefile: 3,167; javascript: 2,504; xml: 892; fortran: 664; cs: 573
file content (159 lines) | stat: -rw-r--r-- 4,532 bytes parent folder | download | duplicates (3)
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
159
// 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() {}
};

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

constexpr int F2(NonLiteral N) {
  return 8;
}

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

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


struct X {
  X();
  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 {{non-literal type '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}}
                            // expected-note@-1 {{non-literal type 'NonLiteral' cannot be used in 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{{non-literal}}
}

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(); }