summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorRichard Smith <richard@metafoo.co.uk>2019-12-10 19:20:46 -0800
committerRichard Smith <richard@metafoo.co.uk>2019-12-10 19:28:30 -0800
commit8e0c9e21bf5f3e7a427b07e3eaf3bc80d2c74cb6 (patch)
treee8d27fae2f59ff1fb3df95fdb69dcbe1fd8de278 /clang/test
parentaf3aac9a227eaf38b625137b7337365b32404068 (diff)
downloadbcm5719-llvm-8e0c9e21bf5f3e7a427b07e3eaf3bc80d2c74cb6.tar.gz
bcm5719-llvm-8e0c9e21bf5f3e7a427b07e3eaf3bc80d2c74cb6.zip
[c++20] Delete defaulted comparison functions if they would invoke an
inaccessible comparison function.
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/class/class.compare/class.eq/p2.cpp65
-rw-r--r--clang/test/CXX/class/class.compare/class.rel/p2.cpp10
-rw-r--r--clang/test/CXX/class/class.compare/class.spaceship/p1.cpp23
3 files changed, 98 insertions, 0 deletions
diff --git a/clang/test/CXX/class/class.compare/class.eq/p2.cpp b/clang/test/CXX/class/class.compare/class.eq/p2.cpp
index 55b2cc3c08f..e5f4a020d5c 100644
--- a/clang/test/CXX/class/class.compare/class.eq/p2.cpp
+++ b/clang/test/CXX/class/class.compare/class.eq/p2.cpp
@@ -47,3 +47,68 @@ void test() {
void(X<A[3]>() == X<A[3]>()); // expected-error {{cannot be compared because its 'operator==' is implicitly deleted}}
void(X<B[3]>() == X<B[3]>());
}
+
+namespace Access {
+ class A {
+ bool operator==(const A &) const; // expected-note 2{{implicitly declared private here}}
+ };
+ struct B : A { // expected-note 2{{because it would invoke a private 'operator==' to compare base class 'A'}}
+ bool operator==(const B &) const = default; // expected-warning {{deleted}}
+ friend bool operator==(const B &, const B &) = default; // expected-warning {{deleted}}
+ };
+
+ class C {
+ protected:
+ bool operator==(const C &) const; // expected-note 2{{declared protected here}}
+ };
+ struct D : C {
+ bool operator==(const D &) const = default;
+ friend bool operator==(const D &, const D&) = default;
+ };
+ struct E {
+ C c; // expected-note 2{{because it would invoke a protected 'operator==' member of 'Access::C' to compare member 'c'}}
+ bool operator==(const E &) const = default; // expected-warning {{deleted}}
+ friend bool operator==(const E &, const E &) = default; // expected-warning {{deleted}}
+ };
+
+ struct F : C {
+ using C::operator==;
+ };
+ struct G : F {
+ bool operator==(const G&) const = default;
+ friend bool operator==(const G&, const G&) = default;
+ };
+
+ struct H : C {
+ private:
+ using C::operator==; // expected-note 2{{declared private here}}
+ };
+ struct I : H { // expected-note 2{{private 'operator==' to compare base class 'H'}}
+ bool operator==(const I&) const = default; // expected-warning {{deleted}}
+ friend bool operator==(const I&, const I&) = default; // expected-warning {{deleted}}
+ };
+
+ class J {
+ bool operator==(const J&) const;
+ friend class K;
+ };
+ class K {
+ J j;
+ bool operator==(const K&) const = default;
+ friend bool operator==(const K&, const K&) = default;
+ };
+
+ struct X {
+ bool operator==(const X&) const; // expected-note {{ambiguity is between a regular call to this operator and a call with the argument order reversed}}
+ };
+ struct Y : private X { // expected-note {{private}}
+ using X::operator==;
+ };
+ struct Z : Y {
+ // Note: this function is not deleted. The selected operator== is
+ // accessible. But the derived-to-base conversion involves an inaccessible
+ // base class, which we don't check for until we define the function.
+ bool operator==(const Z&) const = default; // expected-error {{cannot cast 'const Access::Y' to its private base class 'const Access::X'}} expected-warning {{ambiguous}}
+ };
+ bool z = Z() == Z(); // expected-note {{first required here}}
+}
diff --git a/clang/test/CXX/class/class.compare/class.rel/p2.cpp b/clang/test/CXX/class/class.compare/class.rel/p2.cpp
index 2abe7fb8d79..21a68f9f4c6 100644
--- a/clang/test/CXX/class/class.compare/class.rel/p2.cpp
+++ b/clang/test/CXX/class/class.compare/class.rel/p2.cpp
@@ -72,3 +72,13 @@ namespace NotEqual {
bool operator!=(const Evil&) const = default; // expected-warning {{implicitly deleted}} expected-note {{would be the best match}}
};
}
+
+namespace Access {
+ class A {
+ int operator<=>(A) const; // expected-note {{private}}
+ };
+ struct B : A {
+ friend bool operator<(const B&, const B&) = default; // expected-warning {{implicitly deleted}}
+ // expected-note@-1 {{defaulted 'operator<' is implicitly deleted because it would invoke a private 'operator<=>' member of 'Access::A'}}
+ };
+}
diff --git a/clang/test/CXX/class/class.compare/class.spaceship/p1.cpp b/clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
index a131842d394..7768e84323d 100644
--- a/clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
+++ b/clang/test/CXX/class/class.compare/class.spaceship/p1.cpp
@@ -141,6 +141,29 @@ namespace Deletedness {
}
}
+namespace Access {
+ class A {
+ std::strong_ordering operator<=>(const A &) const; // expected-note {{here}}
+ public:
+ bool operator==(const A &) const;
+ bool operator<(const A &) const;
+ };
+ struct B {
+ A a; // expected-note {{would invoke a private 'operator<=>'}}
+ friend std::strong_ordering operator<=>(const B &, const B &) = default; // expected-warning {{deleted}}
+ };
+
+ class C {
+ std::strong_ordering operator<=>(const C &); // not viable (not const)
+ bool operator==(const C &) const; // expected-note {{here}}
+ bool operator<(const C &) const;
+ };
+ struct D {
+ C c; // expected-note {{would invoke a private 'operator=='}}
+ friend std::strong_ordering operator<=>(const D &, const D &) = default; // expected-warning {{deleted}}
+ };
+}
+
namespace Synthesis {
enum Result { False, True, Mu };
OpenPOWER on IntegriCloud