From patchwork Wed Jul 2 03:20:19 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 366230 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 78AFE140095 for ; Wed, 2 Jul 2014 13:20:53 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=UN3etJgQ72REdwkLZhbhrgVk/j+qgiKrXQYb8uHHD5tO66ZuP9mtI Jjm74q/qjkCSeapZbD/Y68IG4GjcN4Kqc0aSJhTmf5aoOp1gdoJe/TIlYjyPGQBM pKI7reApD8oubiB5+hD/6I19zsrxR+jtpaO6c/QVZyiPhwCORmhNqY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=TxyqzqMBDEhawJoHmS+zK0z2D/E=; b=DPn6gzIH6zhsyI6zaOVR +DC4fbn4bTcfCUu+k0CZE+uXdAXd5ZDKFH6g5oOVATzFwsT3KOkGeEc5TqxNJko1 hDrpp/4RdjsDKR3U8t1DhjHq+FaBKelpyPayYTlMN3c7XtwEKXUsstZYokjWtND9 0DGFppX2LxKPSQSi69WicR4= Received: (qmail 11619 invoked by alias); 2 Jul 2014 03:20:44 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 11473 invoked by uid 89); 2 Jul 2014 03:20:29 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.4 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_LOW, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: nikam.ms.mff.cuni.cz Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 02 Jul 2014 03:20:24 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id E76E1541DBF; Wed, 2 Jul 2014 05:20:19 +0200 (CEST) Date: Wed, 2 Jul 2014 05:20:19 +0200 From: Jan Hubicka To: gcc-patches@gcc.gnu.org Subject: ipa-devirt tweeks Message-ID: <20140702032019.GA9591@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) Hi, this is a preparation patch for the ODR type work. It removes odr comparsion code from tree.c that never worked (because it misses names of template parameters) and is for quite a while replaced by compared assembler names of virtual tables of polymorphic types. I plan to extend this trick and stream mangled names of all non-anonymous types in C++. The ODR hash is now hashing types by their names not only main variants, it allows inserting incomplete types and later replacing them by complete variants and it records cases where ODR violations was found. I also added checks needed to make odr hash work on all types, not only classes, so we need to watch out before accessing TYPE_BINFO. There are no functional changes with current code, Bootstrapped/regtested x86_64-linux and tested with patches enabling the new code paths on Firefox/LTO bootstrap, comitted. * tree.c (decls_same_for_odr, decls_same_for_odr, types_same_for_odr): Remove. (type_in_anonymous_namespace_p): Constify argument. * tree.h (types_same_for_odr, type_in_anonymous_namespace_p): Constify. * ipa-devirt.c (odr_type_d): Add ODR_VIOLATED field. (main_odr_variant): New function. (hash_type_name): Make static; update assert; do not ICE on non-records. (types_same_for_odr): Bring here from tree.c; simplify and remove old structural comparing code that doesn't work for templates. (odr_hasher::equal): Update assert. (add_type_duplicate): Return true when bases should be computed; replace incomplete loader by complete; do not output duplicated warnings; do not ICE on non-records; set odr_violated flag. (get_odr_type): Be ready to replace incomplete type by complete one; work on ODR variants instead of main variants; reorder item in array so bases have still smaller indexes. (dump_type_inheritance_graph): Be ready for holdes in odr_types array. (possible_polymorphic_call_targets): Do not ICE when BINFO is NULL. Index: tree.c =================================================================== --- tree.c (revision 212211) +++ tree.c (working copy) @@ -232,7 +232,6 @@ static void print_value_expr_statistics static int type_hash_marked_p (const void *); static unsigned int type_hash_list (const_tree, hashval_t); static unsigned int attribute_hash_list (const_tree, hashval_t); -static bool decls_same_for_odr (tree decl1, tree decl2); tree global_trees[TI_MAX]; tree integer_types[itk_none]; @@ -11821,151 +11820,6 @@ lhd_gcc_personality (void) return gcc_eh_personality_decl; } -/* For languages with One Definition Rule, work out if - trees are actually the same even if the tree representation - differs. This handles only decls appearing in TYPE_NAME - and TYPE_CONTEXT. That is NAMESPACE_DECL, TYPE_DECL, - RECORD_TYPE and IDENTIFIER_NODE. */ - -static bool -same_for_odr (tree t1, tree t2) -{ - if (t1 == t2) - return true; - if (!t1 || !t2) - return false; - /* C and C++ FEs differ by using IDENTIFIER_NODE and TYPE_DECL. */ - if (TREE_CODE (t1) == IDENTIFIER_NODE - && TREE_CODE (t2) == TYPE_DECL - && DECL_FILE_SCOPE_P (t1)) - { - t2 = DECL_NAME (t2); - gcc_assert (TREE_CODE (t2) == IDENTIFIER_NODE); - } - if (TREE_CODE (t2) == IDENTIFIER_NODE - && TREE_CODE (t1) == TYPE_DECL - && DECL_FILE_SCOPE_P (t2)) - { - t1 = DECL_NAME (t1); - gcc_assert (TREE_CODE (t1) == IDENTIFIER_NODE); - } - if (TREE_CODE (t1) != TREE_CODE (t2)) - return false; - if (TYPE_P (t1)) - return types_same_for_odr (t1, t2); - if (DECL_P (t1)) - return decls_same_for_odr (t1, t2); - return false; -} - -/* For languages with One Definition Rule, work out if - decls are actually the same even if the tree representation - differs. This handles only decls appearing in TYPE_NAME - and TYPE_CONTEXT. That is NAMESPACE_DECL, TYPE_DECL, - RECORD_TYPE and IDENTIFIER_NODE. */ - -static bool -decls_same_for_odr (tree decl1, tree decl2) -{ - if (decl1 && TREE_CODE (decl1) == TYPE_DECL - && DECL_ORIGINAL_TYPE (decl1)) - decl1 = DECL_ORIGINAL_TYPE (decl1); - if (decl2 && TREE_CODE (decl2) == TYPE_DECL - && DECL_ORIGINAL_TYPE (decl2)) - decl2 = DECL_ORIGINAL_TYPE (decl2); - if (decl1 == decl2) - return true; - if (!decl1 || !decl2) - return false; - gcc_checking_assert (DECL_P (decl1) && DECL_P (decl2)); - if (TREE_CODE (decl1) != TREE_CODE (decl2)) - return false; - if (TREE_CODE (decl1) == TRANSLATION_UNIT_DECL) - return true; - if (TREE_CODE (decl1) != NAMESPACE_DECL - && TREE_CODE (decl1) != TYPE_DECL) - return false; - if (!DECL_NAME (decl1)) - return false; - gcc_checking_assert (TREE_CODE (DECL_NAME (decl1)) == IDENTIFIER_NODE); - gcc_checking_assert (!DECL_NAME (decl2) - || TREE_CODE (DECL_NAME (decl2)) == IDENTIFIER_NODE); - if (DECL_NAME (decl1) != DECL_NAME (decl2)) - return false; - return same_for_odr (DECL_CONTEXT (decl1), - DECL_CONTEXT (decl2)); -} - -/* For languages with One Definition Rule, work out if - types are same even if the tree representation differs. - This is non-trivial for LTO where minnor differences in - the type representation may have prevented type merging - to merge two copies of otherwise equivalent type. */ - -bool -types_same_for_odr (tree type1, tree type2) -{ - gcc_checking_assert (TYPE_P (type1) && TYPE_P (type2)); - type1 = TYPE_MAIN_VARIANT (type1); - type2 = TYPE_MAIN_VARIANT (type2); - if (type1 == type2) - return true; - -#ifndef ENABLE_CHECKING - if (!in_lto_p) - return false; -#endif - - /* Check for anonymous namespaces. Those have !TREE_PUBLIC - on the corresponding TYPE_STUB_DECL. */ - if (type_in_anonymous_namespace_p (type1) - || type_in_anonymous_namespace_p (type2)) - return false; - /* When assembler name of virtual table is available, it is - easy to compare types for equivalence. */ - if (TYPE_BINFO (type1) && TYPE_BINFO (type2) - && BINFO_VTABLE (TYPE_BINFO (type1)) - && BINFO_VTABLE (TYPE_BINFO (type2))) - { - tree v1 = BINFO_VTABLE (TYPE_BINFO (type1)); - tree v2 = BINFO_VTABLE (TYPE_BINFO (type2)); - - if (TREE_CODE (v1) == POINTER_PLUS_EXPR) - { - if (TREE_CODE (v2) != POINTER_PLUS_EXPR - || !operand_equal_p (TREE_OPERAND (v1, 1), - TREE_OPERAND (v2, 1), 0)) - return false; - v1 = TREE_OPERAND (TREE_OPERAND (v1, 0), 0); - v2 = TREE_OPERAND (TREE_OPERAND (v2, 0), 0); - } - v1 = DECL_ASSEMBLER_NAME (v1); - v2 = DECL_ASSEMBLER_NAME (v2); - return (v1 == v2); - } - - /* FIXME: the code comparing type names consider all instantiations of the - same template to have same name. This is because we have no access - to template parameters. For types with no virtual method tables - we thus can return false positives. At the moment we do not need - to compare types in other scenarios than devirtualization. */ - - /* If types are not structuraly same, do not bother to contnue. - Match in the remainder of code would mean ODR violation. */ - if (!types_compatible_p (type1, type2)) - return false; - if (!TYPE_NAME (type1)) - return false; - if (!decls_same_for_odr (TYPE_NAME (type1), TYPE_NAME (type2))) - return false; - if (!same_for_odr (TYPE_CONTEXT (type1), TYPE_CONTEXT (type2))) - return false; - /* When not in LTO the MAIN_VARIANT check should be the same. */ - gcc_assert (in_lto_p); - - return true; -} - /* TARGET is a call target of GIMPLE call statement (obtained by gimple_call_fn). Return true if it is OBJ_TYPE_REF representing an virtual call of C++ method. @@ -12009,7 +11863,7 @@ obj_type_ref_class (tree ref) /* Return true if T is in anonymous namespace. */ bool -type_in_anonymous_namespace_p (tree t) +type_in_anonymous_namespace_p (const_tree t) { return (TYPE_STUB_DECL (t) && !TREE_PUBLIC (TYPE_STUB_DECL (t))); } Index: tree.h =================================================================== --- tree.h (revision 212211) +++ tree.h (working copy) @@ -4316,9 +4316,9 @@ extern tree block_ultimate_origin (const extern tree get_binfo_at_offset (tree, HOST_WIDE_INT, tree); extern bool virtual_method_call_p (tree); extern tree obj_type_ref_class (tree ref); -extern bool types_same_for_odr (tree type1, tree type2); +extern bool types_same_for_odr (const_tree type1, const_tree type2); extern bool contains_bitfld_component_ref_p (const_tree); -extern bool type_in_anonymous_namespace_p (tree); +extern bool type_in_anonymous_namespace_p (const_tree); extern bool block_may_fallthru (const_tree); extern void using_eh_for_cleanups (void); extern bool using_eh_for_cleanups_p (void); Index: ipa-devirt.c =================================================================== --- ipa-devirt.c (revision 212211) +++ ipa-devirt.c (working copy) @@ -149,9 +149,10 @@ struct GTY(()) odr_type_d { /* leader type. */ tree type; - /* All bases. */ + /* All bases; built only for main variants of types */ vec GTY((skip)) bases; - /* All derrived types with virtual methods seen in unit. */ + /* All derrived types with virtual methods seen in unit; + buildt only for main variants oftypes */ vec GTY((skip)) derived_types; /* All equivalent types, if more than one. */ @@ -165,6 +166,8 @@ struct GTY(()) odr_type_d bool anonymous_namespace; /* Do we know about all derivations of given type? */ bool all_derivations_known; + /* Did we report ODR violation here? */ + bool odr_violated; }; @@ -249,12 +252,25 @@ struct odr_hasher static inline void remove (value_type *); }; +/* Return type that was declared with T's name so that T is an + qualified variant of it. */ + +static inline tree +main_odr_variant (const_tree t) +{ + if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) + return TREE_TYPE (TYPE_NAME (t)); + /* Unnamed types and non-C++ produced types can be compared by variants. */ + else + return TYPE_MAIN_VARIANT (t); +} + /* Produce hash based on type name. */ -hashval_t +static hashval_t hash_type_name (tree t) { - gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t); + gcc_checking_assert (main_odr_variant (t) == t); /* If not in LTO, all main variants are unique, so we can do pointer hash. */ @@ -266,7 +282,8 @@ hash_type_name (tree t) return htab_hash_pointer (t); /* For polymorphic types, we can simply hash the virtual table. */ - if (TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t))) + if (TREE_CODE (t) == RECORD_TYPE + && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t))) { tree v = BINFO_VTABLE (TYPE_BINFO (t)); hashval_t hash = 0; @@ -294,6 +311,61 @@ odr_hasher::hash (const value_type *odr_ return hash_type_name (odr_type->type); } +/* For languages with One Definition Rule, work out if + types are the same based on their name. + + This is non-trivial for LTO where minnor differences in + the type representation may have prevented type merging + to merge two copies of otherwise equivalent type. + + Until we start streaming mangled type names, this function works + only for polymorphic types. */ + +bool +types_same_for_odr (const_tree type1, const_tree type2) +{ + gcc_checking_assert (TYPE_P (type1) && TYPE_P (type2)); + + type1 = main_odr_variant (type1); + type2 = main_odr_variant (type2); + + if (type1 == type2) + return true; + + if (!in_lto_p) + return false; + + /* Check for anonymous namespaces. Those have !TREE_PUBLIC + on the corresponding TYPE_STUB_DECL. */ + if (type_in_anonymous_namespace_p (type1) + || type_in_anonymous_namespace_p (type2)) + return false; + + /* At the moment we have no way to establish ODR equivlaence at LTO + other than comparing virtual table pointrs of polymorphic types. + Eventually we should start saving mangled names in TYPE_NAME. + Then this condition will become non-trivial. */ + + if (TREE_CODE (type1) == RECORD_TYPE + && TYPE_BINFO (type1) && TYPE_BINFO (type2) + && BINFO_VTABLE (TYPE_BINFO (type1)) + && BINFO_VTABLE (TYPE_BINFO (type2))) + { + tree v1 = BINFO_VTABLE (TYPE_BINFO (type1)); + tree v2 = BINFO_VTABLE (TYPE_BINFO (type2)); + gcc_assert (TREE_CODE (v1) == POINTER_PLUS_EXPR + && TREE_CODE (v2) == POINTER_PLUS_EXPR); + return (operand_equal_p (TREE_OPERAND (v1, 1), + TREE_OPERAND (v2, 1), 0) + && DECL_ASSEMBLER_NAME + (TREE_OPERAND (TREE_OPERAND (v1, 0), 0)) + == DECL_ASSEMBLER_NAME + (TREE_OPERAND (TREE_OPERAND (v2, 0), 0))); + } + gcc_unreachable (); +} + + /* Compare types T1 and T2 and return true if they are equivalent. */ @@ -302,7 +374,7 @@ odr_hasher::equal (const value_type *t1, { tree t2 = const_cast (ct2); - gcc_checking_assert (TYPE_MAIN_VARIANT (ct2) == ct2); + gcc_checking_assert (main_odr_variant (t2) == t2); if (t1->type == t2) return true; if (!in_lto_p) @@ -350,20 +422,34 @@ set_type_binfo (tree type, tree binfo) all variants of the same type. It may or may not mean the ODR violation. Add it to the list of duplicates and warn on some violations. */ -static void +static bool add_type_duplicate (odr_type val, tree type) { + bool build_bases = false; if (!val->types_set) val->types_set = pointer_set_create (); + /* Always prefer complete type to be the leader. */ + if (!COMPLETE_TYPE_P (val->type) + && COMPLETE_TYPE_P (type)) + { + tree tmp = type; + + build_bases = true; + type = val->type; + val->type = tmp; + } + /* See if this duplicate is new. */ if (!pointer_set_insert (val->types_set, type)) { bool merge = true; bool base_mismatch = false; + bool warned = 0; + unsigned int i,j; + gcc_assert (in_lto_p); vec_safe_push (val->types, type); - unsigned int i,j; /* First we compare memory layout. */ if (!types_compatible_p (val->type, type)) @@ -374,9 +460,13 @@ add_type_duplicate (odr_type val, tree t && warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (type)), 0, "type %qD violates one definition rule ", type)) - inform (DECL_SOURCE_LOCATION (TYPE_NAME (val->type)), - "a type with the same name but different layout is " - "defined in another translation unit"); + { + inform (DECL_SOURCE_LOCATION (TYPE_NAME (val->type)), + "a type with the same name but different layout is " + "defined in another translation unit"); + warned = true; + } + val->odr_violated = true; if (cgraph_dump_file) { fprintf (cgraph_dump_file, "ODR violation or merging or ODR type bug?\n"); @@ -390,37 +480,45 @@ add_type_duplicate (odr_type val, tree t /* Next sanity check that bases are the same. If not, we will end up producing wrong answers. */ - for (j = 0, i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++) - if (polymorphic_type_binfo_p (BINFO_BASE_BINFO (TYPE_BINFO (type), i))) - { - odr_type base = get_odr_type - (BINFO_TYPE - (BINFO_BASE_BINFO (TYPE_BINFO (type), - i)), - true); - if (val->bases.length () <= j || val->bases[j] != base) - base_mismatch = true; - j++; - } - if (base_mismatch) - { - merge = false; - odr_violation_reported = true; - - if (warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (type)), 0, - "type %qD violates one definition rule ", - type)) - inform (DECL_SOURCE_LOCATION (TYPE_NAME (val->type)), - "a type with the same name but different bases is " - "defined in another translation unit"); - if (cgraph_dump_file) + if (COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (val->type) + && TREE_CODE (val->type) == RECORD_TYPE + && TREE_CODE (type) == RECORD_TYPE + && TYPE_BINFO (val->type) && TYPE_BINFO (type)) + { + for (j = 0, i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++) + if (polymorphic_type_binfo_p (BINFO_BASE_BINFO (TYPE_BINFO (type), i))) + { + odr_type base = get_odr_type + (BINFO_TYPE + (BINFO_BASE_BINFO (TYPE_BINFO (type), + i)), + true); + if (val->bases.length () <= j || val->bases[j] != base) + base_mismatch = true; + j++; + } + if (base_mismatch) { - fprintf (cgraph_dump_file, "ODR bse violation or merging bug?\n"); - - print_node (cgraph_dump_file, "", val->type, 0); - putc ('\n',cgraph_dump_file); - print_node (cgraph_dump_file, "", type, 0); - putc ('\n',cgraph_dump_file); + merge = false; + odr_violation_reported = true; + + if (!warned + && warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (type)), 0, + "type %qD violates one definition rule ", + type)) + inform (DECL_SOURCE_LOCATION (TYPE_NAME (val->type)), + "a type with the same name but different bases is " + "defined in another translation unit"); + val->odr_violated = true; + if (cgraph_dump_file) + { + fprintf (cgraph_dump_file, "ODR bse violation or merging bug?\n"); + + print_node (cgraph_dump_file, "", val->type, 0); + putc ('\n',cgraph_dump_file); + print_node (cgraph_dump_file, "", type, 0); + putc ('\n',cgraph_dump_file); + } } } @@ -436,7 +534,14 @@ add_type_duplicate (odr_type val, tree t merged LTO unit. For this reason we absolutely need to remove them and replace by internal variants. Not doing so will lead to incomplete answers from possible_polymorphic_call_targets. */ - if (!flag_ltrans && merge) + if (!flag_ltrans && merge + && TREE_CODE (val->type) == RECORD_TYPE + && TREE_CODE (type) == RECORD_TYPE + && TYPE_BINFO (val->type) && TYPE_BINFO (type) + && TYPE_MAIN_VARIANT (type) == type + && TYPE_MAIN_VARIANT (val->type) == val->type + && BINFO_VTABLE (TYPE_BINFO (val->type)) + && BINFO_VTABLE (TYPE_BINFO (type))) { tree master_binfo = TYPE_BINFO (val->type); tree v1 = BINFO_VTABLE (master_binfo); @@ -470,6 +575,7 @@ add_type_duplicate (odr_type val, tree t set_type_binfo (type, master_binfo); } } + return build_bases; } /* Get ODR type hash entry for TYPE. If INSERT is true, create @@ -481,9 +587,12 @@ get_odr_type (tree type, bool insert) odr_type_d **slot; odr_type val; hashval_t hash; + bool build_bases = false; + bool insert_to_odr_array = false; + int base_id = -1; + + type = main_odr_variant (type); - type = TYPE_MAIN_VARIANT (type); - gcc_checking_assert (TYPE_MAIN_VARIANT (type) == type); hash = hash_type_name (type); slot = odr_hash->find_slot_with_hash (type, hash, insert ? INSERT : NO_INSERT); @@ -498,19 +607,28 @@ get_odr_type (tree type, bool insert) /* With LTO we need to support multiple tree representation of the same ODR type. */ if (val->type != type) - add_type_duplicate (val, type); + build_bases = add_type_duplicate (val, type); } else { - tree binfo = TYPE_BINFO (type); - unsigned int i; val = ggc_cleared_alloc (); val->type = type; - gcc_assert (BINFO_TYPE (TYPE_BINFO (val->type)) = type); val->bases = vNULL; val->derived_types = vNULL; val->anonymous_namespace = type_in_anonymous_namespace_p (type); + build_bases = COMPLETE_TYPE_P (val->type); + insert_to_odr_array = true; + } + + if (build_bases && TREE_CODE (type) == RECORD_TYPE && TYPE_BINFO (type) + && type == TYPE_MAIN_VARIANT (type)) + { + tree binfo = TYPE_BINFO (type); + unsigned int i; + + gcc_assert (BINFO_TYPE (TYPE_BINFO (val->type)) = type); + val->all_derivations_known = type_all_derivations_known_p (type); *slot = val; for (i = 0; i < BINFO_N_BASE_BINFOS (binfo); i++) @@ -522,14 +640,27 @@ get_odr_type (tree type, bool insert) odr_type base = get_odr_type (BINFO_TYPE (BINFO_BASE_BINFO (binfo, i)), true); + gcc_assert (TYPE_MAIN_VARIANT (base->type) == base->type); base->derived_types.safe_push (val); val->bases.safe_push (base); + if (base->id > base_id) + base_id = base->id; } - /* First record bases, then add into array so ids are increasing. */ + } + /* Ensure that type always appears after bases. */ + if (insert_to_odr_array) + { if (odr_types_ptr) val->id = odr_types.length (); vec_safe_push (odr_types_ptr, val); } + else if (base_id > val->id) + { + odr_types[val->id] = 0; + if (odr_types_ptr) + val->id = odr_types.length (); + vec_safe_push (odr_types_ptr, val); + } return val; } @@ -577,12 +708,12 @@ dump_type_inheritance_graph (FILE *f) fprintf (f, "\n\nType inheritance graph:\n"); for (i = 0; i < odr_types.length (); i++) { - if (odr_types[i]->bases.length () == 0) + if (odr_types[i] && odr_types[i]->bases.length () == 0) dump_odr_type (f, odr_types[i]); } for (i = 0; i < odr_types.length (); i++) { - if (odr_types[i]->types && odr_types[i]->types->length ()) + if (odr_types[i] && odr_types[i]->types && odr_types[i]->types->length ()) { unsigned int j; fprintf (f, "Duplicate tree types for odr type %i\n", i); @@ -637,7 +768,8 @@ build_type_inheritance_graph (void) if (is_a (n) && DECL_VIRTUAL_P (n->decl) && symtab_real_symbol_p (n)) - get_odr_type (method_class_type (TREE_TYPE (n->decl)), true); + get_odr_type (TYPE_MAIN_VARIANT (method_class_type (TREE_TYPE (n->decl))), + true); /* Look also for virtual tables of types that do not define any methods. @@ -663,7 +795,7 @@ build_type_inheritance_graph (void) && TREE_CODE (DECL_CONTEXT (n->decl)) == RECORD_TYPE && TYPE_BINFO (DECL_CONTEXT (n->decl)) && polymorphic_type_binfo_p (TYPE_BINFO (DECL_CONTEXT (n->decl)))) - get_odr_type (DECL_CONTEXT (n->decl), true); + get_odr_type (TYPE_MAIN_VARIANT (DECL_CONTEXT (n->decl)), true); if (inheritance_dump_file) { dump_type_inheritance_graph (inheritance_dump_file); @@ -1758,7 +1890,8 @@ possible_polymorphic_call_targets (tree gcc_assert (in_lto_p || context.maybe_derived_type); } - pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo)); + if (binfo) + pointer_set_insert (matched_vtables, BINFO_VTABLE (binfo)); /* Next walk recursively all derived types. */ if (context.maybe_derived_type) @@ -1827,7 +1960,7 @@ dump_possible_polymorphic_call_targets ( { vec targets; bool final; - odr_type type = get_odr_type (otr_type, false); + odr_type type = get_odr_type (TYPE_MAIN_VARIANT (otr_type), false); unsigned int i; int nonconstruction; @@ -1926,7 +2059,8 @@ update_type_inheritance_graph (void) if (DECL_VIRTUAL_P (n->decl) && !n->definition && symtab_real_symbol_p (n)) - get_odr_type (method_class_type (TREE_TYPE (n->decl)), true); + get_odr_type (method_class_type (TYPE_MAIN_VARIANT (TREE_TYPE (n->decl))), + true); timevar_pop (TV_IPA_INHERITANCE); }