OSDN Git Service

2005-10-02 Andrew Pinski <pinskia@physics.uc.edu>
authorpinskia <pinskia@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 2 Oct 2005 19:15:58 +0000 (19:15 +0000)
committerpinskia <pinskia@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 2 Oct 2005 19:15:58 +0000 (19:15 +0000)
        PR c/18851
        * c-typeck.c (tagged_tu_seen): Rename to ...
        (tagged_tu_seen_cache): this and add val field.
        (comptypes): Move functional to comptypes_internal
        and free tagged_tu_seen.
        (comptypes_internal): New function and call comptypes_internal
        instead of comptypes. Speed up by sibcalling
        tagged_types_tu_compatible_p.
        (alloc_tagged_tu_seen): New function
        (free_all_tagged_tu_seen_up_to): New function.
        (tagged_types_tu_compatible_p): Return the val of the seen two
        types.
        Add that the two types are the same to tagged_tu_seen_base
        if they are and call comptypes_internal instead of comptypes.
        <case UNION_TYPE>: Speed up common type where the fields are
        in the same order.
        (function_types_compatible_p): Call comptypes_internal instead of
        comptypes.
        (type_lists_compatible_p): Likewise.
        (all functions): s/tagged_tu_seen/tagged_tu_seen_cache/.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@104873 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/c-typeck.c

index 233026b..e712977 100644 (file)
@@ -1,3 +1,26 @@
+2005-10-02  Andrew Pinski  <pinskia@physics.uc.edu>
+
+       PR c/18851
+       * c-typeck.c (tagged_tu_seen): Rename to ...
+       (tagged_tu_seen_cache): this and add val field.
+       (comptypes): Move functional to comptypes_internal
+       and free tagged_tu_seen.
+       (comptypes_internal): New function and call comptypes_internal
+       instead of comptypes. Speed up by sibcalling
+       tagged_types_tu_compatible_p.
+       (alloc_tagged_tu_seen): New function
+       (free_all_tagged_tu_seen_up_to): New function.
+       (tagged_types_tu_compatible_p): Return the val of the seen two
+       types.
+       Add that the two types are the same to tagged_tu_seen_base
+       if they are and call comptypes_internal instead of comptypes.
+       <case UNION_TYPE>: Speed up common type where the fields are
+       in the same order.
+       (function_types_compatible_p): Call comptypes_internal instead of
+       comptypes.
+       (type_lists_compatible_p): Likewise.
+       (all functions): s/tagged_tu_seen/tagged_tu_seen_cache/.
+
 2005-10-02  Matthias Klose  <doko@debian.org>
 
        * doc/invoke.texi: Fix typo and speling error.
 2005-10-02  Matthias Klose  <doko@debian.org>
 
        * doc/invoke.texi: Fix typo and speling error.
index ff8577b..a72dac6 100644 (file)
@@ -105,7 +105,21 @@ static void readonly_error (tree, enum lvalue_use);
 static int lvalue_or_else (tree, enum lvalue_use);
 static int lvalue_p (tree);
 static void record_maybe_used_decl (tree);
 static int lvalue_or_else (tree, enum lvalue_use);
 static int lvalue_p (tree);
 static void record_maybe_used_decl (tree);
-\f
+static int comptypes_internal (tree, tree);
+\f/* 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;
+  tree t1;
+  tree t2;
+  /* The return value of tagged_types_tu_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 *);
+
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
 
 /* Do `exp = require_complete_type (exp);' to make sure exp
    does not have an incomplete type.  (That includes void types.)  */
 
@@ -663,7 +677,7 @@ common_type (tree t1, tree t2)
 
   return c_common_type (t1, t2);
 }
 
   return c_common_type (t1, t2);
 }
-\f
+
 /* 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.  */
 /* 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.  */
@@ -671,6 +685,22 @@ common_type (tree t1, tree t2)
 int
 comptypes (tree type1, tree type2)
 {
 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);
+  free_all_tagged_tu_seen_up_to (tagged_tu_seen_base1);
+  
+  return val;
+}\f
+/* 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.  This
+   differs from comptypes, in that we don't free the seen types.  */
+
+static int
+comptypes_internal (tree type1, tree type2)
+{
   tree t1 = type1;
   tree t2 = type2;
   int attrval, val;
   tree t1 = type1;
   tree t2 = type2;
   int attrval, val;
@@ -737,7 +767,7 @@ comptypes (tree type1, tree type2)
          || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
        break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
          || TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
        break;
       val = (TREE_TYPE (t1) == TREE_TYPE (t2)
-            ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2)));
+            ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2)));
       break;
 
     case FUNCTION_TYPE:
       break;
 
     case FUNCTION_TYPE:
@@ -754,7 +784,7 @@ comptypes (tree type1, tree type2)
 
        /* Target types must match incl. qualifiers.  */
        if (TREE_TYPE (t1) != TREE_TYPE (t2)
 
        /* Target types must match incl. qualifiers.  */
        if (TREE_TYPE (t1) != TREE_TYPE (t2)
-           && 0 == (val = comptypes (TREE_TYPE (t1), TREE_TYPE (t2))))
+           && 0 == (val = comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2))))
          return 0;
 
        /* Sizes must match unless one is missing or variable.  */
          return 0;
 
        /* Sizes must match unless one is missing or variable.  */
@@ -787,12 +817,16 @@ comptypes (tree type1, tree type2)
     case RECORD_TYPE:
     case UNION_TYPE:
       if (val != 1 && !same_translation_unit_p (t1, t2))
     case RECORD_TYPE:
     case UNION_TYPE:
       if (val != 1 && !same_translation_unit_p (t1, t2))
-       val = tagged_types_tu_compatible_p (t1, t2);
+        {
+         if (attrval != 2)
+           return tagged_types_tu_compatible_p (t1, t2);
+         val = tagged_types_tu_compatible_p (t1, t2);
+       }
       break;
 
     case VECTOR_TYPE:
       val = TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
       break;
 
     case VECTOR_TYPE:
       val = TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
-           && comptypes (TREE_TYPE (t1), TREE_TYPE (t2));
+           && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2));
       break;
 
     default:
       break;
 
     default:
@@ -861,21 +895,48 @@ same_translation_unit_p (tree t1, tree t2)
   return t1 == t2;
 }
 
   return t1 == t2;
 }
 
-/* The C standard says that two structures in different translation
-   units are compatible with each other only if the types of their
-   fields are compatible (among other things).  So, consider two copies
-   of this structure:  */
+/* Allocate the seen two types, assuming that they are compatible. */
 
 
-struct tagged_tu_seen {
-  const struct tagged_tu_seen * next;
-  tree t1;
-  tree t2;
-};
+static struct tagged_tu_seen_cache *
+alloc_tagged_tu_seen_cache (tree t1, tree t2)
+{
+  struct tagged_tu_seen_cache *tu = xmalloc (sizeof (struct tagged_tu_seen_cache));
+  tu->next = tagged_tu_seen_base;
+  tu->t1 = t1;
+  tu->t2 = t2;
+  
+  tagged_tu_seen_base = tu;
+  
+  /* The C standard says that two structures in different translation
+     units are compatible with each other only if the types of their
+     fields are compatible (among other things).  We assume that they
+     are compatible until proven otherwise when building the cache.
+     An example where this can occur is:
+     struct a
+     {
+       struct a *next;
+     };
+     If we are comparing this against a similar struct in another TU,
+     and did not assume they were compatiable, we end up with an infinite
+     loop.  */
+  tu->val = 1;
+  return tu;
+}
 
 
-/* Can they be compatible with each other?  We choose to break the
-   recursion by allowing those types to be compatible.  */
+/* Free the seen types until we get to TU_TIL. */
 
 
-static const struct tagged_tu_seen * tagged_tu_seen_base;
+static void
+free_all_tagged_tu_seen_up_to (const struct tagged_tu_seen_cache *tu_til)
+{
+  const struct tagged_tu_seen_cache *tu = tagged_tu_seen_base;
+  while (tu != tu_til)
+    {
+      struct tagged_tu_seen_cache *tu1 = (struct tagged_tu_seen_cache*)tu;
+      tu = tu1->next;
+      free (tu1);
+    }
+  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
 
 /* 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
@@ -917,73 +978,123 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
     return 1;
 
   {
     return 1;
 
   {
-    const struct tagged_tu_seen * tts_i;
+    const struct tagged_tu_seen_cache * tts_i;
     for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
       if (tts_i->t1 == t1 && tts_i->t2 == t2)
     for (tts_i = tagged_tu_seen_base; tts_i != NULL; tts_i = tts_i->next)
       if (tts_i->t1 == t1 && tts_i->t2 == t2)
-       return 1;
+       return tts_i->val;
   }
 
   switch (TREE_CODE (t1))
     {
     case ENUMERAL_TYPE:
       {
   }
 
   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);
 
         if (tv1 == tv2)
         /* Speed up the case where the type values are in the same order.  */
         tree tv1 = TYPE_VALUES (t1);
         tree tv2 = TYPE_VALUES (t2);
 
         if (tv1 == tv2)
-          return 1;
+         {
+           return 1;
+         }
 
         for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
           {
             if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
               break;
             if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
 
         for (;tv1 && tv2; tv1 = TREE_CHAIN (tv1), tv2 = TREE_CHAIN (tv2))
           {
             if (TREE_PURPOSE (tv1) != TREE_PURPOSE (tv2))
               break;
             if (simple_cst_equal (TREE_VALUE (tv1), TREE_VALUE (tv2)) != 1)
-              return 0;
+             {
+               tu->val = 0;
+               return 0;
+             }
           }
 
         if (tv1 == NULL_TREE && tv2 == NULL_TREE)
           }
 
         if (tv1 == NULL_TREE && tv2 == NULL_TREE)
-          return 1;
+         {
+           return 1;
+         }
         if (tv1 == NULL_TREE || tv2 == NULL_TREE)
         if (tv1 == NULL_TREE || tv2 == NULL_TREE)
-          return 0;
+         {
+           tu->val = 0;
+           return 0;
+         }
 
        if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2)))
 
        if (list_length (TYPE_VALUES (t1)) != list_length (TYPE_VALUES (t2)))
-         return 0;
+         {
+           tu->val = 0;
+           return 0;
+         }
 
        for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1))
          {
            s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2));
            if (s2 == NULL
                || simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1)
 
        for (s1 = TYPE_VALUES (t1); s1; s1 = TREE_CHAIN (s1))
          {
            s2 = purpose_member (TREE_PURPOSE (s1), TYPE_VALUES (t2));
            if (s2 == NULL
                || simple_cst_equal (TREE_VALUE (s1), TREE_VALUE (s2)) != 1)
-             return 0;
+             {
+               tu->val = 0;
+               return 0;
+             }
          }
        return 1;
       }
 
     case UNION_TYPE:
       {
          }
        return 1;
       }
 
     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)))
        if (list_length (TYPE_FIELDS (t1)) != list_length (TYPE_FIELDS (t2)))
-         return 0;
+         {
+           tu->val = 0;
+           return 0;
+         }
+       
+       /*  Speed up the common case where the fields are in the same order. */
+       for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2); s1 && s2;
+            s1 = TREE_CHAIN (s1), s2 = TREE_CHAIN (s2))
+         {
+           int result;
+           
+           
+           if (DECL_NAME (s1) == NULL
+               || DECL_NAME (s1) != DECL_NAME (s2))
+             break;
+           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
+           if (result == 0)
+             {
+               tu->val = 0;
+               return 0;
+             }
+           if (result == 2)
+             needs_warning = true;
+
+           if (TREE_CODE (s1) == FIELD_DECL
+               && simple_cst_equal (DECL_FIELD_BIT_OFFSET (s1),
+                                    DECL_FIELD_BIT_OFFSET (s2)) != 1)
+             {
+               tu->val = 0;
+               return 0;
+             }
+         }
+       if (!s1 && !s2)
+         {
+           tu->val = needs_warning ? 2 : 1;
+           return tu->val;
+         }
 
        for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
          {
            bool ok = false;
 
        for (s1 = TYPE_FIELDS (t1); s1; s1 = TREE_CHAIN (s1))
          {
            bool ok = false;
-           struct tagged_tu_seen tts;
-
-           tts.next = tagged_tu_seen_base;
-           tts.t1 = t1;
-           tts.t2 = t2;
-           tagged_tu_seen_base = &tts;
 
            if (DECL_NAME (s1) != NULL)
              for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
                if (DECL_NAME (s1) == DECL_NAME (s2))
                  {
                    int result;
 
            if (DECL_NAME (s1) != NULL)
              for (s2 = TYPE_FIELDS (t2); s2; s2 = TREE_CHAIN (s2))
                if (DECL_NAME (s1) == DECL_NAME (s2))
                  {
                    int result;
-                   result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2));
+                   result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
                    if (result == 0)
                    if (result == 0)
-                     break;
+                     {
+                       tu->val = 0;
+                       return 0;
+                     }
                    if (result == 2)
                      needs_warning = true;
 
                    if (result == 2)
                      needs_warning = true;
 
@@ -995,21 +1106,19 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
                    ok = true;
                    break;
                  }
                    ok = true;
                    break;
                  }
-           tagged_tu_seen_base = tts.next;
            if (!ok)
            if (!ok)
-             return 0;
+             {
+               tu->val = 0;
+               return 0;
+             }
          }
          }
-       return needs_warning ? 2 : 1;
+       tu->val = needs_warning ? 2 : 10;
+       return tu->val;
       }
 
     case RECORD_TYPE:
       {
       }
 
     case RECORD_TYPE:
       {
-       struct tagged_tu_seen tts;
-
-       tts.next = tagged_tu_seen_base;
-       tts.t1 = t1;
-       tts.t2 = t2;
-       tagged_tu_seen_base = &tts;
+        struct tagged_tu_seen_cache *tu = alloc_tagged_tu_seen_cache (t1, t2);
 
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
             s1 && s2;
 
        for (s1 = TYPE_FIELDS (t1), s2 = TYPE_FIELDS (t2);
             s1 && s2;
@@ -1019,7 +1128,7 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
            if (TREE_CODE (s1) != TREE_CODE (s2)
                || DECL_NAME (s1) != DECL_NAME (s2))
              break;
            if (TREE_CODE (s1) != TREE_CODE (s2)
                || DECL_NAME (s1) != DECL_NAME (s2))
              break;
-           result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2));
+           result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2));
            if (result == 0)
              break;
            if (result == 2)
            if (result == 0)
              break;
            if (result == 2)
@@ -1030,10 +1139,11 @@ tagged_types_tu_compatible_p (tree t1, tree t2)
                                     DECL_FIELD_BIT_OFFSET (s2)) != 1)
              break;
          }
                                     DECL_FIELD_BIT_OFFSET (s2)) != 1)
              break;
          }
-       tagged_tu_seen_base = tts.next;
        if (s1 && s2)
        if (s1 && s2)
-         return 0;
-       return needs_warning ? 2 : 1;
+         tu->val = 0;
+       else
+         tu->val = needs_warning ? 2 : 1;
+       return tu->val;
       }
 
     default:
       }
 
     default:
@@ -1070,7 +1180,7 @@ function_types_compatible_p (tree f1, tree f2)
   if (TYPE_VOLATILE (ret2))
     ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
                                 TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
   if (TYPE_VOLATILE (ret2))
     ret2 = build_qualified_type (TYPE_MAIN_VARIANT (ret2),
                                 TYPE_QUALS (ret2) & ~TYPE_QUAL_VOLATILE);
-  val = comptypes (ret1, ret2);
+  val = comptypes_internal (ret1, ret2);
   if (val == 0)
     return 0;
 
   if (val == 0)
     return 0;
 
@@ -1151,7 +1261,7 @@ type_lists_compatible_p (tree args1, tree args2)
       else if (TREE_CODE (a1) == ERROR_MARK
               || TREE_CODE (a2) == ERROR_MARK)
        ;
       else if (TREE_CODE (a1) == ERROR_MARK
               || TREE_CODE (a2) == ERROR_MARK)
        ;
-      else if (!(newval = comptypes (mv1, mv2)))
+      else if (!(newval = comptypes_internal (mv1, mv2)))
        {
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
        {
          /* Allow  wait (union {union wait *u; int *i} *)
             and  wait (union wait *)  to be compatible.  */
@@ -1170,7 +1280,7 @@ type_lists_compatible_p (tree args1, tree args2)
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes (mv3, mv2))
+                 if (comptypes_internal (mv3, mv2))
                    break;
                }
              if (memb == 0)
                    break;
                }
              if (memb == 0)
@@ -1191,7 +1301,7 @@ type_lists_compatible_p (tree args1, tree args2)
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
                  if (mv3 && mv3 != error_mark_node
                      && TREE_CODE (mv3) != ARRAY_TYPE)
                    mv3 = TYPE_MAIN_VARIANT (mv3);
-                 if (comptypes (mv3, mv1))
+                 if (comptypes_internal (mv3, mv1))
                    break;
                }
              if (memb == 0)
                    break;
                }
              if (memb == 0)