https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116317
Nathaniel Shead <nshead at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |nshead at gcc dot gnu.org --- Comment #8 from Nathaniel Shead <nshead at gcc dot gnu.org> --- The root cause is that 'sort_cluster' is not correctly ordering the dependencies; both the element_t specialisation and the reverse_adaptor::first function decl depend on each other, but by streaming element_t first it ends up trying to stream itself recursively as part of calculating its own merge key, which apart from the checking ICE will also cause issues on stream-in. There is a comment in the source file describing this very issue: /* Now rewrite entries [0,lwm), in the dependency order we discovered. Usually each entity is in its own cluster. Rarely, we can get multi-entity clusters, in which case all but one must only be reached from within the cluster. This happens for something like: template<typename T> auto Foo (const T &arg) -> TPL<decltype (arg)>; The instantiation of TPL will be in the specialization table, and refer to Foo via arg. But we can only get to that specialization from Foo's declaration, so we only need to treat Foo as mergable (We'll do structural comparison of TPL<decltype (arg)>). Finding the single cluster entry dep is very tricky and expensive. Let's just not do that. It's harmless in this case anyway. */ However, as this PR shows it's not harmless; it's somewhat just luck that the (consistent) sort happens to work for the existing cases in the testsuite (modules/late-ret*). Finding the single cluster entry dep in sort_cluster is probably already too late, since if this is the only cluster in the SCC we don't have any information about which deps reference us. And we probably want to be sorted correctly even before we hit sort_cluster so that we ensure we never hit this ICE from within the sort_cluster find_dependencies walk. I have a couple of hacky solutions for this specific issue, including guessing that any declaration first found via a merge-key walk is not the entry dep, but I'm not convinced I have a general solution yet that won't be very expensive.