File: p4.cpp

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (163 lines) | stat: -rw-r--r-- 5,989 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
160
161
162
163
// RUN: %clang_cc1 -std=c++2a -verify %s
// RUN: %clang_cc1 -std=c++2a -Wc++23-default-comp-relaxed-constexpr -verify=expected,extension %s

// This test is for [class.compare.default]p3 as modified and renumbered to p4
// by P2002R0.
// Also covers modifications made by P2448R2 and extension warnings

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

namespace N {
  struct A {
    friend constexpr std::strong_ordering operator<=>(const A&, const A&) = default;
  };

  constexpr bool (*test_a_not_found)(const A&, const A&) = &operator==; // expected-error {{undeclared}}

  constexpr bool operator==(const A&, const A&) noexcept;
  constexpr bool (*test_a)(const A&, const A&) noexcept = &operator==;
  static_assert((*test_a)(A(), A()));
}

struct B1 {
  virtual std::strong_ordering operator<=>(const B1&) const = default;
};
bool (B1::*test_b)(const B1&) const = &B1::operator==;

struct C1 : B1 {
  // OK, B1::operator== is virtual.
  bool operator==(const B1&) const override;
};

struct B2 {
  std::strong_ordering operator<=>(const B2&) const = default;
};

struct C2 : B2 {
  bool operator==(const B2&) const override; // expected-error {{only virtual member functions}}
};

struct D {
  std::strong_ordering operator<=>(const D&) const;
  virtual std::strong_ordering operator<=>(const struct E&) const = 0;
};
struct E : D {
  // expected-error@+2 {{only virtual member functions}}
  // expected-note@+1 {{while declaring the corresponding implicit 'operator==' for this defaulted 'operator<=>'}}
  std::strong_ordering operator<=>(const E&) const override = default;
};

struct F {
  [[deprecated("oh no")]] std::strong_ordering operator<=>(const F&) const = default; // expected-note 4{{deprecated}}
};
void use_f(F f) {
  void(f <=> f); // expected-warning {{oh no}}
  void(f < f); // expected-warning {{oh no}}
  void(f == f); // expected-warning {{oh no}}
  void(f != f); // expected-warning {{oh no}}
}

class G {
  // expected-note@+2 {{implicitly declared private here}}
  // expected-note-re@+1 {{{{^}}declared private here}}
  std::strong_ordering operator<=>(const G&) const = default;
public:
};
void use_g(G g) {
  void(g <=> g); // expected-error {{private}}
  void(g == g); // expected-error {{private}}
}

struct H {
  bool operator==(const H&) const; // extension-note {{non-constexpr comparison function declared here}}
  constexpr std::strong_ordering operator<=>(const H&) const { return std::strong_ordering::equal; }
};

struct I {
  H h; // extension-note {{non-constexpr comparison function would be used to compare member 'h'}}
  constexpr std::strong_ordering operator<=>(const I&) const = default; // extension-warning {{implicit 'operator=='  invokes a non-constexpr comparison function is a C++23 extension}}
};

struct J {
  std::strong_ordering operator<=>(const J&) const & = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}
  friend std::strong_ordering operator<=>(const J&, const J&) = default; // expected-note {{candidate function (the implicit 'operator==' for this 'operator<=>)'}}
};
void use_j(J j) {
  void(j == j); // expected-error {{ambiguous}}
}

namespace DeleteAfterFirstDecl {
  bool operator==(const struct Q&, const struct Q&);
  struct Q {
    struct X {
      friend std::strong_ordering operator<=>(const X&, const X&);
    } x; // expected-note {{no viable 'operator=='}}
    // expected-error@+1 {{defaulting the corresponding implicit 'operator==' for this defaulted 'operator<=>' would delete it after its first declaration}}
    friend std::strong_ordering operator<=>(const Q&, const Q&) = default;
  };
}

// Note, substitution here results in the second parameter of 'operator=='
// referring to the first parameter of 'operator==', not to the first parameter
// of 'operator<=>'.
// FIXME: Find a case where this matters (attribute enable_if?).
struct K {
  friend std::strong_ordering operator<=>(const K &k, decltype(k)) = default;
};
bool test_k = K() == K();

namespace NoInjectionIfOperatorEqualsDeclared {
  struct A {
    void operator==(int); // expected-note 2{{not viable}}
    std::strong_ordering operator<=>(const A&) const = default;
  };
  bool test_a = A() == A(); // expected-error {{invalid operands}}

  struct B {
    friend void operator==(int, struct Q); // expected-note 2{{not viable}}
    std::strong_ordering operator<=>(const B&) const = default;
  };
  bool test_b = B() == B(); // expected-error {{invalid operands}}

  struct C {
    void operator==(int); // expected-note 2{{not viable}}
    friend std::strong_ordering operator<=>(const C&, const C&) = default;
  };
  bool test_c = C() == C(); // expected-error {{invalid operands}}

  struct D {
    void f() {
      void operator==(const D&, int);
    }
    struct X {
      friend void operator==(const D&, int);
    };
    friend std::strong_ordering operator<=>(const D&, const D&) = default;
  };
  bool test_d = D() == D();
}

namespace GH61238 {
template <typename A> struct my_struct {
    A value; // extension-note {{non-constexpr comparison function would be used to compare member 'value'}}

    constexpr friend bool operator==(const my_struct &, const my_struct &) noexcept = default; // extension-warning {{declared constexpr but invokes a non-constexpr comparison function is a C++23 extension}}
};

struct non_constexpr_type {
    friend bool operator==(non_constexpr_type, non_constexpr_type) noexcept { // extension-note {{non-constexpr comparison function declared here}}
        return false;
    }
};

my_struct<non_constexpr_type> obj; // extension-note {{in instantiation of template class 'GH61238::my_struct<GH61238::non_constexpr_type>' requested here}}
}