From patchwork Thu Dec 22 17:41:22 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Martin Uecker X-Patchwork-Id: 62280 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 999E63858298 for ; Thu, 22 Dec 2022 17:42:04 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 999E63858298 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1671730924; bh=fyZMDFLCD+jfeRsbO0Wi2tW27WI7bwYdCW4wneQxgok=; h=Subject:To:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=qBKykY9PpyuNKdCgdimOXdQCmg+wvFoE69C4rcBgOYFPeIy576Nzhz1oqJH/JFvKM qOZfkajHffrCRpQ20iOjUefXdUcA4NEreRudx1N1UrvegQ+ZMLNiBVOlQUduE/k4fW j4qOvH0KjOCUv672RwXI7RD+VUSks6I/Yxk0riuI= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mailrelay.tugraz.at (mailrelay.tugraz.at [129.27.2.202]) by sourceware.org (Postfix) with ESMTPS id 3F0BE3858D1E for ; Thu, 22 Dec 2022 17:41:31 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 3F0BE3858D1E Received: from [192.168.0.221] (84-115-221-28.cable.dynamic.surfer.at [84.115.221.28]) by mailrelay.tugraz.at (Postfix) with ESMTPSA id 4NdHfq6pV0z1LM0C for ; Thu, 22 Dec 2022 18:41:22 +0100 (CET) DKIM-Filter: OpenDKIM Filter v2.11.0 mailrelay.tugraz.at 4NdHfq6pV0z1LM0C Message-ID: <9609efd537d50fe41001cc3bf6bb341e65d5f795.camel@tugraz.at> Subject: [C PATCH] (for STAGE 1) Reorganize comptypes and related functions To: gcc-patches@gcc.gnu.org Date: Thu, 22 Dec 2022 18:41:22 +0100 User-Agent: Evolution 3.38.3-1 MIME-Version: 1.0 X-TUG-Backscatter-control: G/VXY7/6zeyuAY/PU2/0qw X-Spam-Scanner: SpamAssassin 3.003001 X-Spam-Score-relay: -1.9 X-Scanned-By: MIMEDefang 2.74 on 129.27.10.117 X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Martin Uecker via Gcc-patches From: Martin Uecker Reply-To: Martin Uecker Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" 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, tree, vec *, vec *, 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)