From 9b7ab853bf33106fd0539e36d6ce7730269026e1 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Thu, 12 Aug 2021 09:16:13 +0200 Subject: [PATCH] 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 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. --- gcc/cp/method.c | 2 ++ gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg6.C | 11 +++++++++ gcc/testsuite/g++.dg/cpp2a/spaceship-synth11.C | 29 +++++++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg6.C create mode 100644 gcc/testsuite/g++.dg/cpp2a/spaceship-synth11.C 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 + +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 +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; -- 2.7.4