> > Now the change does not really translate to great increase of 
> > disambiguations
> > for Firefox (it seems more in noise). The reason is the pointer_type 
> > globbing
> > in alias.c.
> 
> Yeah, we only get the improvement because of some "hack" in the tree
> alias oracle which also uses the base object for TBAA.

Why that is hack? Dereferencing a pointer makes it clear the type of memory 
location
pointed to is known, we should use that info.
> 
> Yeah, we should fix that.  And in fact, for cross-language LTO I don't
> see why
> 
>   union { int a; char c; };
> 
> and
> 
>   union { int a; short s; };
> 
> should not be compatible - they have a common member after all.  So
> I'd like to glob all unions that have the same size (and as improvement

Well, none of language standards I saw so far expect this to happen.
Going to extremes, you can always put variable sized char array to union
and by transitivity glob everything with everything.

> over that, that have at least one compatible member).  That also get's
> rid of the issue that we'd need to sort union members for the comparison
> to avoid quadraticness (as long as we don't check for that one compatible
> member).

Yeah, sorting is possible by using the hash values.
> 
> Oh, and are
> 
>   union { int a; };
> 
> and
> 
>   struct { int a; };
> 
> not compatible?  They are layout-wise at least.  Likewise the struct
> and union { int a; short s; } with the same argument as the two-union
> case.

Applying this rule you have

union { char a[n]; } compatible with every union and thus also
union {int a;}
struct { int a;}
int a;

Which would disable TBAA completely.
> 
> >  We also do not compare alignments. This is probably not important)
> 
> Correct - alignment doesn't enter TBAA.

Yep, I think the alignment compare in C standard basically is there to say that
structures must have same lyaout.
> > void f(double (* restrict a)[5]);
> > void f(double a[restrict][5]);
> > void f(double a[restrict 3][5]);
> > void f(double a[restrict static 3][5]);)
> 
> Not sure why you get into functions here at all ...

Basically it matters only if we want to disambiguate function pointers.
> 
> >   2  Each enumerated type shall be compatible with char ,  a  signed integer
> >      type, or an unsigned integer type. The choice of type is
> >      implementation-defined, but  shall be capable of representing the 
> > values
> >      of all the members of the enumeration.    The enumerated type is
> >      incomplete until immediately after the that terminates the list of
> >      enumerator declarations, and complete thereafter.
> > 
> > (we ignore this completely as far as I know, it is easy to fix though, all
> >  we need is to make ENUMERATION_TYPE pretend to be INTEGER_TYPE)
> 
> Yes, we don't make a distinction between ENUMERAL_TYPE and INTEGER_TYPE.

hstate.add_int (TREE_CODE (type));

makes them different.  I think we want to produce "simplified" code that turns
REFERENCE_TYPE to POINTER_TYPE and ENUMERAL_TYPE to INTEGER_TYPE.
I will send patch fo that.
> 
> >   10 For two qualified types to be compatible, both shall have the 
> > identically
> >      qualified version of a compatible type; the order of type qualifiers
> >      within a list of specifiers or qualifiers does not affect the 
> > specified type.
> > 
> > Now I think in order to get C standard type compatiblity to imply
> > gimple_canonical_types_compatible we need to implement all the above 
> > globbing
> > rules as part of canonical type computation, not only punt at pointers in
> > alias.c
> > 
> > My reading is that for example
> > 
> > struct a {char *a;};
> > 
> > is compatible with
> > 
> > struct a {enum *a;};
> > 
> > defined in other compilation unit.
> 
> Yes, as said above the TREE_CODE trick in the pointer-type handing is
> wrong.  We can as well just drop it ...

struct a {char a;};

is compatible with

struct a {enum a;};

I would say we just want to simplify the codes and peel for
pointers instead of TREE_TYPE (t) compare look for actual pointed to type
(peeling out POINTER_TYPE/RECORD_TYPE/ARRAY_TYPEs)
> >  8) i think to be correct by C language standard we need to glob enum 
> > with char
> >     tough I do not quite see how standard conforming program should use 
> >     it given that standard does not say if it is char/unsigned 
> >     char/signed char.
> 
> I think it depends on the actual enum, no?  So for forward declarations
> like
> 
>  enum Foo;
>  struct X { enum Foo *p; };
> 
> you face the same issue as with void *.

Well, handling all enums as integers should solve this.
> > Overall plan
> > ============
> > 
> > So I propose the following:
> >  1) we add the incomplete types mode to gimple_canonical_types_compatible_p
> >     as suggested by this patch
> >  2) I will add the individual globbing rules to the functions one by one
> >  3) once done, we enable recursion on pointer
> >  4) we drop the alias.c globing of pointer_type for in_lto_p.
> 
> I don't think we want to do 4), especially not only for in_lto_p.  I'm
> not sure we should spend time on improving accuracy before fixing
> correctness (on the current precision level).

Yep, fixing correctness is 2).  I will look into that.
> > Based on experience, we may switch to C/C++ compliant equivalence when we 
> > know
> > that whole unit is C/C++ and we do not have to deal with odd cases from 
> > other
> > languages.
> 
> I'm not convinced the patch is a step in the right direction.
> 
> Can we please first fix pointer handing for TYPE_CANONICAL by dropping
> the TREE_CODE handling and fix union handling by only looking at
> union size?

OK, I will send patch for TYPE_CODE compare.
I am not quite convinced about the unions as per example abov.
> 
> Originally I wanted to make LTO type compatibility really layout-based
> (thus struct { int i[2]; } and struct { int i; int j; } match for 
> example).
> 
> I wonder if for non-cross-language-LTO we shouldn't simply stream
> TYPE_CANONICAL, at stream-in record a TYPE_CANONICAL vs. uses vector
> map and "fix" up canonical types globally (we'd need to stream
> "local" canonical types in the global trees then).

Hmm, can you explain bit more what you have in mind?  I did play
with non-cross-language canonical type streaming for anonymous
namespace C++ types (that by definition can not be compatible
with anything from other language).
I can return to that.

Honza
> 
> Richard.
> 
> > Honza
> > 
> >     * tree.c (gimple_canonical_types_compatible_p): Turn
> >     TRUST_TYPE_CANONICAL into FLAGS parameter; support
> >     comparsion with MATCH_WITH_INCOMPLETE_TYPE.
> > Index: lto/lto.c
> > ===================================================================
> > --- lto/lto.c       (revision 223632)
> > +++ lto/lto.c       (working copy)
> > @@ -295,7 +295,9 @@
> >  static unsigned long num_canonical_type_hash_entries;
> >  static unsigned long num_canonical_type_hash_queries;
> >  
> > -static void iterative_hash_canonical_type (tree type, inchash::hash 
> > &hstate);
> > +static void iterative_hash_canonical_type (tree type, inchash::hash 
> > &hstate,
> > +                                      unsigned int flags
> > +                                        = MATCH_TYPE_CANONICAL);
> >  static hashval_t gimple_canonical_type_hash (const void *p);
> >  static void gimple_register_canonical_type_1 (tree t, hashval_t hash);
> >  
> > @@ -302,26 +304,36 @@
> >  /* Returning a hash value for gimple type TYPE.
> >  
> >     The hash value returned is equal for types considered compatible
> > -   by gimple_canonical_types_compatible_p.  */
> > +   by gimple_canonical_types_compatible_p.  FLAGS values are interpretted
> > +   same way as by this function.  */
> >  
> >  static hashval_t
> > -hash_canonical_type (tree type)
> > +hash_canonical_type (tree type, unsigned int flags = MATCH_TYPE_CANONICAL)
> >  {
> >    inchash::hash hstate;
> >  
> > -  /* We compute alias sets only for types that needs them.
> > -     Be sure we do not recurse to something else as we can not hash 
> > incomplete
> > -     types in a way they would have same hash value as compatible complete
> > -     types.  */
> > -  gcc_checking_assert (type_with_alias_set_p (type));
> > +  /* Check that we encounter incomplete types only with
> > +     MATCH_WITH_INCOMPLETE_TYPE.
> >  
> > +     Also check that no one tries to use hashing in compbination with 
> > +     !MATCH_TYPE_CANONICAL.  In this case 
> > gimple_canonical_types_compatible_p
> > +     is not transitive and thus does not produce equivalence on all types. 
> >  */
> > +  gcc_checking_assert ((flags & MATCH_TYPE_CANONICAL)
> > +                  && ((flags & MATCH_WITH_INCOMPLETE_TYPE)
> > +                      || type_with_alias_set_p (type)));
> > +
> >    /* Combine a few common features of types so that types are grouped into
> >       smaller sets; when searching for existing matching types to merge,
> >       only existing types having the same features as the new type will be
> >       checked.  */
> >    hstate.add_int (TREE_CODE (type));
> > -  hstate.add_int (TYPE_MODE (type));
> >  
> > +  /* Incomplete arrays and aggregates do not have TYPE_MODE defined.  */
> > +  if (!(flags & MATCH_WITH_INCOMPLETE_TYPE)
> > +      || (TREE_CODE (type) != ARRAY_TYPE
> > +     && !AGGREGATE_TYPE_P (type)))
> > +    hstate.add_int (TYPE_MODE (type));
> > +
> >    /* Incorporate common features of numerical types.  */
> >    if (INTEGRAL_TYPE_P (type)
> >        || SCALAR_FLOAT_TYPE_P (type)
> > @@ -355,7 +367,8 @@
> >      hstate.add_int (TYPE_STRING_FLAG (type));
> >  
> >    /* For array types hash the domain bounds and the string flag.  */
> > -  if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
> > +  if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)
> > +      && !(flags & MATCH_WITH_INCOMPLETE_TYPE))
> >      {
> >        hstate.add_int (TYPE_STRING_FLAG (type));
> >        /* OMP lowering can introduce error_mark_node in place of
> > @@ -366,30 +379,35 @@
> >     inchash::add_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), hstate);
> >      }
> >  
> > -  /* Recurse for aggregates with a single element type.  */
> > +  /* Recurse for aggregates with a single element type.
> > +     We are safe to drop MATCH_INCOMPLETE.  There is no way to build
> > +     an array of incomplete types.   */
> >    if (TREE_CODE (type) == ARRAY_TYPE
> >        || TREE_CODE (type) == COMPLEX_TYPE
> >        || TREE_CODE (type) == VECTOR_TYPE)
> > -    iterative_hash_canonical_type (TREE_TYPE (type), hstate);
> > +    iterative_hash_canonical_type (TREE_TYPE (type), hstate,
> > +                              flags & ~MATCH_WITH_INCOMPLETE_TYPE);
> >  
> >    /* Incorporate function return and argument types.  */
> >    if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
> >      {
> > -      unsigned na;
> > -      tree p;
> > +      iterative_hash_canonical_type (TREE_TYPE (type), hstate, flags);
> >  
> > -      iterative_hash_canonical_type (TREE_TYPE (type), hstate);
> > -
> > -      for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
> > +      if (!(flags & MATCH_WITH_INCOMPLETE_TYPE)
> > +     || TREE_CODE (type) == METHOD_TYPE)
> >     {
> > -     iterative_hash_canonical_type (TREE_VALUE (p), hstate);
> > -     na++;
> > +     unsigned na;
> > +     tree p;
> > +     for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
> > +       {
> > +         iterative_hash_canonical_type (TREE_VALUE (p), hstate, flags);
> > +         na++;
> > +       }
> > +     hstate.add_int (na);
> >     }
> > -
> > -      hstate.add_int (na);
> >      }
> >  
> > -  if (RECORD_OR_UNION_TYPE_P (type))
> > +  if (RECORD_OR_UNION_TYPE_P (type) && !(flags & 
> > MATCH_WITH_INCOMPLETE_TYPE))
> >      {
> >        unsigned nf;
> >        tree f;
> > @@ -397,7 +415,7 @@
> >        for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
> >     if (TREE_CODE (f) == FIELD_DECL)
> >       {
> > -       iterative_hash_canonical_type (TREE_TYPE (f), hstate);
> > +       iterative_hash_canonical_type (TREE_TYPE (f), hstate, flags);
> >         nf++;
> >       }
> >  
> > @@ -407,14 +425,22 @@
> >    return hstate.end();
> >  }
> >  
> > -/* Returning a hash value for gimple type TYPE combined with VAL.  */
> > +/* Returning a hash value for gimple type TYPE combined with VAL.
> > +   FLAGS are the same as for gimple_conanical_types_compatible_p.  */
> >  
> >  static void
> > -iterative_hash_canonical_type (tree type, inchash::hash &hstate)
> > +iterative_hash_canonical_type (tree type, inchash::hash &hstate,
> > +                          unsigned int flags)
> >  {
> >    hashval_t v;
> > +
> > +  /* TYPE_CANONICAL reflects equivalence classes with
> > +     !MATCH_WITH_INCOMPLETE_TYPE.   If we are matching incomplete types,
> > +     then we need to recurse.  */
> > +  if (flags & MATCH_WITH_INCOMPLETE_TYPE)
> > +    v = hash_canonical_type (type, flags);
> >    /* An already processed type.  */
> > -  if (TYPE_CANONICAL (type))
> > +  else if (TYPE_CANONICAL (type))
> >      {
> >        type = TYPE_CANONICAL (type);
> >        v = gimple_canonical_type_hash (type);
> > @@ -497,6 +523,14 @@
> >  {
> >    if (TYPE_CANONICAL (t) || !type_with_alias_set_p (t))
> >      return;
> > +  /* Only types that can be handled in memory need canonical types.
> > +     Function and methods are never accessed. Also we do not need canonical
> > +     types for incomplete types with exception of arrays - structures may 
> > end
> > +     with incomplete arrays that may be referenced.  */
> > +  if (TREE_CODE (t) == FUNCTION_TYPE || TREE_CODE (t) == METHOD_TYPE
> > +      || (!COMPLETE_TYPE_P (t)
> > +     && (TREE_CODE (t) != ARRAY_TYPE || !COMPLETE_TYPE_P (TREE_TYPE (t)))))
> > +    return;
> >  
> >    gimple_register_canonical_type_1 (t, hash_canonical_type (t));
> >  }
> > Index: tree.c
> > ===================================================================
> > --- tree.c  (revision 223633)
> > +++ tree.c  (working copy)
> > @@ -12702,12 +12702,24 @@
> >  /* Return true iff T1 and T2 are structurally identical for what
> >     TBAA is concerned.  
> >     This function is used both by lto.c canonical type merging and by the
> > -   verifier.  If TRUST_TYPE_CANONICAL we do not look into structure of 
> > types
> > -   that have TYPE_CANONICAL defined and assume them equivalent.  */
> > +   verifier.  
> >  
> > +   If flags sets MATCH_TYPE_CANONICAL we assume that TYPE_CANONICAL is set 
> > in a
> > +   way that two types have the same canonical type if and only if
> > +   gimple_canonical_types_compatible_p (t1,t2, 0) is true.  This is used
> > +   to cut down recursion during LTO canonical type comptuation.  When this 
> > flag
> > +   is set we also sanity check that we are going to produce equivalence 
> > relation
> > +   that is needed to drive the hashtable in lto.c.
> > +
> > +   if MATCH_WITH_INCOMPLETE_TYPE is true, then we do not use any 
> > information
> > +   from complete types and thus i.e. all RECORD_TYPE are equivlaent to 
> > other
> > +   RECORD_TYPEs.  This is the only equivalence possible if one require
> > +   incomplete type to be in the same equivalence class with all its
> > +   completetions.  */
> > +
> >  bool
> >  gimple_canonical_types_compatible_p (const_tree t1, const_tree t2,
> > -                                bool trust_type_canonical)
> > +                                unsigned int flags)
> >  {
> >    /* Before starting to set up the SCC machinery handle simple cases.  */
> >  
> > @@ -12719,28 +12731,28 @@
> >    if (t1 == NULL_TREE || t2 == NULL_TREE)
> >      return false;
> >  
> > -  /* We consider complete types always compatible with incomplete type.
> > -     This does not make sense for canonical type calculation and thus we
> > -     need to ensure that we are never called on it.
> > +  /* Check that either flags allow incomplete types or both types are 
> > complete.
> > +     This is necessary to ensure transitivity for canonical type merging.
> >  
> > -     FIXME: For more correctness the function probably should have three 
> > modes
> > -   1) mode assuming that types are complete mathcing their structure
> > -   2) mode allowing incomplete types but producing equivalence classes
> > -      and thus ignoring all info from complete types
> > -   3) mode allowing incomplete types to match complete but checking
> > -      compatibility between complete types.
> > +     FIXME: with !MATCH_TYPE_CANONICAL we probably should allow match 
> > between
> > +     incomplete type and complete type as defined by language standards.  
> > No
> > +     one however rely on it so far.  */
> >  
> > -     1 and 2 can be used for canonical type calculation. 3 is the real
> > -     definition of type compatibility that can be used i.e. for warnings 
> > during
> > -     declaration merging.  */
> > -
> > -  gcc_assert (!trust_type_canonical
> > +  gcc_assert ((flags & MATCH_WITH_INCOMPLETE_TYPE)
> > +         || !(flags & MATCH_TYPE_CANONICAL)
> >           || (type_with_alias_set_p (t1) && type_with_alias_set_p (t2)));
> >    /* If the types have been previously registered and found equal
> >       they still are.  */
> >    if (TYPE_CANONICAL (t1) && TYPE_CANONICAL (t2)
> > -      && trust_type_canonical)
> > -    return TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2);
> > +      && (flags & MATCH_TYPE_CANONICAL))
> > +    {
> > +      if (TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
> > +   return true;
> > +      /* TYPE_CANONICAL is always computed with an assumption that the type
> > +    is complete.  */
> > +      if (!(flags & MATCH_WITH_INCOMPLETE_TYPE))
> > +   return false;
> > +    }
> >  
> >    /* Can't be the same type if the types don't have the same code.  */
> >    if (TREE_CODE (t1) != TREE_CODE (t2))
> > @@ -12753,8 +12765,12 @@
> >        || TREE_CODE (t1) == NULLPTR_TYPE)
> >      return true;
> >  
> > -  /* Can't be the same type if they have different mode.  */
> > -  if (TYPE_MODE (t1) != TYPE_MODE (t2))
> > +  /* Can't be the same type if they have different mode.
> > +     Incomplete arrays and aggregates do not have TYPE_MODE defined.  */
> > +  if ((!(flags & MATCH_WITH_INCOMPLETE_TYPE)
> > +       || (TREE_CODE (t1) != ARRAY_TYPE
> > +           && !AGGREGATE_TYPE_P (t1)))
> > +      && TYPE_MODE (t1) != TYPE_MODE (t2))
> >      return false;
> >  
> >    /* Non-aggregate types can be handled cheaply.  */
> > @@ -12783,8 +12799,7 @@
> >     {
> >       if (TYPE_ADDR_SPACE (TREE_TYPE (t1))
> >           != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
> > -       return false;
> > -
> > +       return false;
> >       if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2)))
> >         return false;
> >     }
> > @@ -12792,9 +12807,9 @@
> >        /* Tail-recurse to components.  */
> >        if (TREE_CODE (t1) == VECTOR_TYPE
> >       || TREE_CODE (t1) == COMPLEX_TYPE)
> > -   return gimple_canonical_types_compatible_p (TREE_TYPE (t1),
> > -                                               TREE_TYPE (t2),
> > -                                               trust_type_canonical);
> > +   return gimple_canonical_types_compatible_p
> > +            (TREE_TYPE (t1), TREE_TYPE (t2),
> > +             flags & ~MATCH_WITH_INCOMPLETE_TYPE);
> >  
> >        return true;
> >      }
> > @@ -12804,12 +12819,20 @@
> >      {
> >      case ARRAY_TYPE:
> >        /* Array types are the same if the element types are the same and
> > -    the number of elements are the same.  */
> > -      if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE 
> > (t2),
> > -                                           trust_type_canonical)
> > +    the number of elements are the same.
> > +
> > +    When MATCH_WITH_INCOMPLETE_TYPE is set, bypass the check
> > +    on number of elements.
> > +    When recursing, clear MATCH_WITH_INCOMPLETE_TYPE because there is
> > +    no way to make incomplete array of array.  */
> > +      if (!gimple_canonical_types_compatible_p
> > +        (TREE_TYPE (t1), TREE_TYPE (t2),
> > +         flags & ~MATCH_WITH_INCOMPLETE_TYPE)
> >       || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
> >       || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
> >     return false;
> > +      else if (flags & MATCH_WITH_INCOMPLETE_TYPE)
> > +   return true;
> >        else
> >     {
> >       tree i1 = TYPE_DOMAIN (t1);
> > @@ -12848,11 +12871,19 @@
> >      case METHOD_TYPE:
> >      case FUNCTION_TYPE:
> >        /* Function types are the same if the return type and arguments types
> > -    are the same.  */
> > +    are the same.
> > +    It is possible that function pointers have return values and parameters
> > +    of incomplete types; permit that by not clearing
> > +    MATCH_WITH_INCOMPLETE_TYPE  */
> >        if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE 
> > (t2),
> > -                                           trust_type_canonical))
> > +                                           flags))
> >     return false;
> >  
> > +      /* We must permit a match between !prototype_p and prototype_p for
> > +    functions; methods are never !prototype_p.  */
> > +      if ((flags & MATCH_WITH_INCOMPLETE_TYPE)
> > +     && TREE_CODE (t1) == FUNCTION_TYPE)
> > +   return true;
> >        if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
> >     return true;
> >        else
> > @@ -12864,8 +12895,7 @@
> >            parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
> >         {
> >           if (!gimple_canonical_types_compatible_p
> > -                (TREE_VALUE (parms1), TREE_VALUE (parms2),
> > -                 trust_type_canonical))
> > +                (TREE_VALUE (parms1), TREE_VALUE (parms2), flags))
> >             return false;
> >         }
> >  
> > @@ -12881,6 +12911,15 @@
> >        {
> >     tree f1, f2;
> >  
> > +   /* C standrad require incomplete structures and unions to be
> > +      considered compatible with complete ones regardless their TYPE_NAME
> > +      when they come from different translation units.
> > +      We must consider transitive closure here, so 
> > +      every structure/union is equivalent to each other.  */
> > +      
> > +   if (flags & MATCH_WITH_INCOMPLETE_TYPE)
> > +     return true;
> > +
> >     /* For aggregate types, all the fields must be the same.  */
> >     for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
> >          f1 || f2;
> > @@ -12897,8 +12936,7 @@
> >         if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
> >             || !gimple_compare_field_offset (f1, f2)
> >             || !gimple_canonical_types_compatible_p
> > -                 (TREE_TYPE (f1), TREE_TYPE (f2),
> > -                  trust_type_canonical))
> > +                 (TREE_TYPE (f1), TREE_TYPE (f2), flags))
> >           return false;
> >       }
> >  
> > @@ -12961,7 +12999,7 @@
> >           with variably sized arrays because their sizes possibly
> >           gimplified to different variables.  */
> >        && !variably_modified_type_p (ct, NULL)
> > -      && !gimple_canonical_types_compatible_p (t, ct, false))
> > +      && !gimple_canonical_types_compatible_p (t, ct, 0))
> >      {
> >        error ("TYPE_CANONICAL is not compatible");
> >        debug_tree (ct);
> > Index: tree.h
> > ===================================================================
> > --- tree.h  (revision 223632)
> > +++ tree.h  (working copy)
> > @@ -4569,9 +4569,21 @@
> >  extern unsigned int tree_map_base_hash (const void *);
> >  extern int tree_map_base_marked_p (const void *);
> >  extern void DEBUG_FUNCTION verify_type (const_tree t);
> > -extern bool gimple_canonical_types_compatible_p (const_tree, const_tree,
> > -                                            bool trust_type_canonical = 
> > true);
> >  
> > +/* Flags used by gimple_canonical_types_compatible_p.  */
> > +enum gimple_canonical_types_compatible_flags
> > +  {
> > +    /* Asume that TYPE_CANONICAL is set in a way that two types have
> > +       the same canonical type if and only if
> > +       gimple_canonical_types_compatible_p (t1,t2, 0) is true.  */
> > +    MATCH_TYPE_CANONICAL = 1,
> > +    /* Match all types as if they were incomplete.  */
> > +    MATCH_WITH_INCOMPLETE_TYPE = 2
> > +  };
> > +extern bool gimple_canonical_types_compatible_p
> > +    (const_tree, const_tree,
> > +     unsigned int flags = MATCH_TYPE_CANONICAL);
> > +
> >  #define tree_map_eq tree_map_base_eq
> >  extern unsigned int tree_map_hash (const void *);
> >  #define tree_map_marked_p tree_map_base_marked_p
> > 
> > 
> 
> -- 
> Richard Biener <rguent...@suse.de>
> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Dilip Upmanyu, Graham 
> Norton, HRB 21284 (AG Nuernberg)

Reply via email to