aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-08-12 09:16:13 +0200
committerJakub Jelinek <jakub@redhat.com>2021-08-12 09:34:16 +0200
commit9b7ab853bf33106fd0539e36d6ce7730269026e1 (patch)
treecd246195e79ecfddde3abe1930acea5e5083e592
parentc84f79e9e3f63e9ae447fd15dbd0a768cab3f643 (diff)
downloadgcc-9b7ab853bf33106fd0539e36d6ce7730269026e1.zip
gcc-9b7ab853bf33106fd0539e36d6ce7730269026e1.tar.gz
gcc-9b7ab853bf33106fd0539e36d6ce7730269026e1.tar.bz2
c++: Fix ICE on defaulted spaceship with pointer return type [PR94162]
The spaceship-synth-neg6.C testcase ICEs because we call cat_tag_for on the explicit return type, but pointer types don't have TYPE_LINKAGE_IDENTIFIER. The patch fixes that by checking for CLASS_TYPE_P only and also adds verification that it is in std namespace, so we don't return non-cc_last for my_namespace::partial_ordering. The g++.dg/cpp2a/spaceship-synth11.C testcase is from a PR that has been fixed with r12-619-gfc178519771db508c03611cff4a1466cf67fce1d (but not backported to 11). 2021-08-12 Jakub Jelinek <jakub@redhat.com> gcc/cp/ PR c++/94162 * method.c (cat_tag_for): Return cc_last for !CLASS_TYPE_P or for classes not in std namespace. gcc/testsuite/ PR c++/99429 * g++.dg/cpp2a/spaceship-synth11.C: New test. PR c++/94162 * g++.dg/cpp2a/spaceship-synth-neg6.C: New test.
-rw-r--r--gcc/cp/method.c2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg6.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-synth11.C29
3 files changed, 42 insertions, 0 deletions
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index f268aab..353046d 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1029,6 +1029,8 @@ is_cat (tree type, comp_cat_tag tag)
static comp_cat_tag
cat_tag_for (tree type)
{
+ if (!CLASS_TYPE_P (type) || !decl_in_std_namespace_p (TYPE_MAIN_DECL (type)))
+ return cc_last;
for (int i = 0; i < cc_last; ++i)
{
comp_cat_tag tag = (comp_cat_tag)i;
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg6.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg6.C
new file mode 100644
index 0000000..d3f95e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg6.C
@@ -0,0 +1,11 @@
+// PR c++/94162
+// { dg-do compile { target c++20 } }
+
+#include <compare>
+
+struct S {
+ int a; // { dg-error "three-way comparison of 'S::a' has type 'std::strong_ordering', which does not convert to 'int\\*'" }
+ int *operator<=>(const S&) const = default;
+};
+
+bool b = S{} < S{}; // { dg-error "use of deleted function 'constexpr int\\* S::operator<=>\\\(const S&\\\) const'" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-synth11.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth11.C
new file mode 100644
index 0000000..37c8157
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-synth11.C
@@ -0,0 +1,29 @@
+// PR c++/99429
+// { dg-do compile { target c++20 } }
+
+namespace std {
+struct strong_ordering {
+ int _v;
+ constexpr strong_ordering (int v) :_v(v) {}
+ constexpr operator int (void) const { return _v; }
+ static const strong_ordering less;
+ static const strong_ordering equal;
+ static const strong_ordering greater;
+};
+constexpr strong_ordering strong_ordering::less = -1;
+constexpr strong_ordering strong_ordering::equal = 0;
+constexpr strong_ordering strong_ordering::greater = 1;
+}
+
+template <unsigned long N>
+struct duration {
+ static constexpr const long period = N;
+ constexpr duration (void) = default;
+ constexpr duration (const duration& d) = default;
+ constexpr bool operator== (const duration& d) const = default;
+ constexpr bool operator<=> (const duration& d) const = default;
+ long _d;
+};
+
+using nanoseconds = duration<1>;
+using microseconds = duration<nanoseconds::period * 1000>;