https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68763
--- Comment #13 from Jakub Jelinek <jakub at gcc dot gnu.org> --- The reason for the weird behavior of build_method_type_directly are default args. We call this function with one argument list and return type etc., where one argument type in TYPE_ARG_TYPES has TREE_PURPOSE some DEFAULT_ARG. Then it is called again on another argument list and return type, but all the types are the same in there, the only difference is that the argument with default arg has different DEFAULT_ARG (and obviously the TREE_LIST nodes aren't the same either, but that is not the problem). TREE_PURPOSE of TYPE_ARG_TYPES nodes is ignored for hash value computation, the two nodes get the same hash value. But, type_list_equal compares even the TREE_PURPOSE and determines the two METHOD_TYPEs are not equal, so we create another METHOD_TYPE. Next, we in-place modify the TREE_PURPOSE in those two METHOD_TYPEs and they actually end up being the same (well, not pointer equality, but simple_cst_equal kind of equality). So, because of the in-place modifications of the default argument, we now have two different METHOD_TYPEs that compare equal and have the same hash value in the hash table, and we get pretty randomly chosen one of those. Now, the question is, do we use hash tables for the FUNCTION_TYPE/METHOD_TYPE just as a way to decrease compiler memory usage (in that case what we do is probably fine), or do we rely on it for other reasons, so that say pointer equality can be used for the "same" function types (strip_typedefs and its caller clearly relies on that, but perhaps that is a bug). If we rely on it for other reasons, then I'd be afraid we couldn't modify the default arguments in place, so we'd need to include the TREE_PURPOSE in the hash value (optionally) and build_method_type_directly again after we change the TREE_PURPOSE, so in the end such change could result in more compiler memory being used for the function/method types.