aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2023-05-09 15:07:00 -0400
committerPatrick Palka <ppalka@redhat.com>2023-05-09 15:07:00 -0400
commitbbb6cf926f1732559b3a8aaf2796d34e8651c066 (patch)
treea35d306cde7462a17a78dcb9550f9bb860f2fc5d /gcc
parentc13906f258fb34b3e0c90ddc8d9191dd72f3da0e (diff)
downloadgcc-bbb6cf926f1732559b3a8aaf2796d34e8651c066.zip
gcc-bbb6cf926f1732559b3a8aaf2796d34e8651c066.tar.gz
gcc-bbb6cf926f1732559b3a8aaf2796d34e8651c066.tar.bz2
c++: error-recovery ICE with unstable satisfaction [PR109752]
After diagnosing and recovering from unstable satisfaction, it's possible to evaluate an atom for the first time noisily rather than quietly. The satisfaction cache tries to handle this situation gracefully, but apparently not gracefully enough: we inserted an empty slot into the cache, and left it empty, which later makes hash_table::check_complete_insertion unhappy. This patch fixes this by removing the empty slot in this case. PR c++/109752 gcc/cp/ChangeLog: * constraint.cc (satisfaction_cache::satisfaction_cache): In the unexpected case of evaluating an atom for the first time noisily, remove the cache slot that we inserted. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/concepts-pr109752.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/constraint.cc13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr109752.C26
2 files changed, 36 insertions, 3 deletions
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 675299a..c81e024 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -2687,9 +2687,16 @@ satisfaction_cache
*slot = entry;
}
else
- /* We shouldn't get here, but if we do, let's just leave 'entry'
- empty, effectively disabling the cache. */
- return;
+ {
+ /* We're evaluating this atom for the first time, and doing so noisily.
+ This shouldn't happen outside of error recovery situations involving
+ unstable satisfaction. Let's just leave 'entry' empty, effectively
+ disabling the cache, and remove the empty slot. */
+ gcc_checking_assert (seen_error ());
+ /* Appease hash_table::check_complete_insertion. */
+ *slot = ggc_alloc<sat_entry> ();
+ sat_cache->clear_slot (slot);
+ }
}
/* Returns the cached satisfaction result if we have one and we're not
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr109752.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr109752.C
new file mode 100644
index 0000000..d54ce29
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr109752.C
@@ -0,0 +1,26 @@
+// PR c++/109752
+// { dg-do compile { target c++20 } }
+
+template <typename _Tp, typename... _Args>
+ inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
+ template<typename _Tp, typename _Up>
+ concept __weakly_eq_cmp_with
+ = requires(_Tp __t, _Up __u) { { __u != __t } ; // { dg-error "changed from" }
+ };
+ template<typename _Tp>
+ concept regular = is_constructible_v<_Tp> && __weakly_eq_cmp_with<_Tp, _Tp>;
+ template<typename _Iter> concept incrementable = true
+&& regular<_Iter>
+&& requires(_Iter __i) { { __i++ } ;}
+;
+template<typename D>
+struct iterator_interface
+{
+ friend constexpr bool operator>=(D lhs, D rhs) requires __weakly_eq_cmp_with<D, D> { return true; }
+};
+template<typename T>
+struct iterator : iterator_interface<iterator<T>>
+{
+ bool operator==(iterator) const;
+};
+static_assert(incrementable<iterator<int>>); // { dg-error "assert" }