Because I want to add another argument to comptypes
and co. for UBSan instrumentation and this then
starts to become a bit unwiedly, here is a patch to
reorganize and simplify this a bit. This can wait
until stage 1. (The cache can be simplified further
by allocating it on the stack, but this can be done
later).



c: Reorganize comptypes and related functions.

Move common arguments and a global variable (the
cache for type compatibility) used by comptypes
and childen into a single structure and pass a
pointer to it.

gcc/c/ 
* c/c-typeck.cc: (comptypes,comptypes_check_enum_int,
comptypes_check_different_types,comptypes_internal,
tagged_types_tu_compatible_p,function_types_compatible_p,
type_lists_compatible_p): Introduce a structure argument.
(alloc_tagged_tu_seen_cache,free_all_tagged_tu_seen_up_to):
Reorganize cache and remove tu from function names.



diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index 47fa36f4ec8..ebc9ba88afe 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -90,12 +90,11 @@ static bool require_constexpr_value;
 
 static bool null_pointer_constant_p (const_tree);
 static tree qualify_type (tree, tree);
-static int tagged_types_tu_compatible_p (const_tree, const_tree, bool *,
-                                        bool *);
+struct comptypes_data;
+static int tagged_types_compatible_p (const_tree, const_tree, struct 
comptypes_data *);
 static int comp_target_types (location_t, tree, tree);
-static int function_types_compatible_p (const_tree, const_tree, bool *,
-                                       bool *);
-static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
+static int function_types_compatible_p (const_tree, const_tree, struct 
comptypes_data *);
+static int type_lists_compatible_p (const_tree, const_tree, struct 
comptypes_data *);
 static tree lookup_field (tree, tree);
 static int convert_arguments (location_t, vec<location_t>, tree,
                              vec<tree, va_gc> *, vec<tree, va_gc> *, tree,
@@ -125,7 +124,7 @@ static tree find_init_member (tree, struct obstack *);
 static void readonly_warning (tree, enum lvalue_use);
 static int lvalue_or_else (location_t, const_tree, enum lvalue_use);
 static void record_maybe_used_decl (tree);
-static int comptypes_internal (const_tree, const_tree, bool *, bool *);
+static int comptypes_internal (const_tree, const_tree, struct comptypes_data 
*data);
 
 /* Return true if EXP is a null pointer constant, false otherwise.  */
 
@@ -189,17 +188,16 @@ remove_c_maybe_const_expr (tree expr)
 
 /* This is a cache to hold if two types are compatible or not.  */
 
-struct tagged_tu_seen_cache {
-  const struct tagged_tu_seen_cache * next;
+struct tagged_seen_cache {
+  const struct tagged_seen_cache * next;
   const_tree t1;
   const_tree t2;
-  /* The return value of tagged_types_tu_compatible_p if we had seen
+  /* The return value of tagged_types_compatible_p if we had seen
      these two types already.  */
   int val;
 };
 
-static const struct tagged_tu_seen_cache * tagged_tu_seen_base;
-static void free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache 
*);
+static void free_all_tagged_seen (const struct tagged_seen_cache *);
 
 /* Do `exp = require_complete_type (loc, exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)
@@ -1049,6 +1047,14 @@ common_type (tree t1, tree t2)
   return c_common_type (t1, t2);
 }
 
+struct comptypes_data {
+
+  const struct tagged_seen_cache *seen_base;
+
+  bool enum_and_int_p;
+  bool different_types_p;
+};
+
 /* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
    or various other operations.  Return 2 if they are compatible
    but a warning may be needed if you use them together.  */
@@ -1056,11 +1062,12 @@ common_type (tree t1, tree t2)
 int
 comptypes (tree type1, tree type2)
 {
-  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = 
tagged_tu_seen_base;
   int val;
 
-  val = comptypes_internal (type1, type2, NULL, NULL);
-  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+  struct comptypes_data data = { };
+  val = comptypes_internal (type1, type2, &data);
+
+  free_all_tagged_seen (data.seen_base);
 
   return val;
 }
@@ -1071,11 +1078,13 @@ comptypes (tree type1, tree type2)
 int
 comptypes_check_enum_int (tree type1, tree type2, bool *enum_and_int_p)
 {
-  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = 
tagged_tu_seen_base;
   int val;
 
-  val = comptypes_internal (type1, type2, enum_and_int_p, NULL);
-  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+  struct comptypes_data data = { };
+  val = comptypes_internal (type1, type2, &data);
+  *enum_and_int_p = data.enum_and_int_p;
+
+  free_all_tagged_seen (data.seen_base);
 
   return val;
 }
@@ -1087,31 +1096,33 @@ int
 comptypes_check_different_types (tree type1, tree type2,
                                 bool *different_types_p)
 {
-  const struct tagged_tu_seen_cache * tagged_tu_seen_base1 = 
tagged_tu_seen_base;
   int val;
 
-  val = comptypes_internal (type1, type2, NULL, different_types_p);
-  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+  struct comptypes_data data = { };
+  val = comptypes_internal (type1, type2, &data);
+  *different_types_p = data.different_types_p;
+
+  free_all_tagged_seen (data.seen_base);
 
   return val;
 }
+
 
-/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
+/* Return 1 if 'type1' and 'type2' are compatible types for assignment
    or various other operations.  Return 2 if they are compatible
    but a warning may be needed if you use them together.  If
-   ENUM_AND_INT_P is not NULL, and one type is an enum and the other a
-   compatible integer type, then this sets *ENUM_AND_INT_P to true;
-   *ENUM_AND_INT_P is never set to false.  If DIFFERENT_TYPES_P is not
-   NULL, and the types are compatible but different enough not to be
-   permitted in C11 typedef redeclarations, then this sets
-   *DIFFERENT_TYPES_P to true; *DIFFERENT_TYPES_P is never set to
-   false, but may or may not be set if the types are incompatible.
-   This differs from comptypes, in that we don't free the seen
-   types.  */
+   one type is an enum and the other a compatible integer type,
+   then this sets 'enum_and_int_p' in 'data' to true
+   (it is never set to false).  If the types are compatible but
+   different enough not to be permitted in C11 typedef redeclarations,
+   then this sets 'different_types_p' in 'data' to true (it is never
+   set to false), but may or may not be set if the types are
+   incompatible. This differs from 'comptypes', in that we don't free
+   the seen types.  */
 
 static int
-comptypes_internal (const_tree type1, const_tree type2, bool *enum_and_int_p,
-                   bool *different_types_p)
+comptypes_internal (const_tree type1, const_tree type2,
+                   struct comptypes_data *data)
 {
   const_tree t1 = type1;
   const_tree t2 = type2;
@@ -1134,10 +1145,8 @@ comptypes_internal (const_tree type1, const_tree type2, 
bool *enum_and_int_p,
       t1 = ENUM_UNDERLYING_TYPE (t1);
       if (TREE_CODE (t2) != VOID_TYPE)
        {
-         if (enum_and_int_p != NULL)
-           *enum_and_int_p = true;
-         if (different_types_p != NULL)
-           *different_types_p = true;
+         data->enum_and_int_p = true;
+         data->different_types_p = true;
        }
     }
   else if (TREE_CODE (t2) == ENUMERAL_TYPE
@@ -1147,10 +1156,8 @@ comptypes_internal (const_tree type1, const_tree type2, 
bool *enum_and_int_p,
       t2 = ENUM_UNDERLYING_TYPE (t2);
       if (TREE_CODE (t1) != VOID_TYPE)
        {
-         if (enum_and_int_p != NULL)
-           *enum_and_int_p = true;
-         if (different_types_p != NULL)
-           *different_types_p = true;
+         data->enum_and_int_p = true;
+         data->different_types_p = true;
        }
     }
 
@@ -1208,13 +1215,11 @@ comptypes_internal (const_tree type1, const_tree type2, 
bool *enum_and_int_p,
       if (TYPE_MODE (t1) != TYPE_MODE (t2))
        break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
-            ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                      enum_and_int_p, different_types_p));
+            ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), data));
       break;
 
     case FUNCTION_TYPE:
-      val = function_types_compatible_p (t1, t2, enum_and_int_p,
-                                        different_types_p);
+      val = function_types_compatible_p (t1, t2, data);
       break;
 
     case ARRAY_TYPE:
@@ -1228,13 +1233,11 @@ comptypes_internal (const_tree type1, const_tree type2, 
bool *enum_and_int_p,
        /* Target types must match incl. qualifiers.  */
        if (TREE_TYPE (t1) != TREE_TYPE (t2)
            && (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                         enum_and_int_p,
-                                         different_types_p)) == 0)
+                                         data)) == 0)
          return 0;
 
-       if (different_types_p != NULL
-           && (d1 == NULL_TREE) != (d2 == NULL_TREE))
-         *different_types_p = true;
+       if ((d1 == NULL_TREE) != (d2 == NULL_TREE))
+         data->different_types_p = true;
        /* Sizes must match unless one is missing or variable.  */
        if (d1 == NULL_TREE || d2 == NULL_TREE || d1 == d2)
          break;
@@ -1251,9 +1254,8 @@ comptypes_internal (const_tree type1, const_tree type2, 
bool *enum_and_int_p,
        d1_variable = d1_variable || (d1_zero && c_vla_type_p (t1));
        d2_variable = d2_variable || (d2_zero && c_vla_type_p (t2));
 
-       if (different_types_p != NULL
-           && d1_variable != d2_variable)
-         *different_types_p = true;
+       if (d1_variable != d2_variable)
+         data->different_types_p = true;
        if (d1_variable || d2_variable)
          break;
        if (d1_zero && d2_zero)
@@ -1278,8 +1280,7 @@ comptypes_internal (const_tree type1, const_tree type2, 
bool *enum_and_int_p,
              && ! attribute_list_contained (a2, a1))
            break;
 
-         val = tagged_types_tu_compatible_p (t1, t2, enum_and_int_p,
-                                             different_types_p);
+         val = tagged_types_compatible_p (t1, t2, data);
 
          if (attrval != 2)
            return val;
@@ -1288,8 +1289,7 @@ comptypes_internal (const_tree type1, const_tree type2, 
bool *enum_and_int_p,
 
     case VECTOR_TYPE:
       val = (known_eq (TYPE_VECTOR_SUBPARTS (t1), TYPE_VECTOR_SUBPARTS (t2))
-            && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2),
-                                   enum_and_int_p, different_types_p));
+            && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2), data));
       break;
 
     default:
@@ -1357,19 +1357,17 @@ comp_target_types (location_t location, tree ttl, tree 
ttr)
 
 /* Subroutines of `comptypes'.  */
 
-
-
 /* Allocate the seen two types, assuming that they are compatible. */
 
-static struct tagged_tu_seen_cache *
-alloc_tagged_tu_seen_cache (const_tree t1, const_tree t2)
+static struct tagged_seen_cache *
+alloc_tagged_seen_cache (const struct tagged_seen_cache **cache, const_tree 
t1, const_tree t2)
 {
-  struct tagged_tu_seen_cache *tu = XNEW (struct tagged_tu_seen_cache);
-  tu->next = tagged_tu_seen_base;
+  struct tagged_seen_cache *tu = XNEW (struct tagged_seen_cache);
   tu->t1 = t1;
   tu->t2 = t2;
 
-  tagged_tu_seen_base = tu;
+  tu->next = *cache;
+  *cache = tu;
 
   /* The C standard says that two structures in different translation
      units are compatible with each other only if the types of their
@@ -1387,32 +1385,26 @@ alloc_tagged_tu_seen_cache (const_tree t1, const_tree 
t2)
   return tu;
 }
 
-/* Free the seen types until we get to TU_TIL. */
+/* Free the seen types. */
 
 static void
-free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
+free_all_tagged_seen (const struct tagged_seen_cache *cache)
 {
-  const struct tagged_tu_seen_cache *tu = tagged_tu_seen_base;
-  while (tu != tu_til)
+  while (cache != NULL)
     {
-      const struct tagged_tu_seen_cache *const tu1
-       = (const struct tagged_tu_seen_cache *) tu;
-      tu = tu1->next;
-      XDELETE (CONST_CAST (struct tagged_tu_seen_cache *, tu1));
+      const struct tagged_seen_cache *tmp = cache;
+      cache = tmp->next;
+      XDELETE (CONST_CAST (struct tagged_seen_cache *, cache));
     }
-  tagged_tu_seen_base = tu_til;
 }
 
 /* Return 1 if two 'struct', 'union', or 'enum' types T1 and T2 are
    compatible.  If the two types are not the same (which has been
-   checked earlier), this can only happen when multiple translation
-   units are being compiled.  See C99 6.2.7 paragraph 1 for the exact
-   rules.  ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in
-   comptypes_internal.  */
+   checked earlier).  */
 
 static int
-tagged_types_tu_compatible_p (const_tree t1, const_tree t2,
-                             bool *enum_and_int_p, bool *different_types_p)
+tagged_types_compatible_p (const_tree t1, const_tree t2,
+                             struct comptypes_data* data)
 {
   tree s1, s2;
   bool needs_warning = false;
@@ -1445,17 +1437,18 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree 
t2,
     return 1;
 
   {
-    const struct tagged_tu_seen_cache * tts_i;
-    for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
+    const struct tagged_seen_cache * tts_i;
+    for (tts_i = data->seen_base; tts_i != NULL; tts_i = tts_i->next)
       if (tts_i->t1 == t1 && tts_i->t2 == t2)
        return tts_i->val;
   }
 
+  struct tagged_seen_cache *tu = alloc_tagged_seen_cache (&data->seen_base, 
t1, t2);
+
   switch (TREE_CODE (t1))
     {
     case ENUMERAL_TYPE:
       {
-       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
        /* Speed up the case where the type values are in the same order.  */
        tree tv1 = TYPE_VALUES (t1);
        tree tv2 = TYPE_VALUES (t2);
@@ -1507,8 +1500,6 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree 
t2,
 
     case UNION_TYPE:
       {
-       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
-
        if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2)))
          {
            tu->val = 0;
@@ -1523,8 +1514,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree 
t2,
 
            if (DECL_NAME (s1) != DECL_NAME (s2))
              break;
-           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                        enum_and_int_p, different_types_p);
+           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), data);
 
            if (result != 1 && !DECL_NAME (s1))
              break;
@@ -1560,8 +1550,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree 
t2,
                  int result;
 
                  result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                              enum_and_int_p,
-                                              different_types_p);
+                                              data);
 
                  if (result != 1 && !DECL_NAME (s1))
                    continue;
@@ -1593,8 +1582,6 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree 
t2,
 
     case RECORD_TYPE:
       {
-       struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
-
        if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2)))
          {
            tu->val = 0;
@@ -1609,8 +1596,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree 
t2,
            if (TREE_CODE (s1) != TREE_CODE (s2)
                || DECL_NAME (s1) != DECL_NAME (s2))
              break;
-           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2),
-                                        enum_and_int_p, different_types_p);
+           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2), data);
            if (result == 0)
              break;
            if (result == 2)
@@ -1642,8 +1628,7 @@ tagged_types_tu_compatible_p (const_tree t1, const_tree 
t2,
    ENUM_AND_INT_P and DIFFERENT_TYPES_P are as in comptypes_internal.  */
 
 static int
-function_types_compatible_p (const_tree f1, const_tree f2,
-                            bool *enum_and_int_p, bool *different_types_p)
+function_types_compatible_p (const_tree f1, const_tree f2, struct 
comptypes_data *data)
 {
   tree args1, args2;
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
@@ -1664,16 +1649,15 @@ function_types_compatible_p (const_tree f1, const_tree 
f2,
   if (TYPE_VOLATILE (ret2))
     ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
                                 TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
-  val = comptypes_internal (ret1, ret2, enum_and_int_p, different_types_p);
+  val = comptypes_internal (ret1, ret2, data);
   if (val == 0)
     return 0;
 
   args1 = TYPE_ARG_TYPES (f1);
   args2 = TYPE_ARG_TYPES (f2);
 
-  if (different_types_p != NULL
-      && (args1 == NULL_TREE) != (args2 == NULL_TREE))
-    *different_types_p = true;
+  if ((args1 == NULL_TREE) != (args2 == NULL_TREE))
+    data->different_types_p = true;
 
   /* An unspecified parmlist matches any specified parmlist
      whose argument types don't need default promotions.  */
@@ -1689,7 +1673,7 @@ function_types_compatible_p (const_tree f1, const_tree f2,
         If they don't match, ask for a warning (but no error).  */
       if (TYPE_ACTUAL_ARG_TYPES (f1)
          && type_lists_compatible_p (args2, TYPE_ACTUAL_ARG_TYPES (f1),
-                                     enum_and_int_p, different_types_p) != 1)
+                                     data) != 1)
        val = 2;
       return val;
     }
@@ -1701,14 +1685,13 @@ function_types_compatible_p (const_tree f1, const_tree 
f2,
        return 0;
       if (TYPE_ACTUAL_ARG_TYPES (f2)
          && type_lists_compatible_p (args1, TYPE_ACTUAL_ARG_TYPES (f2),
-                                     enum_and_int_p, different_types_p) != 1)
+                                     data) != 1)
        val = 2;
       return val;
     }
 
   /* Both types have argument lists: compare them and propagate results.  */
-  val1 = type_lists_compatible_p (args1, args2, enum_and_int_p,
-                                 different_types_p);
+  val1 = type_lists_compatible_p (args1, args2, data);
   return val1 != 1 ? val1 : val;
 }
 
@@ -1719,7 +1702,7 @@ function_types_compatible_p (const_tree f1, const_tree f2,
 
 static int
 type_lists_compatible_p (const_tree args1, const_tree args2,
-                        bool *enum_and_int_p, bool *different_types_p)
+                        struct comptypes_data *data)
 {
   /* 1 if no need for warning yet, 2 if warning cause has been seen.  */
   int val = 1;
@@ -1750,9 +1733,8 @@ type_lists_compatible_p (const_tree args1, const_tree 
args2,
         means there is supposed to be an argument
         but nothing is specified about what type it has.
         So match anything that self-promotes.  */
-      if (different_types_p != NULL
-         && (a1 == NULL_TREE) != (a2 == NULL_TREE))
-       *different_types_p = true;
+      if ((a1 == NULL_TREE) != (a2 == NULL_TREE))
+       data->different_types_p = true;
       if (a1 == NULL_TREE)
        {
          if (c_type_promotes_to (a2) != a2)
@@ -1767,11 +1749,9 @@ type_lists_compatible_p (const_tree args1, const_tree 
args2,
       else if (TREE_CODE (a1) == ERROR_MARK
               || TREE_CODE (a2) == ERROR_MARK)
        ;
-      else if (!(newval = comptypes_internal (mv1, mv2, enum_and_int_p,
-                                             different_types_p)))
+      else if (!(newval = comptypes_internal (mv1, mv2, data)))
        {
-         if (different_types_p != NULL)
-           *different_types_p = true;
+         data->different_types_p = true;
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
          if (TREE_CODE (a1) == UNION_TYPE
@@ -1792,8 +1772,7 @@ type_lists_compatible_p (const_tree args1, const_tree 
args2,
                           ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv3),
                                                     TYPE_QUAL_ATOMIC)
                           : TYPE_MAIN_VARIANT (mv3));
-                 if (comptypes_internal (mv3, mv2, enum_and_int_p,
-                                         different_types_p))
+                 if (comptypes_internal (mv3, mv2, data))
                    break;
                }
              if (memb == NULL_TREE)
@@ -1817,8 +1796,7 @@ type_lists_compatible_p (const_tree args1, const_tree 
args2,
                           ? c_build_qualified_type (TYPE_MAIN_VARIANT (mv3),
                                                     TYPE_QUAL_ATOMIC)
                           : TYPE_MAIN_VARIANT (mv3));
-                 if (comptypes_internal (mv3, mv1, enum_and_int_p,
-                                         different_types_p))
+                 if (comptypes_internal (mv3, mv1, data))
                    break;
                }
              if (memb == NULL_TREE)




Reply via email to