https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123818

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org,
                   |                            |jason at gcc dot gnu.org,
                   |                            |ppalka at gcc dot gnu.org

--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
I think this goes on far longer than that, I think 1992-ish.
The problem is that the default arguments are in the IL in the function types
(TREE_PURPOSE of nodes in TYPE_ARG_TYPES list nodes on
FUNCTION_TYPE/METHOD_TYPE).
And the FE heavily uses build_function_type or build_method_type_directly,
which like for many other functions which use type_hash_canon for type sharing
uses
type_hash_canon_hash/type_cache_hasher::equal for hashing/equality.
Now, type_hash_canon_hash doesn't bother with the default arguments at all, it
just hashes the types:
      for (tree t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t))
        if (TREE_VALUE (t) != error_mark_node)
          hstate.add_object (TYPE_HASH (TREE_VALUE (t)));
The equal static member function considers those, for both METHOD_TYPE and
FUNCTION_TYPE it uses type_list_equal (TYPE_ARG_TYPES (a->type), TYPE_ARG_TYPES
(b->type)) among other checks.
And type_list_equal uses simple_cst_equal for the default arguments
  for (t1 = l1, t2 = l2; t1 && t2; t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2))
    if (TREE_VALUE (t1) != TREE_VALUE (t2)
        || (TREE_PURPOSE (t1) != TREE_PURPOSE (t2)
            && ! (1 == simple_cst_equal (TREE_PURPOSE (t1), TREE_PURPOSE (t2))
                  && (TREE_TYPE (TREE_PURPOSE (t1))
                      == TREE_TYPE (TREE_PURPOSE (t2))))))
which works just fine for say INTEGER_CSTs or many other cases.
But simple_cst_equal returns true here due to a bug.
That said, even the
  if (CONVERT_EXPR_CODE_P (code1) || code1 == NON_LVALUE_EXPR)
    { 
      if (CONVERT_EXPR_CODE_P (code2)
          || code2 == NON_LVALUE_EXPR)
        return simple_cst_equal (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
      else
        return simple_cst_equal (TREE_OPERAND (t1, 0), t2);
    }

  else if (CONVERT_EXPR_CODE_P (code2)
           || code2 == NON_LVALUE_EXPR)
    return simple_cst_equal (t1, TREE_OPERAND (t2, 0));
looks risky to me especially these days when the FE attempts to defer folding.
I'm worried about say intermediate cast to different types.

Reply via email to