diff options
author | Jakub Jelinek <jakub@redhat.com> | 2021-08-12 09:16:13 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2021-08-12 09:34:16 +0200 |
commit | 9b7ab853bf33106fd0539e36d6ce7730269026e1 (patch) | |
tree | cd246195e79ecfddde3abe1930acea5e5083e592 | |
parent | c84f79e9e3f63e9ae447fd15dbd0a768cab3f643 (diff) | |
download | gcc-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.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/spaceship-synth-neg6.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/spaceship-synth11.C | 29 |
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>; |