From 7e58afa1fccd88427cb22c4b94cffc49a30ea95c Mon Sep 17 00:00:00 2001 From: pinskia Date: Sun, 2 Oct 2005 19:15:58 +0000 Subject: [PATCH] 2005-10-02 Andrew Pinski 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. : 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 | 23 ++++++ gcc/c-typeck.c | 216 +++++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 186 insertions(+), 53 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 233026b..e712977 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2005-10-02 Andrew Pinski + + 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. + : 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 * doc/invoke.texi: Fix typo and speling error. diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c index ff8577b..a72dac6 100644 --- a/gcc/c-typeck.c +++ b/gcc/c-typeck.c @@ -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 comptypes_internal (tree, tree); + /* 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.) */ @@ -663,7 +677,7 @@ common_type (tree t1, tree t2) return c_common_type (t1, t2); } - + /* 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) { + 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; +} +/* 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; @@ -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) - ? 1 : comptypes (TREE_TYPE (t1), TREE_TYPE (t2))); + ? 1 : comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2))); 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) - && 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. */ @@ -787,12 +817,16 @@ comptypes (tree type1, tree type2) 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) - && comptypes (TREE_TYPE (t1), TREE_TYPE (t2)); + && comptypes_internal (TREE_TYPE (t1), TREE_TYPE (t2)); break; default: @@ -861,21 +895,48 @@ same_translation_unit_p (tree t1, tree 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 @@ -917,73 +978,123 @@ tagged_types_tu_compatible_p (tree t1, tree t2) 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) - return 1; + return tts_i->val; } 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) - 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) - return 0; + { + tu->val = 0; + return 0; + } } if (tv1 == NULL_TREE && tv2 == NULL_TREE) - return 1; + { + return 1; + } 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))) - 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) - return 0; + { + tu->val = 0; + return 0; + } } 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))) - 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; - 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; - result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2)); + result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2)); if (result == 0) - break; + { + tu->val = 0; + return 0; + } if (result == 2) needs_warning = true; @@ -995,21 +1106,19 @@ tagged_types_tu_compatible_p (tree t1, tree t2) ok = true; break; } - tagged_tu_seen_base = tts.next; 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: { - 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; @@ -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; - result = comptypes (TREE_TYPE (s1), TREE_TYPE (s2)); + result = comptypes_internal (TREE_TYPE (s1), TREE_TYPE (s2)); 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; } - tagged_tu_seen_base = tts.next; if (s1 && s2) - return 0; - return needs_warning ? 2 : 1; + tu->val = 0; + else + tu->val = needs_warning ? 2 : 1; + return tu->val; } 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); - val = comptypes (ret1, ret2); + val = comptypes_internal (ret1, ret2); 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 (!(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. */ @@ -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 (comptypes (mv3, mv2)) + if (comptypes_internal (mv3, mv2)) 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 (comptypes (mv3, mv1)) + if (comptypes_internal (mv3, mv1)) break; } if (memb == 0) -- 2.7.4