File: p1.cpp

package info (click to toggle)
llvm-toolchain-15 1%3A15.0.6-4
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 1,554,644 kB
  • sloc: cpp: 5,922,452; ansic: 1,012,136; asm: 674,362; python: 191,568; objc: 73,855; f90: 42,327; lisp: 31,913; pascal: 11,973; javascript: 10,144; sh: 9,421; perl: 7,447; ml: 5,527; awk: 3,523; makefile: 2,520; xml: 885; cs: 573; fortran: 567
file content (222 lines) | stat: -rw-r--r-- 8,119 bytes parent folder | download | duplicates (4)
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// RUN: %clang_cc1 -std=c++2a -verify %s

struct B {};

template<typename T = void>
  bool operator<(const B&, const B&) = default; // expected-error {{comparison operator template cannot be defaulted}}

struct A {
  friend bool operator==(const A&, const A&) = default;
  friend bool operator!=(const A&, const B&) = default; // expected-error {{parameters for defaulted equality comparison operator must have the same type (found 'const A &' vs 'const B &')}}
  friend bool operator!=(const B&, const B&) = default; // expected-error {{invalid parameter type for defaulted equality comparison}}
  friend bool operator<(const A&, const A&);
  friend bool operator<(const B&, const B&) = default; // expected-error {{invalid parameter type for defaulted relational comparison}}
  friend bool operator>(A, A) = default; // expected-warning {{implicitly deleted}}

  bool operator<(const A&) const;
  bool operator<=(const A&) const = default;
  bool operator==(const A&) const volatile && = default; // surprisingly, OK
  bool operator<=>(const A&) = default; // expected-error {{defaulted member three-way comparison operator must be const-qualified}}
  bool operator>=(const B&) const = default; // expected-error-re {{invalid parameter type for defaulted relational comparison operator; found 'const B &', expected 'const A &'{{$}}}}
  static bool operator>(const B&) = default; // expected-error {{overloaded 'operator>' cannot be a static member function}}
  friend bool operator>(A, const A&) = default; // expected-error {{must have the same type}} expected-note {{would be the best match}}

  template<typename T = void>
    friend bool operator==(const A&, const A&) = default; // expected-error {{comparison operator template cannot be defaulted}}
  template<typename T = void>
    bool operator==(const A&) const = default; // expected-error {{comparison operator template cannot be defaulted}}
};

template<typename T> struct Dependent {
  using U = typename T::type;
  bool operator==(U) const = default; // expected-error {{found 'Dependent<Bad>::U'}}
  friend bool operator==(U, U) = default; // expected-error {{found 'Dependent<Bad>::U'}}
};

struct Good { using type = const Dependent<Good>&; };
template struct Dependent<Good>;

struct Bad { using type = Dependent<Bad>&; };
template struct Dependent<Bad>; // expected-note {{in instantiation of}}


namespace std {
  struct strong_ordering {
    int n;
    constexpr operator int() const { return n; }
    static const strong_ordering equal, greater, less;
  };
  constexpr strong_ordering strong_ordering::equal = {0};
  constexpr strong_ordering strong_ordering::greater = {1};
  constexpr strong_ordering strong_ordering::less = {-1};
}

namespace LookupContext {
  struct A {};

  namespace N {
    template <typename T> auto f() {
      bool operator==(const T &, const T &);
      bool operator<(const T &, const T &);
      struct B {
        T a;
        std::strong_ordering operator<=>(const B &) const = default;
      };
      return B();
    }

    auto g() {
      struct Cmp { Cmp(std::strong_ordering); };
      Cmp operator<=>(const A&, const A&);
      bool operator!=(const Cmp&, int);
      struct B {
        A a;
        Cmp operator<=>(const B &) const = default;
      };
      return B();
    }

    auto h() {
      struct B;
      bool operator==(const B&, const B&);
      bool operator!=(const B&, const B&); // expected-note 2{{best match}}
      std::strong_ordering operator<=>(const B&, const B&);
      bool operator<(const B&, const B&); // expected-note 2{{best match}}
      bool operator<=(const B&, const B&); // expected-note 2{{best match}}
      bool operator>(const B&, const B&); // expected-note 2{{best match}}
      bool operator>=(const B&, const B&); // expected-note 2{{best match}}

      struct B {
        bool operator!=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
        bool operator<(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
        bool operator<=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
        bool operator>(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
        bool operator>=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}}
      };
      return B();
    }
  }

  namespace M {
    bool operator==(const A &, const A &) = delete;
    bool operator<(const A &, const A &) = delete;
    bool cmp = N::f<A>() < N::f<A>();

    void operator<=>(const A &, const A &) = delete;
    auto cmp2 = N::g() <=> N::g();

    void use_h() {
      N::h() != N::h(); // expected-error {{implicitly deleted}}
      N::h() < N::h(); // expected-error {{implicitly deleted}}
      N::h() <= N::h(); // expected-error {{implicitly deleted}}
      N::h() > N::h(); // expected-error {{implicitly deleted}}
      N::h() >= N::h(); // expected-error {{implicitly deleted}}
    }
  }
}

namespace evil1 {
template <class T> struct Bad {
  // expected-error@+1{{found 'const float &'}}
  bool operator==(T const &) const = default;
  Bad(int = 0);
};

template <class T> struct Weird {
  // expected-error@+1{{'float' cannot be used prior to '::'}}
  bool operator==(typename T::Weird_ const &) const = default;
  Weird(int = 0);
};

struct evil {
  using Weird_ = Weird<evil>;
};
template struct Bad<float>;   // expected-note{{evil1::Bad<float>' requested}}
template struct Weird<float>; // expected-note{{evil1::Weird<float>' requested}}
template struct Weird<evil>;

} // namespace evil1

namespace P1946 {
  struct A {
    friend bool operator==(A &, A &); // expected-note {{would lose const qualifier}}
  };
  struct B {
    A a; // expected-note {{no viable three-way comparison}}
    friend bool operator==(B, B) = default; // ok
    friend bool operator==(const B&, const B&) = default; // expected-warning {{deleted}}
  };
}

namespace p2085 {
// out-of-class defaulting

struct S1 {
  bool operator==(S1 const &) const;
};

bool S1::operator==(S1 const &) const = default;

bool F1(S1 &s) {
  return s != s;
}

struct S2 {
  friend bool operator==(S2 const &, S2 const &);
};

bool operator==(S2 const &, S2 const &) = default;
bool F2(S2 &s) {
  return s != s;
}

struct S3 {};                                      // expected-note{{here}}
bool operator==(S3 const &, S3 const &) = default; // expected-error{{not a friend}}

struct S4;                                         // expected-note{{forward declaration}}
bool operator==(S4 const &, S4 const &) = default; // expected-error{{not a friend}}

struct S5;                         // expected-note 3{{forward declaration}}
bool operator==(S5, S5) = default; // expected-error{{not a friend}} expected-error 2{{has incomplete type}}

enum e {};
bool operator==(e, int) = default; // expected-error{{expected class or reference to a constant class}}

bool operator==(e *, int *) = default; // expected-error{{must have at least one}}
} // namespace p2085

namespace p2085_2 {
template <class T> struct S6 {
  // expected-error@+2{{found 'const int &'}}
  // expected-error@+1{{found 'const float &'}}
  bool operator==(T const &) const;
};
template <class T> bool S6<T>::operator==(T const &) const = default;

template struct S6<int>; // expected-note{{S6<int>::operator==' requested}}

void f1() {
  S6<float> a;
  (void)(a == 0); // expected-note{{S6<float>::operator==' requested}}
}

template <class T> struct S7 {
  // expected-error@+2{{'float' cannot be used}}
  // expected-error@+1{{'int' cannot be used}}
  bool operator==(typename T::S7_ const &) const;
  S7(int = 0);
};
template <class T> bool S7<T>::operator==(typename T::S7_ const &) const = default;

struct evil {
  using S7_ = S7<evil>;
};
template struct S7<float>; // expected-note{{S7<float>' requested}}

void f2() {
  S7<int> a; // expected-note{{S7<int>' requested}}
  S7<evil> b;
  (void)(a == 0); // expected-error{{invalid operands}}
  (void)(b == 0);
}
} // namespace p2085_2