138fd1498Szrj /* Basic IPA utilities for type inheritance graph construction and 238fd1498Szrj devirtualization. 338fd1498Szrj Copyright (C) 2013-2018 Free Software Foundation, Inc. 438fd1498Szrj Contributed by Jan Hubicka 538fd1498Szrj 638fd1498Szrj This file is part of GCC. 738fd1498Szrj 838fd1498Szrj GCC is free software; you can redistribute it and/or modify it under 938fd1498Szrj the terms of the GNU General Public License as published by the Free 1038fd1498Szrj Software Foundation; either version 3, or (at your option) any later 1138fd1498Szrj version. 1238fd1498Szrj 1338fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY 1438fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or 1538fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1638fd1498Szrj for more details. 1738fd1498Szrj 1838fd1498Szrj You should have received a copy of the GNU General Public License 1938fd1498Szrj along with GCC; see the file COPYING3. If not see 2038fd1498Szrj <http://www.gnu.org/licenses/>. */ 2138fd1498Szrj 2238fd1498Szrj /* Brief vocabulary: 2338fd1498Szrj ODR = One Definition Rule 2438fd1498Szrj In short, the ODR states that: 2538fd1498Szrj 1 In any translation unit, a template, type, function, or object can 2638fd1498Szrj have no more than one definition. Some of these can have any number 2738fd1498Szrj of declarations. A definition provides an instance. 2838fd1498Szrj 2 In the entire program, an object or non-inline function cannot have 2938fd1498Szrj more than one definition; if an object or function is used, it must 3038fd1498Szrj have exactly one definition. You can declare an object or function 3138fd1498Szrj that is never used, in which case you don't have to provide 3238fd1498Szrj a definition. In no event can there be more than one definition. 3338fd1498Szrj 3 Some things, like types, templates, and extern inline functions, can 3438fd1498Szrj be defined in more than one translation unit. For a given entity, 3538fd1498Szrj each definition must be the same. Non-extern objects and functions 3638fd1498Szrj in different translation units are different entities, even if their 3738fd1498Szrj names and types are the same. 3838fd1498Szrj 3938fd1498Szrj OTR = OBJ_TYPE_REF 4038fd1498Szrj This is the Gimple representation of type information of a polymorphic call. 4138fd1498Szrj It contains two parameters: 4238fd1498Szrj otr_type is a type of class whose method is called. 4338fd1498Szrj otr_token is the index into virtual table where address is taken. 4438fd1498Szrj 4538fd1498Szrj BINFO 4638fd1498Szrj This is the type inheritance information attached to each tree 4738fd1498Szrj RECORD_TYPE by the C++ frontend. It provides information about base 4838fd1498Szrj types and virtual tables. 4938fd1498Szrj 5038fd1498Szrj BINFO is linked to the RECORD_TYPE by TYPE_BINFO. 5138fd1498Szrj BINFO also links to its type by BINFO_TYPE and to the virtual table by 5238fd1498Szrj BINFO_VTABLE. 5338fd1498Szrj 5438fd1498Szrj Base types of a given type are enumerated by BINFO_BASE_BINFO 5538fd1498Szrj vector. Members of this vectors are not BINFOs associated 5638fd1498Szrj with a base type. Rather they are new copies of BINFOs 5738fd1498Szrj (base BINFOs). Their virtual tables may differ from 5838fd1498Szrj virtual table of the base type. Also BINFO_OFFSET specifies 5938fd1498Szrj offset of the base within the type. 6038fd1498Szrj 6138fd1498Szrj In the case of single inheritance, the virtual table is shared 6238fd1498Szrj and BINFO_VTABLE of base BINFO is NULL. In the case of multiple 6338fd1498Szrj inheritance the individual virtual tables are pointer to by 6438fd1498Szrj BINFO_VTABLE of base binfos (that differs of BINFO_VTABLE of 6538fd1498Szrj binfo associated to the base type). 6638fd1498Szrj 6738fd1498Szrj BINFO lookup for a given base type and offset can be done by 6838fd1498Szrj get_binfo_at_offset. It returns proper BINFO whose virtual table 6938fd1498Szrj can be used for lookup of virtual methods associated with the 7038fd1498Szrj base type. 7138fd1498Szrj 7238fd1498Szrj token 7338fd1498Szrj This is an index of virtual method in virtual table associated 7438fd1498Szrj to the type defining it. Token can be looked up from OBJ_TYPE_REF 7538fd1498Szrj or from DECL_VINDEX of a given virtual table. 7638fd1498Szrj 7738fd1498Szrj polymorphic (indirect) call 7838fd1498Szrj This is callgraph representation of virtual method call. Every 7938fd1498Szrj polymorphic call contains otr_type and otr_token taken from 8038fd1498Szrj original OBJ_TYPE_REF at callgraph construction time. 8138fd1498Szrj 8238fd1498Szrj What we do here: 8338fd1498Szrj 8438fd1498Szrj build_type_inheritance_graph triggers a construction of the type inheritance 8538fd1498Szrj graph. 8638fd1498Szrj 8738fd1498Szrj We reconstruct it based on types of methods we see in the unit. 8838fd1498Szrj This means that the graph is not complete. Types with no methods are not 8938fd1498Szrj inserted into the graph. Also types without virtual methods are not 9038fd1498Szrj represented at all, though it may be easy to add this. 9138fd1498Szrj 9238fd1498Szrj The inheritance graph is represented as follows: 9338fd1498Szrj 9438fd1498Szrj Vertices are structures odr_type. Every odr_type may correspond 9538fd1498Szrj to one or more tree type nodes that are equivalent by ODR rule. 9638fd1498Szrj (the multiple type nodes appear only with linktime optimization) 9738fd1498Szrj 9838fd1498Szrj Edges are represented by odr_type->base and odr_type->derived_types. 9938fd1498Szrj At the moment we do not track offsets of types for multiple inheritance. 10038fd1498Szrj Adding this is easy. 10138fd1498Szrj 10238fd1498Szrj possible_polymorphic_call_targets returns, given an parameters found in 10338fd1498Szrj indirect polymorphic edge all possible polymorphic call targets of the call. 10438fd1498Szrj 10538fd1498Szrj pass_ipa_devirt performs simple speculative devirtualization. 10638fd1498Szrj */ 10738fd1498Szrj 10838fd1498Szrj #include "config.h" 10938fd1498Szrj #include "system.h" 11038fd1498Szrj #include "coretypes.h" 11138fd1498Szrj #include "backend.h" 11238fd1498Szrj #include "rtl.h" 11338fd1498Szrj #include "tree.h" 11438fd1498Szrj #include "gimple.h" 11538fd1498Szrj #include "alloc-pool.h" 11638fd1498Szrj #include "tree-pass.h" 11738fd1498Szrj #include "cgraph.h" 11838fd1498Szrj #include "lto-streamer.h" 11938fd1498Szrj #include "fold-const.h" 12038fd1498Szrj #include "print-tree.h" 12138fd1498Szrj #include "calls.h" 12238fd1498Szrj #include "ipa-utils.h" 12338fd1498Szrj #include "gimple-fold.h" 12438fd1498Szrj #include "symbol-summary.h" 12538fd1498Szrj #include "tree-vrp.h" 12638fd1498Szrj #include "ipa-prop.h" 12738fd1498Szrj #include "ipa-fnsummary.h" 12838fd1498Szrj #include "demangle.h" 12938fd1498Szrj #include "dbgcnt.h" 13038fd1498Szrj #include "gimple-pretty-print.h" 13138fd1498Szrj #include "intl.h" 13238fd1498Szrj #include "stringpool.h" 13338fd1498Szrj #include "attribs.h" 13438fd1498Szrj 13538fd1498Szrj /* Hash based set of pairs of types. */ 13638fd1498Szrj struct type_pair 13738fd1498Szrj { 13838fd1498Szrj tree first; 13938fd1498Szrj tree second; 14038fd1498Szrj }; 14138fd1498Szrj 14238fd1498Szrj template <> 14338fd1498Szrj struct default_hash_traits <type_pair> 14438fd1498Szrj : typed_noop_remove <type_pair> 14538fd1498Szrj { 14638fd1498Szrj GTY((skip)) typedef type_pair value_type; 14738fd1498Szrj GTY((skip)) typedef type_pair compare_type; 14838fd1498Szrj static hashval_t 14938fd1498Szrj hash (type_pair p) 15038fd1498Szrj { 15138fd1498Szrj return TYPE_UID (p.first) ^ TYPE_UID (p.second); 15238fd1498Szrj } 15338fd1498Szrj static bool 15438fd1498Szrj is_empty (type_pair p) 15538fd1498Szrj { 15638fd1498Szrj return p.first == NULL; 15738fd1498Szrj } 15838fd1498Szrj static bool 15938fd1498Szrj is_deleted (type_pair p ATTRIBUTE_UNUSED) 16038fd1498Szrj { 16138fd1498Szrj return false; 16238fd1498Szrj } 16338fd1498Szrj static bool 16438fd1498Szrj equal (const type_pair &a, const type_pair &b) 16538fd1498Szrj { 16638fd1498Szrj return a.first==b.first && a.second == b.second; 16738fd1498Szrj } 16838fd1498Szrj static void 16938fd1498Szrj mark_empty (type_pair &e) 17038fd1498Szrj { 17138fd1498Szrj e.first = NULL; 17238fd1498Szrj } 17338fd1498Szrj }; 17438fd1498Szrj 17538fd1498Szrj static bool odr_types_equivalent_p (tree, tree, bool, bool *, 17638fd1498Szrj hash_set<type_pair> *, 17738fd1498Szrj location_t, location_t); 17838fd1498Szrj 17938fd1498Szrj static bool odr_violation_reported = false; 18038fd1498Szrj 18138fd1498Szrj 18238fd1498Szrj /* Pointer set of all call targets appearing in the cache. */ 18338fd1498Szrj static hash_set<cgraph_node *> *cached_polymorphic_call_targets; 18438fd1498Szrj 18538fd1498Szrj /* The node of type inheritance graph. For each type unique in 18638fd1498Szrj One Definition Rule (ODR) sense, we produce one node linking all 18738fd1498Szrj main variants of types equivalent to it, bases and derived types. */ 18838fd1498Szrj 18938fd1498Szrj struct GTY(()) odr_type_d 19038fd1498Szrj { 19138fd1498Szrj /* leader type. */ 19238fd1498Szrj tree type; 19338fd1498Szrj /* All bases; built only for main variants of types. */ 19438fd1498Szrj vec<odr_type> GTY((skip)) bases; 19538fd1498Szrj /* All derived types with virtual methods seen in unit; 19638fd1498Szrj built only for main variants of types. */ 19738fd1498Szrj vec<odr_type> GTY((skip)) derived_types; 19838fd1498Szrj 19938fd1498Szrj /* All equivalent types, if more than one. */ 20038fd1498Szrj vec<tree, va_gc> *types; 20138fd1498Szrj /* Set of all equivalent types, if NON-NULL. */ 20238fd1498Szrj hash_set<tree> * GTY((skip)) types_set; 20338fd1498Szrj 20438fd1498Szrj /* Unique ID indexing the type in odr_types array. */ 20538fd1498Szrj int id; 20638fd1498Szrj /* Is it in anonymous namespace? */ 20738fd1498Szrj bool anonymous_namespace; 20838fd1498Szrj /* Do we know about all derivations of given type? */ 20938fd1498Szrj bool all_derivations_known; 21038fd1498Szrj /* Did we report ODR violation here? */ 21138fd1498Szrj bool odr_violated; 21238fd1498Szrj /* Set when virtual table without RTTI previaled table with. */ 21338fd1498Szrj bool rtti_broken; 21438fd1498Szrj }; 21538fd1498Szrj 21638fd1498Szrj /* Return TRUE if all derived types of T are known and thus 21738fd1498Szrj we may consider the walk of derived type complete. 21838fd1498Szrj 21938fd1498Szrj This is typically true only for final anonymous namespace types and types 22038fd1498Szrj defined within functions (that may be COMDAT and thus shared across units, 22138fd1498Szrj but with the same set of derived types). */ 22238fd1498Szrj 22338fd1498Szrj bool 22438fd1498Szrj type_all_derivations_known_p (const_tree t) 22538fd1498Szrj { 22638fd1498Szrj if (TYPE_FINAL_P (t)) 22738fd1498Szrj return true; 22838fd1498Szrj if (flag_ltrans) 22938fd1498Szrj return false; 23038fd1498Szrj /* Non-C++ types may have IDENTIFIER_NODE here, do not crash. */ 23138fd1498Szrj if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL) 23238fd1498Szrj return true; 23338fd1498Szrj if (type_in_anonymous_namespace_p (t)) 23438fd1498Szrj return true; 23538fd1498Szrj return (decl_function_context (TYPE_NAME (t)) != NULL); 23638fd1498Szrj } 23738fd1498Szrj 23838fd1498Szrj /* Return TRUE if type's constructors are all visible. */ 23938fd1498Szrj 24038fd1498Szrj static bool 24138fd1498Szrj type_all_ctors_visible_p (tree t) 24238fd1498Szrj { 24338fd1498Szrj return !flag_ltrans 24438fd1498Szrj && symtab->state >= CONSTRUCTION 24538fd1498Szrj /* We can not always use type_all_derivations_known_p. 24638fd1498Szrj For function local types we must assume case where 24738fd1498Szrj the function is COMDAT and shared in between units. 24838fd1498Szrj 24938fd1498Szrj TODO: These cases are quite easy to get, but we need 25038fd1498Szrj to keep track of C++ privatizing via -Wno-weak 25138fd1498Szrj as well as the IPA privatizing. */ 25238fd1498Szrj && type_in_anonymous_namespace_p (t); 25338fd1498Szrj } 25438fd1498Szrj 25538fd1498Szrj /* Return TRUE if type may have instance. */ 25638fd1498Szrj 25738fd1498Szrj static bool 25838fd1498Szrj type_possibly_instantiated_p (tree t) 25938fd1498Szrj { 26038fd1498Szrj tree vtable; 26138fd1498Szrj varpool_node *vnode; 26238fd1498Szrj 26338fd1498Szrj /* TODO: Add abstract types here. */ 26438fd1498Szrj if (!type_all_ctors_visible_p (t)) 26538fd1498Szrj return true; 26638fd1498Szrj 26738fd1498Szrj vtable = BINFO_VTABLE (TYPE_BINFO (t)); 26838fd1498Szrj if (TREE_CODE (vtable) == POINTER_PLUS_EXPR) 26938fd1498Szrj vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0); 27038fd1498Szrj vnode = varpool_node::get (vtable); 27138fd1498Szrj return vnode && vnode->definition; 27238fd1498Szrj } 27338fd1498Szrj 27438fd1498Szrj /* Hash used to unify ODR types based on their mangled name and for anonymous 27538fd1498Szrj namespace types. */ 27638fd1498Szrj 27738fd1498Szrj struct odr_name_hasher : pointer_hash <odr_type_d> 27838fd1498Szrj { 27938fd1498Szrj typedef union tree_node *compare_type; 28038fd1498Szrj static inline hashval_t hash (const odr_type_d *); 28138fd1498Szrj static inline bool equal (const odr_type_d *, const tree_node *); 28238fd1498Szrj static inline void remove (odr_type_d *); 28338fd1498Szrj }; 28438fd1498Szrj 28538fd1498Szrj /* Has used to unify ODR types based on their associated virtual table. 28638fd1498Szrj This hash is needed to keep -fno-lto-odr-type-merging to work and contains 28738fd1498Szrj only polymorphic types. Types with mangled names are inserted to both. */ 28838fd1498Szrj 28938fd1498Szrj struct odr_vtable_hasher:odr_name_hasher 29038fd1498Szrj { 29138fd1498Szrj static inline hashval_t hash (const odr_type_d *); 29238fd1498Szrj static inline bool equal (const odr_type_d *, const tree_node *); 29338fd1498Szrj }; 29438fd1498Szrj 29538fd1498Szrj /* Return type that was declared with T's name so that T is an 29638fd1498Szrj qualified variant of it. */ 29738fd1498Szrj 29838fd1498Szrj static inline tree 29938fd1498Szrj main_odr_variant (const_tree t) 30038fd1498Szrj { 30138fd1498Szrj if (TYPE_NAME (t) && TREE_CODE (TYPE_NAME (t)) == TYPE_DECL) 30238fd1498Szrj return TREE_TYPE (TYPE_NAME (t)); 30338fd1498Szrj /* Unnamed types and non-C++ produced types can be compared by variants. */ 30438fd1498Szrj else 30538fd1498Szrj return TYPE_MAIN_VARIANT (t); 30638fd1498Szrj } 30738fd1498Szrj 30838fd1498Szrj static bool 30938fd1498Szrj can_be_name_hashed_p (tree t) 31038fd1498Szrj { 31138fd1498Szrj return (!in_lto_p || odr_type_p (t)); 31238fd1498Szrj } 31338fd1498Szrj 31438fd1498Szrj /* Hash type by its ODR name. */ 31538fd1498Szrj 31638fd1498Szrj static hashval_t 31738fd1498Szrj hash_odr_name (const_tree t) 31838fd1498Szrj { 31938fd1498Szrj gcc_checking_assert (main_odr_variant (t) == t); 32038fd1498Szrj 32138fd1498Szrj /* If not in LTO, all main variants are unique, so we can do 32238fd1498Szrj pointer hash. */ 32338fd1498Szrj if (!in_lto_p) 32438fd1498Szrj return htab_hash_pointer (t); 32538fd1498Szrj 32638fd1498Szrj /* Anonymous types are unique. */ 32738fd1498Szrj if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t)) 32838fd1498Szrj return htab_hash_pointer (t); 32938fd1498Szrj 33038fd1498Szrj gcc_checking_assert (TYPE_NAME (t) 33138fd1498Szrj && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t))); 33238fd1498Szrj return IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (TYPE_NAME (t))); 33338fd1498Szrj } 33438fd1498Szrj 33538fd1498Szrj /* Return the computed hashcode for ODR_TYPE. */ 33638fd1498Szrj 33738fd1498Szrj inline hashval_t 33838fd1498Szrj odr_name_hasher::hash (const odr_type_d *odr_type) 33938fd1498Szrj { 34038fd1498Szrj return hash_odr_name (odr_type->type); 34138fd1498Szrj } 34238fd1498Szrj 34338fd1498Szrj static bool 34438fd1498Szrj can_be_vtable_hashed_p (tree t) 34538fd1498Szrj { 34638fd1498Szrj /* vtable hashing can distinguish only main variants. */ 34738fd1498Szrj if (TYPE_MAIN_VARIANT (t) != t) 34838fd1498Szrj return false; 34938fd1498Szrj /* Anonymous namespace types are always handled by name hash. */ 35038fd1498Szrj if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t)) 35138fd1498Szrj return false; 35238fd1498Szrj return (TREE_CODE (t) == RECORD_TYPE 35338fd1498Szrj && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t))); 35438fd1498Szrj } 35538fd1498Szrj 35638fd1498Szrj /* Hash type by assembler name of its vtable. */ 35738fd1498Szrj 35838fd1498Szrj static hashval_t 35938fd1498Szrj hash_odr_vtable (const_tree t) 36038fd1498Szrj { 36138fd1498Szrj tree v = BINFO_VTABLE (TYPE_BINFO (TYPE_MAIN_VARIANT (t))); 36238fd1498Szrj inchash::hash hstate; 36338fd1498Szrj 36438fd1498Szrj gcc_checking_assert (in_lto_p); 36538fd1498Szrj gcc_checking_assert (!type_in_anonymous_namespace_p (t)); 36638fd1498Szrj gcc_checking_assert (TREE_CODE (t) == RECORD_TYPE 36738fd1498Szrj && TYPE_BINFO (t) && BINFO_VTABLE (TYPE_BINFO (t))); 36838fd1498Szrj gcc_checking_assert (main_odr_variant (t) == t); 36938fd1498Szrj 37038fd1498Szrj if (TREE_CODE (v) == POINTER_PLUS_EXPR) 37138fd1498Szrj { 37238fd1498Szrj add_expr (TREE_OPERAND (v, 1), hstate); 37338fd1498Szrj v = TREE_OPERAND (TREE_OPERAND (v, 0), 0); 37438fd1498Szrj } 37538fd1498Szrj 37638fd1498Szrj hstate.add_hwi (IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (v))); 37738fd1498Szrj return hstate.end (); 37838fd1498Szrj } 37938fd1498Szrj 38038fd1498Szrj /* Return the computed hashcode for ODR_TYPE. */ 38138fd1498Szrj 38238fd1498Szrj inline hashval_t 38338fd1498Szrj odr_vtable_hasher::hash (const odr_type_d *odr_type) 38438fd1498Szrj { 38538fd1498Szrj return hash_odr_vtable (odr_type->type); 38638fd1498Szrj } 38738fd1498Szrj 38838fd1498Szrj /* For languages with One Definition Rule, work out if 38938fd1498Szrj types are the same based on their name. 39038fd1498Szrj 39138fd1498Szrj This is non-trivial for LTO where minor differences in 39238fd1498Szrj the type representation may have prevented type merging 39338fd1498Szrj to merge two copies of otherwise equivalent type. 39438fd1498Szrj 39538fd1498Szrj Until we start streaming mangled type names, this function works 39638fd1498Szrj only for polymorphic types. 39738fd1498Szrj 39838fd1498Szrj When STRICT is true, we compare types by their names for purposes of 39938fd1498Szrj ODR violation warnings. When strict is false, we consider variants 40038fd1498Szrj equivalent, because it is all that matters for devirtualization machinery. 40138fd1498Szrj */ 40238fd1498Szrj 40338fd1498Szrj bool 40438fd1498Szrj types_same_for_odr (const_tree type1, const_tree type2, bool strict) 40538fd1498Szrj { 40638fd1498Szrj gcc_checking_assert (TYPE_P (type1) && TYPE_P (type2)); 40738fd1498Szrj 40838fd1498Szrj type1 = main_odr_variant (type1); 40938fd1498Szrj type2 = main_odr_variant (type2); 41038fd1498Szrj if (!strict) 41138fd1498Szrj { 41238fd1498Szrj type1 = TYPE_MAIN_VARIANT (type1); 41338fd1498Szrj type2 = TYPE_MAIN_VARIANT (type2); 41438fd1498Szrj } 41538fd1498Szrj 41638fd1498Szrj if (type1 == type2) 41738fd1498Szrj return true; 41838fd1498Szrj 41938fd1498Szrj if (!in_lto_p) 42038fd1498Szrj return false; 42138fd1498Szrj 42238fd1498Szrj /* Check for anonymous namespaces. Those have !TREE_PUBLIC 42338fd1498Szrj on the corresponding TYPE_STUB_DECL. */ 42438fd1498Szrj if ((type_with_linkage_p (type1) && type_in_anonymous_namespace_p (type1)) 42538fd1498Szrj || (type_with_linkage_p (type2) && type_in_anonymous_namespace_p (type2))) 42638fd1498Szrj return false; 42738fd1498Szrj 42838fd1498Szrj 42938fd1498Szrj /* ODR name of the type is set in DECL_ASSEMBLER_NAME of its TYPE_NAME. 43038fd1498Szrj 43138fd1498Szrj Ideally we should never need types without ODR names here. It can however 43238fd1498Szrj happen in two cases: 43338fd1498Szrj 43438fd1498Szrj 1) for builtin types that are not streamed but rebuilt in lto/lto-lang.c 43538fd1498Szrj Here testing for equivalence is safe, since their MAIN_VARIANTs are 43638fd1498Szrj unique. 43738fd1498Szrj 2) for units streamed with -fno-lto-odr-type-merging. Here we can't 43838fd1498Szrj establish precise ODR equivalency, but for correctness we care only 43938fd1498Szrj about equivalency on complete polymorphic types. For these we can 44038fd1498Szrj compare assembler names of their virtual tables. */ 44138fd1498Szrj if ((!TYPE_NAME (type1) || !DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (type1))) 44238fd1498Szrj || (!TYPE_NAME (type2) || !DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (type2)))) 44338fd1498Szrj { 44438fd1498Szrj /* See if types are obviously different (i.e. different codes 44538fd1498Szrj or polymorphic wrt non-polymorphic). This is not strictly correct 44638fd1498Szrj for ODR violating programs, but we can't do better without streaming 44738fd1498Szrj ODR names. */ 44838fd1498Szrj if (TREE_CODE (type1) != TREE_CODE (type2)) 44938fd1498Szrj return false; 45038fd1498Szrj if (TREE_CODE (type1) == RECORD_TYPE 45138fd1498Szrj && (TYPE_BINFO (type1) == NULL_TREE) 45238fd1498Szrj != (TYPE_BINFO (type2) == NULL_TREE)) 45338fd1498Szrj return false; 45438fd1498Szrj if (TREE_CODE (type1) == RECORD_TYPE && TYPE_BINFO (type1) 45538fd1498Szrj && (BINFO_VTABLE (TYPE_BINFO (type1)) == NULL_TREE) 45638fd1498Szrj != (BINFO_VTABLE (TYPE_BINFO (type2)) == NULL_TREE)) 45738fd1498Szrj return false; 45838fd1498Szrj 45938fd1498Szrj /* At the moment we have no way to establish ODR equivalence at LTO 46038fd1498Szrj other than comparing virtual table pointers of polymorphic types. 46138fd1498Szrj Eventually we should start saving mangled names in TYPE_NAME. 46238fd1498Szrj Then this condition will become non-trivial. */ 46338fd1498Szrj 46438fd1498Szrj if (TREE_CODE (type1) == RECORD_TYPE 46538fd1498Szrj && TYPE_BINFO (type1) && TYPE_BINFO (type2) 46638fd1498Szrj && BINFO_VTABLE (TYPE_BINFO (type1)) 46738fd1498Szrj && BINFO_VTABLE (TYPE_BINFO (type2))) 46838fd1498Szrj { 46938fd1498Szrj tree v1 = BINFO_VTABLE (TYPE_BINFO (type1)); 47038fd1498Szrj tree v2 = BINFO_VTABLE (TYPE_BINFO (type2)); 47138fd1498Szrj gcc_assert (TREE_CODE (v1) == POINTER_PLUS_EXPR 47238fd1498Szrj && TREE_CODE (v2) == POINTER_PLUS_EXPR); 47338fd1498Szrj return (operand_equal_p (TREE_OPERAND (v1, 1), 47438fd1498Szrj TREE_OPERAND (v2, 1), 0) 47538fd1498Szrj && DECL_ASSEMBLER_NAME 47638fd1498Szrj (TREE_OPERAND (TREE_OPERAND (v1, 0), 0)) 47738fd1498Szrj == DECL_ASSEMBLER_NAME 47838fd1498Szrj (TREE_OPERAND (TREE_OPERAND (v2, 0), 0))); 47938fd1498Szrj } 48038fd1498Szrj gcc_unreachable (); 48138fd1498Szrj } 48238fd1498Szrj return (DECL_ASSEMBLER_NAME (TYPE_NAME (type1)) 48338fd1498Szrj == DECL_ASSEMBLER_NAME (TYPE_NAME (type2))); 48438fd1498Szrj } 48538fd1498Szrj 48638fd1498Szrj /* Return true if we can decide on ODR equivalency. 48738fd1498Szrj 48838fd1498Szrj In non-LTO it is always decide, in LTO however it depends in the type has 48938fd1498Szrj ODR info attached. 49038fd1498Szrj 49138fd1498Szrj When STRICT is false, compare main variants. */ 49238fd1498Szrj 49338fd1498Szrj bool 49438fd1498Szrj types_odr_comparable (tree t1, tree t2, bool strict) 49538fd1498Szrj { 49638fd1498Szrj return (!in_lto_p 49738fd1498Szrj || (strict ? (main_odr_variant (t1) == main_odr_variant (t2) 49838fd1498Szrj && main_odr_variant (t1)) 49938fd1498Szrj : TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) 50038fd1498Szrj || (odr_type_p (t1) && odr_type_p (t2)) 50138fd1498Szrj || (TREE_CODE (t1) == RECORD_TYPE && TREE_CODE (t2) == RECORD_TYPE 50238fd1498Szrj && TYPE_BINFO (t1) && TYPE_BINFO (t2) 50338fd1498Szrj && polymorphic_type_binfo_p (TYPE_BINFO (t1)) 50438fd1498Szrj && polymorphic_type_binfo_p (TYPE_BINFO (t2)))); 50538fd1498Szrj } 50638fd1498Szrj 50738fd1498Szrj /* Return true if T1 and T2 are ODR equivalent. If ODR equivalency is not 50838fd1498Szrj known, be conservative and return false. */ 50938fd1498Szrj 51038fd1498Szrj bool 51138fd1498Szrj types_must_be_same_for_odr (tree t1, tree t2) 51238fd1498Szrj { 51338fd1498Szrj if (types_odr_comparable (t1, t2)) 51438fd1498Szrj return types_same_for_odr (t1, t2); 51538fd1498Szrj else 51638fd1498Szrj return TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2); 51738fd1498Szrj } 51838fd1498Szrj 51938fd1498Szrj /* If T is compound type, return type it is based on. */ 52038fd1498Szrj 52138fd1498Szrj static tree 52238fd1498Szrj compound_type_base (const_tree t) 52338fd1498Szrj { 52438fd1498Szrj if (TREE_CODE (t) == ARRAY_TYPE 52538fd1498Szrj || POINTER_TYPE_P (t) 52638fd1498Szrj || TREE_CODE (t) == COMPLEX_TYPE 52738fd1498Szrj || VECTOR_TYPE_P (t)) 52838fd1498Szrj return TREE_TYPE (t); 52938fd1498Szrj if (TREE_CODE (t) == METHOD_TYPE) 53038fd1498Szrj return TYPE_METHOD_BASETYPE (t); 53138fd1498Szrj if (TREE_CODE (t) == OFFSET_TYPE) 53238fd1498Szrj return TYPE_OFFSET_BASETYPE (t); 53338fd1498Szrj return NULL_TREE; 53438fd1498Szrj } 53538fd1498Szrj 53638fd1498Szrj /* Return true if T is either ODR type or compound type based from it. 53738fd1498Szrj If the function return true, we know that T is a type originating from C++ 53838fd1498Szrj source even at link-time. */ 53938fd1498Szrj 54038fd1498Szrj bool 54138fd1498Szrj odr_or_derived_type_p (const_tree t) 54238fd1498Szrj { 54338fd1498Szrj do 54438fd1498Szrj { 54538fd1498Szrj if (odr_type_p (t)) 54638fd1498Szrj return true; 54738fd1498Szrj /* Function type is a tricky one. Basically we can consider it 54838fd1498Szrj ODR derived if return type or any of the parameters is. 54938fd1498Szrj We need to check all parameters because LTO streaming merges 55038fd1498Szrj common types (such as void) and they are not considered ODR then. */ 55138fd1498Szrj if (TREE_CODE (t) == FUNCTION_TYPE) 55238fd1498Szrj { 55338fd1498Szrj if (TYPE_METHOD_BASETYPE (t)) 55438fd1498Szrj t = TYPE_METHOD_BASETYPE (t); 55538fd1498Szrj else 55638fd1498Szrj { 55738fd1498Szrj if (TREE_TYPE (t) && odr_or_derived_type_p (TREE_TYPE (t))) 55838fd1498Szrj return true; 55938fd1498Szrj for (t = TYPE_ARG_TYPES (t); t; t = TREE_CHAIN (t)) 56038fd1498Szrj if (odr_or_derived_type_p (TREE_VALUE (t))) 56138fd1498Szrj return true; 56238fd1498Szrj return false; 56338fd1498Szrj } 56438fd1498Szrj } 56538fd1498Szrj else 56638fd1498Szrj t = compound_type_base (t); 56738fd1498Szrj } 56838fd1498Szrj while (t); 56938fd1498Szrj return t; 57038fd1498Szrj } 57138fd1498Szrj 57238fd1498Szrj /* Compare types T1 and T2 and return true if they are 57338fd1498Szrj equivalent. */ 57438fd1498Szrj 57538fd1498Szrj inline bool 57638fd1498Szrj odr_name_hasher::equal (const odr_type_d *o1, const tree_node *t2) 57738fd1498Szrj { 57838fd1498Szrj tree t1 = o1->type; 57938fd1498Szrj 58038fd1498Szrj gcc_checking_assert (main_odr_variant (t2) == t2); 58138fd1498Szrj gcc_checking_assert (main_odr_variant (t1) == t1); 58238fd1498Szrj if (t1 == t2) 58338fd1498Szrj return true; 58438fd1498Szrj if (!in_lto_p) 58538fd1498Szrj return false; 58638fd1498Szrj /* Check for anonymous namespaces. Those have !TREE_PUBLIC 58738fd1498Szrj on the corresponding TYPE_STUB_DECL. */ 58838fd1498Szrj if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1)) 58938fd1498Szrj || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2))) 59038fd1498Szrj return false; 59138fd1498Szrj gcc_checking_assert (DECL_ASSEMBLER_NAME (TYPE_NAME (t1))); 59238fd1498Szrj gcc_checking_assert (DECL_ASSEMBLER_NAME (TYPE_NAME (t2))); 59338fd1498Szrj return (DECL_ASSEMBLER_NAME (TYPE_NAME (t1)) 59438fd1498Szrj == DECL_ASSEMBLER_NAME (TYPE_NAME (t2))); 59538fd1498Szrj } 59638fd1498Szrj 59738fd1498Szrj /* Compare types T1 and T2 and return true if they are 59838fd1498Szrj equivalent. */ 59938fd1498Szrj 60038fd1498Szrj inline bool 60138fd1498Szrj odr_vtable_hasher::equal (const odr_type_d *o1, const tree_node *t2) 60238fd1498Szrj { 60338fd1498Szrj tree t1 = o1->type; 60438fd1498Szrj 60538fd1498Szrj gcc_checking_assert (main_odr_variant (t2) == t2); 60638fd1498Szrj gcc_checking_assert (main_odr_variant (t1) == t1); 60738fd1498Szrj gcc_checking_assert (in_lto_p); 60838fd1498Szrj t1 = TYPE_MAIN_VARIANT (t1); 60938fd1498Szrj t2 = TYPE_MAIN_VARIANT (t2); 61038fd1498Szrj if (t1 == t2) 61138fd1498Szrj return true; 61238fd1498Szrj tree v1 = BINFO_VTABLE (TYPE_BINFO (t1)); 61338fd1498Szrj tree v2 = BINFO_VTABLE (TYPE_BINFO (t2)); 61438fd1498Szrj return (operand_equal_p (TREE_OPERAND (v1, 1), 61538fd1498Szrj TREE_OPERAND (v2, 1), 0) 61638fd1498Szrj && DECL_ASSEMBLER_NAME 61738fd1498Szrj (TREE_OPERAND (TREE_OPERAND (v1, 0), 0)) 61838fd1498Szrj == DECL_ASSEMBLER_NAME 61938fd1498Szrj (TREE_OPERAND (TREE_OPERAND (v2, 0), 0))); 62038fd1498Szrj } 62138fd1498Szrj 62238fd1498Szrj /* Free ODR type V. */ 62338fd1498Szrj 62438fd1498Szrj inline void 62538fd1498Szrj odr_name_hasher::remove (odr_type_d *v) 62638fd1498Szrj { 62738fd1498Szrj v->bases.release (); 62838fd1498Szrj v->derived_types.release (); 62938fd1498Szrj if (v->types_set) 63038fd1498Szrj delete v->types_set; 63138fd1498Szrj ggc_free (v); 63238fd1498Szrj } 63338fd1498Szrj 63438fd1498Szrj /* ODR type hash used to look up ODR type based on tree type node. */ 63538fd1498Szrj 63638fd1498Szrj typedef hash_table<odr_name_hasher> odr_hash_type; 63738fd1498Szrj static odr_hash_type *odr_hash; 63838fd1498Szrj typedef hash_table<odr_vtable_hasher> odr_vtable_hash_type; 63938fd1498Szrj static odr_vtable_hash_type *odr_vtable_hash; 64038fd1498Szrj 64138fd1498Szrj /* ODR types are also stored into ODR_TYPE vector to allow consistent 64238fd1498Szrj walking. Bases appear before derived types. Vector is garbage collected 64338fd1498Szrj so we won't end up visiting empty types. */ 64438fd1498Szrj 64538fd1498Szrj static GTY(()) vec <odr_type, va_gc> *odr_types_ptr; 64638fd1498Szrj #define odr_types (*odr_types_ptr) 64738fd1498Szrj 64838fd1498Szrj /* Set TYPE_BINFO of TYPE and its variants to BINFO. */ 64938fd1498Szrj void 65038fd1498Szrj set_type_binfo (tree type, tree binfo) 65138fd1498Szrj { 65238fd1498Szrj for (; type; type = TYPE_NEXT_VARIANT (type)) 65338fd1498Szrj if (COMPLETE_TYPE_P (type)) 65438fd1498Szrj TYPE_BINFO (type) = binfo; 65538fd1498Szrj else 65638fd1498Szrj gcc_assert (!TYPE_BINFO (type)); 65738fd1498Szrj } 65838fd1498Szrj 65938fd1498Szrj /* Compare T1 and T2 based on name or structure. */ 66038fd1498Szrj 66138fd1498Szrj static bool 66238fd1498Szrj odr_subtypes_equivalent_p (tree t1, tree t2, 66338fd1498Szrj hash_set<type_pair> *visited, 66438fd1498Szrj location_t loc1, location_t loc2) 66538fd1498Szrj { 66638fd1498Szrj 66738fd1498Szrj /* This can happen in incomplete types that should be handled earlier. */ 66838fd1498Szrj gcc_assert (t1 && t2); 66938fd1498Szrj 67038fd1498Szrj t1 = main_odr_variant (t1); 67138fd1498Szrj t2 = main_odr_variant (t2); 67238fd1498Szrj if (t1 == t2) 67338fd1498Szrj return true; 67438fd1498Szrj 67538fd1498Szrj /* Anonymous namespace types must match exactly. */ 67638fd1498Szrj if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1)) 67738fd1498Szrj || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2))) 67838fd1498Szrj return false; 67938fd1498Szrj 68038fd1498Szrj /* For ODR types be sure to compare their names. 68138fd1498Szrj To support -Wno-odr-type-merging we allow one type to be non-ODR 68238fd1498Szrj and other ODR even though it is a violation. */ 68338fd1498Szrj if (types_odr_comparable (t1, t2, true)) 68438fd1498Szrj { 68538fd1498Szrj if (!types_same_for_odr (t1, t2, true)) 68638fd1498Szrj return false; 68738fd1498Szrj /* Limit recursion: If subtypes are ODR types and we know 68838fd1498Szrj that they are same, be happy. */ 68938fd1498Szrj if (!odr_type_p (t1) || !get_odr_type (t1, true)->odr_violated) 69038fd1498Szrj return true; 69138fd1498Szrj } 69238fd1498Szrj 69338fd1498Szrj /* Component types, builtins and possibly violating ODR types 69438fd1498Szrj have to be compared structurally. */ 69538fd1498Szrj if (TREE_CODE (t1) != TREE_CODE (t2)) 69638fd1498Szrj return false; 69738fd1498Szrj if (AGGREGATE_TYPE_P (t1) 69838fd1498Szrj && (TYPE_NAME (t1) == NULL_TREE) != (TYPE_NAME (t2) == NULL_TREE)) 69938fd1498Szrj return false; 70038fd1498Szrj 70138fd1498Szrj type_pair pair={t1,t2}; 70238fd1498Szrj if (TYPE_UID (t1) > TYPE_UID (t2)) 70338fd1498Szrj { 70438fd1498Szrj pair.first = t2; 70538fd1498Szrj pair.second = t1; 70638fd1498Szrj } 70738fd1498Szrj if (visited->add (pair)) 70838fd1498Szrj return true; 70938fd1498Szrj return odr_types_equivalent_p (t1, t2, false, NULL, visited, loc1, loc2); 71038fd1498Szrj } 71138fd1498Szrj 71238fd1498Szrj /* Return true if DECL1 and DECL2 are identical methods. Consider 71338fd1498Szrj name equivalent to name.localalias.xyz. */ 71438fd1498Szrj 71538fd1498Szrj static bool 71638fd1498Szrj methods_equal_p (tree decl1, tree decl2) 71738fd1498Szrj { 71838fd1498Szrj if (DECL_ASSEMBLER_NAME (decl1) == DECL_ASSEMBLER_NAME (decl2)) 71938fd1498Szrj return true; 72038fd1498Szrj const char sep = symbol_table::symbol_suffix_separator (); 72138fd1498Szrj 72238fd1498Szrj const char *name1 = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl1)); 72338fd1498Szrj const char *ptr1 = strchr (name1, sep); 72438fd1498Szrj int len1 = ptr1 ? ptr1 - name1 : strlen (name1); 72538fd1498Szrj 72638fd1498Szrj const char *name2 = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl2)); 72738fd1498Szrj const char *ptr2 = strchr (name2, sep); 72838fd1498Szrj int len2 = ptr2 ? ptr2 - name2 : strlen (name2); 72938fd1498Szrj 73038fd1498Szrj if (len1 != len2) 73138fd1498Szrj return false; 73238fd1498Szrj return !strncmp (name1, name2, len1); 73338fd1498Szrj } 73438fd1498Szrj 73538fd1498Szrj /* Compare two virtual tables, PREVAILING and VTABLE and output ODR 73638fd1498Szrj violation warnings. */ 73738fd1498Szrj 73838fd1498Szrj void 73938fd1498Szrj compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable) 74038fd1498Szrj { 74138fd1498Szrj int n1, n2; 74238fd1498Szrj 74338fd1498Szrj if (DECL_VIRTUAL_P (prevailing->decl) != DECL_VIRTUAL_P (vtable->decl)) 74438fd1498Szrj { 74538fd1498Szrj odr_violation_reported = true; 74638fd1498Szrj if (DECL_VIRTUAL_P (prevailing->decl)) 74738fd1498Szrj { 74838fd1498Szrj varpool_node *tmp = prevailing; 74938fd1498Szrj prevailing = vtable; 75038fd1498Szrj vtable = tmp; 75138fd1498Szrj } 75238fd1498Szrj if (warning_at (DECL_SOURCE_LOCATION 75338fd1498Szrj (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 75438fd1498Szrj OPT_Wodr, 75538fd1498Szrj "virtual table of type %qD violates one definition rule", 75638fd1498Szrj DECL_CONTEXT (vtable->decl))) 75738fd1498Szrj inform (DECL_SOURCE_LOCATION (prevailing->decl), 75838fd1498Szrj "variable of same assembler name as the virtual table is " 75938fd1498Szrj "defined in another translation unit"); 76038fd1498Szrj return; 76138fd1498Szrj } 76238fd1498Szrj if (!prevailing->definition || !vtable->definition) 76338fd1498Szrj return; 76438fd1498Szrj 76538fd1498Szrj /* If we do not stream ODR type info, do not bother to do useful compare. */ 76638fd1498Szrj if (!TYPE_BINFO (DECL_CONTEXT (vtable->decl)) 76738fd1498Szrj || !polymorphic_type_binfo_p (TYPE_BINFO (DECL_CONTEXT (vtable->decl)))) 76838fd1498Szrj return; 76938fd1498Szrj 77038fd1498Szrj odr_type class_type = get_odr_type (DECL_CONTEXT (vtable->decl), true); 77138fd1498Szrj 77238fd1498Szrj if (class_type->odr_violated) 77338fd1498Szrj return; 77438fd1498Szrj 77538fd1498Szrj for (n1 = 0, n2 = 0; true; n1++, n2++) 77638fd1498Szrj { 77738fd1498Szrj struct ipa_ref *ref1, *ref2; 77838fd1498Szrj bool end1, end2; 77938fd1498Szrj 78038fd1498Szrj end1 = !prevailing->iterate_reference (n1, ref1); 78138fd1498Szrj end2 = !vtable->iterate_reference (n2, ref2); 78238fd1498Szrj 78338fd1498Szrj /* !DECL_VIRTUAL_P means RTTI entry; 78438fd1498Szrj We warn when RTTI is lost because non-RTTI previals; we silently 78538fd1498Szrj accept the other case. */ 78638fd1498Szrj while (!end2 78738fd1498Szrj && (end1 78838fd1498Szrj || (methods_equal_p (ref1->referred->decl, 78938fd1498Szrj ref2->referred->decl) 79038fd1498Szrj && TREE_CODE (ref1->referred->decl) == FUNCTION_DECL)) 79138fd1498Szrj && TREE_CODE (ref2->referred->decl) != FUNCTION_DECL) 79238fd1498Szrj { 79338fd1498Szrj if (!class_type->rtti_broken 79438fd1498Szrj && warning_at (DECL_SOURCE_LOCATION 79538fd1498Szrj (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 79638fd1498Szrj OPT_Wodr, 79738fd1498Szrj "virtual table of type %qD contains RTTI " 79838fd1498Szrj "information", 79938fd1498Szrj DECL_CONTEXT (vtable->decl))) 80038fd1498Szrj { 80138fd1498Szrj inform (DECL_SOURCE_LOCATION 80238fd1498Szrj (TYPE_NAME (DECL_CONTEXT (prevailing->decl))), 80338fd1498Szrj "but is prevailed by one without from other translation " 80438fd1498Szrj "unit"); 80538fd1498Szrj inform (DECL_SOURCE_LOCATION 80638fd1498Szrj (TYPE_NAME (DECL_CONTEXT (prevailing->decl))), 80738fd1498Szrj "RTTI will not work on this type"); 80838fd1498Szrj class_type->rtti_broken = true; 80938fd1498Szrj } 81038fd1498Szrj n2++; 81138fd1498Szrj end2 = !vtable->iterate_reference (n2, ref2); 81238fd1498Szrj } 81338fd1498Szrj while (!end1 81438fd1498Szrj && (end2 81538fd1498Szrj || (methods_equal_p (ref2->referred->decl, ref1->referred->decl) 81638fd1498Szrj && TREE_CODE (ref2->referred->decl) == FUNCTION_DECL)) 81738fd1498Szrj && TREE_CODE (ref1->referred->decl) != FUNCTION_DECL) 81838fd1498Szrj { 81938fd1498Szrj n1++; 82038fd1498Szrj end1 = !prevailing->iterate_reference (n1, ref1); 82138fd1498Szrj } 82238fd1498Szrj 82338fd1498Szrj /* Finished? */ 82438fd1498Szrj if (end1 && end2) 82538fd1498Szrj { 82638fd1498Szrj /* Extra paranoia; compare the sizes. We do not have information 82738fd1498Szrj about virtual inheritance offsets, so just be sure that these 82838fd1498Szrj match. 82938fd1498Szrj Do this as very last check so the not very informative error 83038fd1498Szrj is not output too often. */ 83138fd1498Szrj if (DECL_SIZE (prevailing->decl) != DECL_SIZE (vtable->decl)) 83238fd1498Szrj { 83338fd1498Szrj class_type->odr_violated = true; 83438fd1498Szrj if (warning_at (DECL_SOURCE_LOCATION 83538fd1498Szrj (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 83638fd1498Szrj OPT_Wodr, 83738fd1498Szrj "virtual table of type %qD violates " 83838fd1498Szrj "one definition rule ", 83938fd1498Szrj DECL_CONTEXT (vtable->decl))) 84038fd1498Szrj { 84138fd1498Szrj inform (DECL_SOURCE_LOCATION 84238fd1498Szrj (TYPE_NAME (DECL_CONTEXT (prevailing->decl))), 84338fd1498Szrj "the conflicting type defined in another translation " 84438fd1498Szrj "unit has virtual table of different size"); 84538fd1498Szrj } 84638fd1498Szrj } 84738fd1498Szrj return; 84838fd1498Szrj } 84938fd1498Szrj 85038fd1498Szrj if (!end1 && !end2) 85138fd1498Szrj { 85238fd1498Szrj if (methods_equal_p (ref1->referred->decl, ref2->referred->decl)) 85338fd1498Szrj continue; 85438fd1498Szrj 85538fd1498Szrj class_type->odr_violated = true; 85638fd1498Szrj 85738fd1498Szrj /* If the loops above stopped on non-virtual pointer, we have 85838fd1498Szrj mismatch in RTTI information mangling. */ 85938fd1498Szrj if (TREE_CODE (ref1->referred->decl) != FUNCTION_DECL 86038fd1498Szrj && TREE_CODE (ref2->referred->decl) != FUNCTION_DECL) 86138fd1498Szrj { 86238fd1498Szrj if (warning_at (DECL_SOURCE_LOCATION 86338fd1498Szrj (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 86438fd1498Szrj OPT_Wodr, 86538fd1498Szrj "virtual table of type %qD violates " 86638fd1498Szrj "one definition rule ", 86738fd1498Szrj DECL_CONTEXT (vtable->decl))) 86838fd1498Szrj { 86938fd1498Szrj inform (DECL_SOURCE_LOCATION 87038fd1498Szrj (TYPE_NAME (DECL_CONTEXT (prevailing->decl))), 87138fd1498Szrj "the conflicting type defined in another translation " 87238fd1498Szrj "unit with different RTTI information"); 87338fd1498Szrj } 87438fd1498Szrj return; 87538fd1498Szrj } 87638fd1498Szrj /* At this point both REF1 and REF2 points either to virtual table 87738fd1498Szrj or virtual method. If one points to virtual table and other to 87838fd1498Szrj method we can complain the same way as if one table was shorter 87938fd1498Szrj than other pointing out the extra method. */ 88038fd1498Szrj if (TREE_CODE (ref1->referred->decl) 88138fd1498Szrj != TREE_CODE (ref2->referred->decl)) 88238fd1498Szrj { 88338fd1498Szrj if (VAR_P (ref1->referred->decl)) 88438fd1498Szrj end1 = true; 88538fd1498Szrj else if (VAR_P (ref2->referred->decl)) 88638fd1498Szrj end2 = true; 88738fd1498Szrj } 88838fd1498Szrj } 88938fd1498Szrj 89038fd1498Szrj class_type->odr_violated = true; 89138fd1498Szrj 89238fd1498Szrj /* Complain about size mismatch. Either we have too many virutal 89338fd1498Szrj functions or too many virtual table pointers. */ 89438fd1498Szrj if (end1 || end2) 89538fd1498Szrj { 89638fd1498Szrj if (end1) 89738fd1498Szrj { 89838fd1498Szrj varpool_node *tmp = prevailing; 89938fd1498Szrj prevailing = vtable; 90038fd1498Szrj vtable = tmp; 90138fd1498Szrj ref1 = ref2; 90238fd1498Szrj } 90338fd1498Szrj if (warning_at (DECL_SOURCE_LOCATION 90438fd1498Szrj (TYPE_NAME (DECL_CONTEXT (vtable->decl))), 90538fd1498Szrj OPT_Wodr, 90638fd1498Szrj "virtual table of type %qD violates " 90738fd1498Szrj "one definition rule", 90838fd1498Szrj DECL_CONTEXT (vtable->decl))) 90938fd1498Szrj { 91038fd1498Szrj if (TREE_CODE (ref1->referring->decl) == FUNCTION_DECL) 91138fd1498Szrj { 91238fd1498Szrj inform (DECL_SOURCE_LOCATION 91338fd1498Szrj (TYPE_NAME (DECL_CONTEXT (prevailing->decl))), 91438fd1498Szrj "the conflicting type defined in another translation " 91538fd1498Szrj "unit"); 91638fd1498Szrj inform (DECL_SOURCE_LOCATION 91738fd1498Szrj (TYPE_NAME (DECL_CONTEXT (ref1->referring->decl))), 91838fd1498Szrj "contains additional virtual method %qD", 91938fd1498Szrj ref1->referred->decl); 92038fd1498Szrj } 92138fd1498Szrj else 92238fd1498Szrj { 92338fd1498Szrj inform (DECL_SOURCE_LOCATION 92438fd1498Szrj (TYPE_NAME (DECL_CONTEXT (prevailing->decl))), 92538fd1498Szrj "the conflicting type defined in another translation " 92638fd1498Szrj "unit has virtual table with more entries"); 92738fd1498Szrj } 92838fd1498Szrj } 92938fd1498Szrj return; 93038fd1498Szrj } 93138fd1498Szrj 93238fd1498Szrj /* And in the last case we have either mistmatch in between two virtual 93338fd1498Szrj methods or two virtual table pointers. */ 93438fd1498Szrj if (warning_at (DECL_SOURCE_LOCATION 93538fd1498Szrj (TYPE_NAME (DECL_CONTEXT (vtable->decl))), OPT_Wodr, 93638fd1498Szrj "virtual table of type %qD violates " 93738fd1498Szrj "one definition rule ", 93838fd1498Szrj DECL_CONTEXT (vtable->decl))) 93938fd1498Szrj { 94038fd1498Szrj if (TREE_CODE (ref1->referred->decl) == FUNCTION_DECL) 94138fd1498Szrj { 94238fd1498Szrj inform (DECL_SOURCE_LOCATION 94338fd1498Szrj (TYPE_NAME (DECL_CONTEXT (prevailing->decl))), 94438fd1498Szrj "the conflicting type defined in another translation " 94538fd1498Szrj "unit"); 94638fd1498Szrj gcc_assert (TREE_CODE (ref2->referred->decl) 94738fd1498Szrj == FUNCTION_DECL); 94838fd1498Szrj inform (DECL_SOURCE_LOCATION 94938fd1498Szrj (ref1->referred->ultimate_alias_target ()->decl), 95038fd1498Szrj "virtual method %qD", 95138fd1498Szrj ref1->referred->ultimate_alias_target ()->decl); 95238fd1498Szrj inform (DECL_SOURCE_LOCATION 95338fd1498Szrj (ref2->referred->ultimate_alias_target ()->decl), 95438fd1498Szrj "ought to match virtual method %qD but does not", 95538fd1498Szrj ref2->referred->ultimate_alias_target ()->decl); 95638fd1498Szrj } 95738fd1498Szrj else 95838fd1498Szrj inform (DECL_SOURCE_LOCATION 95938fd1498Szrj (TYPE_NAME (DECL_CONTEXT (prevailing->decl))), 96038fd1498Szrj "the conflicting type defined in another translation " 96138fd1498Szrj "unit has virtual table with different contents"); 96238fd1498Szrj return; 96338fd1498Szrj } 96438fd1498Szrj } 96538fd1498Szrj } 96638fd1498Szrj 96738fd1498Szrj /* Output ODR violation warning about T1 and T2 with REASON. 96838fd1498Szrj Display location of ST1 and ST2 if REASON speaks about field or 96938fd1498Szrj method of the type. 97038fd1498Szrj If WARN is false, do nothing. Set WARNED if warning was indeed 97138fd1498Szrj output. */ 97238fd1498Szrj 97338fd1498Szrj void 97438fd1498Szrj warn_odr (tree t1, tree t2, tree st1, tree st2, 97538fd1498Szrj bool warn, bool *warned, const char *reason) 97638fd1498Szrj { 97738fd1498Szrj tree decl2 = TYPE_NAME (t2); 97838fd1498Szrj if (warned) 97938fd1498Szrj *warned = false; 98038fd1498Szrj 98138fd1498Szrj if (!warn || !TYPE_NAME(t1)) 98238fd1498Szrj return; 98338fd1498Szrj 98438fd1498Szrj /* ODR warnings are output druing LTO streaming; we must apply location 98538fd1498Szrj cache for potential warnings to be output correctly. */ 98638fd1498Szrj if (lto_location_cache::current_cache) 98738fd1498Szrj lto_location_cache::current_cache->apply_location_cache (); 98838fd1498Szrj 98938fd1498Szrj if (!warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (t1)), OPT_Wodr, 99038fd1498Szrj "type %qT violates the C++ One Definition Rule", 99138fd1498Szrj t1)) 99238fd1498Szrj return; 99338fd1498Szrj if (!st1 && !st2) 99438fd1498Szrj ; 99538fd1498Szrj /* For FIELD_DECL support also case where one of fields is 99638fd1498Szrj NULL - this is used when the structures have mismatching number of 99738fd1498Szrj elements. */ 99838fd1498Szrj else if (!st1 || TREE_CODE (st1) == FIELD_DECL) 99938fd1498Szrj { 100038fd1498Szrj inform (DECL_SOURCE_LOCATION (decl2), 100138fd1498Szrj "a different type is defined in another translation unit"); 100238fd1498Szrj if (!st1) 100338fd1498Szrj { 100438fd1498Szrj st1 = st2; 100538fd1498Szrj st2 = NULL; 100638fd1498Szrj } 100738fd1498Szrj inform (DECL_SOURCE_LOCATION (st1), 100838fd1498Szrj "the first difference of corresponding definitions is field %qD", 100938fd1498Szrj st1); 101038fd1498Szrj if (st2) 101138fd1498Szrj decl2 = st2; 101238fd1498Szrj } 101338fd1498Szrj else if (TREE_CODE (st1) == FUNCTION_DECL) 101438fd1498Szrj { 101538fd1498Szrj inform (DECL_SOURCE_LOCATION (decl2), 101638fd1498Szrj "a different type is defined in another translation unit"); 101738fd1498Szrj inform (DECL_SOURCE_LOCATION (st1), 101838fd1498Szrj "the first difference of corresponding definitions is method %qD", 101938fd1498Szrj st1); 102038fd1498Szrj decl2 = st2; 102138fd1498Szrj } 102238fd1498Szrj else 102338fd1498Szrj return; 102438fd1498Szrj inform (DECL_SOURCE_LOCATION (decl2), reason); 102538fd1498Szrj 102638fd1498Szrj if (warned) 102738fd1498Szrj *warned = true; 102838fd1498Szrj } 102938fd1498Szrj 103038fd1498Szrj /* Return ture if T1 and T2 are incompatible and we want to recusively 103138fd1498Szrj dive into them from warn_type_mismatch to give sensible answer. */ 103238fd1498Szrj 103338fd1498Szrj static bool 103438fd1498Szrj type_mismatch_p (tree t1, tree t2) 103538fd1498Szrj { 103638fd1498Szrj if (odr_or_derived_type_p (t1) && odr_or_derived_type_p (t2) 103738fd1498Szrj && !odr_types_equivalent_p (t1, t2)) 103838fd1498Szrj return true; 103938fd1498Szrj return !types_compatible_p (t1, t2); 104038fd1498Szrj } 104138fd1498Szrj 104238fd1498Szrj 104338fd1498Szrj /* Types T1 and T2 was found to be incompatible in a context they can't 104438fd1498Szrj (either used to declare a symbol of same assembler name or unified by 104538fd1498Szrj ODR rule). We already output warning about this, but if possible, output 104638fd1498Szrj extra information on how the types mismatch. 104738fd1498Szrj 104838fd1498Szrj This is hard to do in general. We basically handle the common cases. 104938fd1498Szrj 105038fd1498Szrj If LOC1 and LOC2 are meaningful locations, use it in the case the types 105138fd1498Szrj themselves do no thave one.*/ 105238fd1498Szrj 105338fd1498Szrj void 105438fd1498Szrj warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2) 105538fd1498Szrj { 105638fd1498Szrj /* Location of type is known only if it has TYPE_NAME and the name is 105738fd1498Szrj TYPE_DECL. */ 105838fd1498Szrj location_t loc_t1 = TYPE_NAME (t1) && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL 105938fd1498Szrj ? DECL_SOURCE_LOCATION (TYPE_NAME (t1)) 106038fd1498Szrj : UNKNOWN_LOCATION; 106138fd1498Szrj location_t loc_t2 = TYPE_NAME (t2) && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL 106238fd1498Szrj ? DECL_SOURCE_LOCATION (TYPE_NAME (t2)) 106338fd1498Szrj : UNKNOWN_LOCATION; 106438fd1498Szrj bool loc_t2_useful = false; 106538fd1498Szrj 106638fd1498Szrj /* With LTO it is a common case that the location of both types match. 106738fd1498Szrj See if T2 has a location that is different from T1. If so, we will 106838fd1498Szrj inform user about the location. 106938fd1498Szrj Do not consider the location passed to us in LOC1/LOC2 as those are 107038fd1498Szrj already output. */ 107138fd1498Szrj if (loc_t2 > BUILTINS_LOCATION && loc_t2 != loc_t1) 107238fd1498Szrj { 107338fd1498Szrj if (loc_t1 <= BUILTINS_LOCATION) 107438fd1498Szrj loc_t2_useful = true; 107538fd1498Szrj else 107638fd1498Szrj { 107738fd1498Szrj expanded_location xloc1 = expand_location (loc_t1); 107838fd1498Szrj expanded_location xloc2 = expand_location (loc_t2); 107938fd1498Szrj 108038fd1498Szrj if (strcmp (xloc1.file, xloc2.file) 108138fd1498Szrj || xloc1.line != xloc2.line 108238fd1498Szrj || xloc1.column != xloc2.column) 108338fd1498Szrj loc_t2_useful = true; 108438fd1498Szrj } 108538fd1498Szrj } 108638fd1498Szrj 108738fd1498Szrj if (loc_t1 <= BUILTINS_LOCATION) 108838fd1498Szrj loc_t1 = loc1; 108938fd1498Szrj if (loc_t2 <= BUILTINS_LOCATION) 109038fd1498Szrj loc_t2 = loc2; 109138fd1498Szrj 109238fd1498Szrj location_t loc = loc_t1 <= BUILTINS_LOCATION ? loc_t2 : loc_t1; 109338fd1498Szrj 109438fd1498Szrj /* It is a quite common bug to reference anonymous namespace type in 109538fd1498Szrj non-anonymous namespace class. */ 109638fd1498Szrj if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1)) 109738fd1498Szrj || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2))) 109838fd1498Szrj { 109938fd1498Szrj if (type_with_linkage_p (t1) && !type_in_anonymous_namespace_p (t1)) 110038fd1498Szrj { 110138fd1498Szrj std::swap (t1, t2); 110238fd1498Szrj std::swap (loc_t1, loc_t2); 110338fd1498Szrj } 110438fd1498Szrj gcc_assert (TYPE_NAME (t1) && TYPE_NAME (t2) 110538fd1498Szrj && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL 110638fd1498Szrj && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL); 110738fd1498Szrj /* Most of the time, the type names will match, do not be unnecesarily 110838fd1498Szrj verbose. */ 110938fd1498Szrj if (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t1))) 111038fd1498Szrj != IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t2)))) 111138fd1498Szrj inform (loc_t1, 111238fd1498Szrj "type %qT defined in anonymous namespace can not match " 111338fd1498Szrj "type %qT across the translation unit boundary", 111438fd1498Szrj t1, t2); 111538fd1498Szrj else 111638fd1498Szrj inform (loc_t1, 111738fd1498Szrj "type %qT defined in anonymous namespace can not match " 111838fd1498Szrj "across the translation unit boundary", 111938fd1498Szrj t1); 112038fd1498Szrj if (loc_t2_useful) 112138fd1498Szrj inform (loc_t2, 112238fd1498Szrj "the incompatible type defined in another translation unit"); 112338fd1498Szrj return; 112438fd1498Szrj } 112538fd1498Szrj /* If types have mangled ODR names and they are different, it is most 112638fd1498Szrj informative to output those. 112738fd1498Szrj This also covers types defined in different namespaces. */ 112838fd1498Szrj if (TYPE_NAME (t1) && TYPE_NAME (t2) 112938fd1498Szrj && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL 113038fd1498Szrj && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL 113138fd1498Szrj && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t1)) 113238fd1498Szrj && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t2)) 113338fd1498Szrj && DECL_ASSEMBLER_NAME (TYPE_NAME (t1)) 113438fd1498Szrj != DECL_ASSEMBLER_NAME (TYPE_NAME (t2))) 113538fd1498Szrj { 113638fd1498Szrj char *name1 = xstrdup (cplus_demangle 113738fd1498Szrj (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (t1))), 113838fd1498Szrj DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES)); 113938fd1498Szrj char *name2 = cplus_demangle 114038fd1498Szrj (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (TYPE_NAME (t2))), 114138fd1498Szrj DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES); 114238fd1498Szrj if (name1 && name2 && strcmp (name1, name2)) 114338fd1498Szrj { 114438fd1498Szrj inform (loc_t1, 114538fd1498Szrj "type name %qs should match type name %qs", 114638fd1498Szrj name1, name2); 114738fd1498Szrj if (loc_t2_useful) 114838fd1498Szrj inform (loc_t2, 114938fd1498Szrj "the incompatible type is defined here"); 115038fd1498Szrj free (name1); 115138fd1498Szrj return; 115238fd1498Szrj } 115338fd1498Szrj free (name1); 115438fd1498Szrj } 115538fd1498Szrj /* A tricky case are compound types. Often they appear the same in source 115638fd1498Szrj code and the mismatch is dragged in by type they are build from. 115738fd1498Szrj Look for those differences in subtypes and try to be informative. In other 115838fd1498Szrj cases just output nothing because the source code is probably different 115938fd1498Szrj and in this case we already output a all necessary info. */ 116038fd1498Szrj if (!TYPE_NAME (t1) || !TYPE_NAME (t2)) 116138fd1498Szrj { 116238fd1498Szrj if (TREE_CODE (t1) == TREE_CODE (t2)) 116338fd1498Szrj { 116438fd1498Szrj if (TREE_CODE (t1) == ARRAY_TYPE 116538fd1498Szrj && COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2)) 116638fd1498Szrj { 116738fd1498Szrj tree i1 = TYPE_DOMAIN (t1); 116838fd1498Szrj tree i2 = TYPE_DOMAIN (t2); 116938fd1498Szrj 117038fd1498Szrj if (i1 && i2 117138fd1498Szrj && TYPE_MAX_VALUE (i1) 117238fd1498Szrj && TYPE_MAX_VALUE (i2) 117338fd1498Szrj && !operand_equal_p (TYPE_MAX_VALUE (i1), 117438fd1498Szrj TYPE_MAX_VALUE (i2), 0)) 117538fd1498Szrj { 117638fd1498Szrj inform (loc, 117738fd1498Szrj "array types have different bounds"); 117838fd1498Szrj return; 117938fd1498Szrj } 118038fd1498Szrj } 118138fd1498Szrj if ((POINTER_TYPE_P (t1) || TREE_CODE (t1) == ARRAY_TYPE) 118238fd1498Szrj && type_mismatch_p (TREE_TYPE (t1), TREE_TYPE (t2))) 118338fd1498Szrj warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), loc_t1, loc_t2); 118438fd1498Szrj else if (TREE_CODE (t1) == METHOD_TYPE 118538fd1498Szrj || TREE_CODE (t1) == FUNCTION_TYPE) 118638fd1498Szrj { 118738fd1498Szrj tree parms1 = NULL, parms2 = NULL; 118838fd1498Szrj int count = 1; 118938fd1498Szrj 119038fd1498Szrj if (type_mismatch_p (TREE_TYPE (t1), TREE_TYPE (t2))) 119138fd1498Szrj { 119238fd1498Szrj inform (loc, "return value type mismatch"); 119338fd1498Szrj warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), loc_t1, 119438fd1498Szrj loc_t2); 119538fd1498Szrj return; 119638fd1498Szrj } 119738fd1498Szrj if (prototype_p (t1) && prototype_p (t2)) 119838fd1498Szrj for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2); 119938fd1498Szrj parms1 && parms2; 120038fd1498Szrj parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2), 120138fd1498Szrj count++) 120238fd1498Szrj { 120338fd1498Szrj if (type_mismatch_p (TREE_VALUE (parms1), TREE_VALUE (parms2))) 120438fd1498Szrj { 120538fd1498Szrj if (count == 1 && TREE_CODE (t1) == METHOD_TYPE) 120638fd1498Szrj inform (loc, 120738fd1498Szrj "implicit this pointer type mismatch"); 120838fd1498Szrj else 120938fd1498Szrj inform (loc, 121038fd1498Szrj "type mismatch in parameter %i", 121138fd1498Szrj count - (TREE_CODE (t1) == METHOD_TYPE)); 121238fd1498Szrj warn_types_mismatch (TREE_VALUE (parms1), 121338fd1498Szrj TREE_VALUE (parms2), 121438fd1498Szrj loc_t1, loc_t2); 121538fd1498Szrj return; 121638fd1498Szrj } 121738fd1498Szrj } 121838fd1498Szrj if (parms1 || parms2) 121938fd1498Szrj { 122038fd1498Szrj inform (loc, 122138fd1498Szrj "types have different parameter counts"); 122238fd1498Szrj return; 122338fd1498Szrj } 122438fd1498Szrj } 122538fd1498Szrj } 122638fd1498Szrj return; 122738fd1498Szrj } 122838fd1498Szrj 122938fd1498Szrj if (types_odr_comparable (t1, t2, true) 123038fd1498Szrj && types_same_for_odr (t1, t2, true)) 123138fd1498Szrj inform (loc_t1, 123238fd1498Szrj "type %qT itself violates the C++ One Definition Rule", t1); 123338fd1498Szrj /* Prevent pointless warnings like "struct aa" should match "struct aa". */ 123438fd1498Szrj else if (TYPE_NAME (t1) == TYPE_NAME (t2) 123538fd1498Szrj && TREE_CODE (t1) == TREE_CODE (t2) && !loc_t2_useful) 123638fd1498Szrj return; 123738fd1498Szrj else 123838fd1498Szrj inform (loc_t1, "type %qT should match type %qT", 123938fd1498Szrj t1, t2); 124038fd1498Szrj if (loc_t2_useful) 124138fd1498Szrj inform (loc_t2, "the incompatible type is defined here"); 124238fd1498Szrj } 124338fd1498Szrj 124438fd1498Szrj /* Compare T1 and T2, report ODR violations if WARN is true and set 124538fd1498Szrj WARNED to true if anything is reported. Return true if types match. 124638fd1498Szrj If true is returned, the types are also compatible in the sense of 124738fd1498Szrj gimple_canonical_types_compatible_p. 124838fd1498Szrj If LOC1 and LOC2 is not UNKNOWN_LOCATION it may be used to output a warning 124938fd1498Szrj about the type if the type itself do not have location. */ 125038fd1498Szrj 125138fd1498Szrj static bool 125238fd1498Szrj odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned, 125338fd1498Szrj hash_set<type_pair> *visited, 125438fd1498Szrj location_t loc1, location_t loc2) 125538fd1498Szrj { 125638fd1498Szrj /* Check first for the obvious case of pointer identity. */ 125738fd1498Szrj if (t1 == t2) 125838fd1498Szrj return true; 125938fd1498Szrj gcc_assert (!type_with_linkage_p (t1) || !type_in_anonymous_namespace_p (t1)); 126038fd1498Szrj gcc_assert (!type_with_linkage_p (t2) || !type_in_anonymous_namespace_p (t2)); 126138fd1498Szrj 126238fd1498Szrj /* Can't be the same type if the types don't have the same code. */ 126338fd1498Szrj if (TREE_CODE (t1) != TREE_CODE (t2)) 126438fd1498Szrj { 126538fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 126638fd1498Szrj G_("a different type is defined in another translation unit")); 126738fd1498Szrj return false; 126838fd1498Szrj } 126938fd1498Szrj 127038fd1498Szrj if (TYPE_QUALS (t1) != TYPE_QUALS (t2)) 127138fd1498Szrj { 127238fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 127338fd1498Szrj G_("a type with different qualifiers is defined in another " 127438fd1498Szrj "translation unit")); 127538fd1498Szrj return false; 127638fd1498Szrj } 127738fd1498Szrj 127838fd1498Szrj if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1)) 127938fd1498Szrj || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2))) 128038fd1498Szrj { 128138fd1498Szrj /* We can not trip this when comparing ODR types, only when trying to 128238fd1498Szrj match different ODR derivations from different declarations. 128338fd1498Szrj So WARN should be always false. */ 128438fd1498Szrj gcc_assert (!warn); 128538fd1498Szrj return false; 128638fd1498Szrj } 128738fd1498Szrj 128838fd1498Szrj if (comp_type_attributes (t1, t2) != 1) 128938fd1498Szrj { 129038fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 129138fd1498Szrj G_("a type with different attributes " 129238fd1498Szrj "is defined in another translation unit")); 129338fd1498Szrj return false; 129438fd1498Szrj } 129538fd1498Szrj 129638fd1498Szrj if (TREE_CODE (t1) == ENUMERAL_TYPE 129738fd1498Szrj && TYPE_VALUES (t1) && TYPE_VALUES (t2)) 129838fd1498Szrj { 129938fd1498Szrj tree v1, v2; 130038fd1498Szrj for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2); 130138fd1498Szrj v1 && v2 ; v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2)) 130238fd1498Szrj { 130338fd1498Szrj if (TREE_PURPOSE (v1) != TREE_PURPOSE (v2)) 130438fd1498Szrj { 130538fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 130638fd1498Szrj G_("an enum with different value name" 130738fd1498Szrj " is defined in another translation unit")); 130838fd1498Szrj return false; 130938fd1498Szrj } 131038fd1498Szrj if (TREE_VALUE (v1) != TREE_VALUE (v2) 131138fd1498Szrj && !operand_equal_p (DECL_INITIAL (TREE_VALUE (v1)), 131238fd1498Szrj DECL_INITIAL (TREE_VALUE (v2)), 0)) 131338fd1498Szrj { 131438fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 131538fd1498Szrj G_("an enum with different values is defined" 131638fd1498Szrj " in another translation unit")); 131738fd1498Szrj return false; 131838fd1498Szrj } 131938fd1498Szrj } 132038fd1498Szrj if (v1 || v2) 132138fd1498Szrj { 132238fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 132338fd1498Szrj G_("an enum with mismatching number of values " 132438fd1498Szrj "is defined in another translation unit")); 132538fd1498Szrj return false; 132638fd1498Szrj } 132738fd1498Szrj } 132838fd1498Szrj 132938fd1498Szrj /* Non-aggregate types can be handled cheaply. */ 133038fd1498Szrj if (INTEGRAL_TYPE_P (t1) 133138fd1498Szrj || SCALAR_FLOAT_TYPE_P (t1) 133238fd1498Szrj || FIXED_POINT_TYPE_P (t1) 133338fd1498Szrj || TREE_CODE (t1) == VECTOR_TYPE 133438fd1498Szrj || TREE_CODE (t1) == COMPLEX_TYPE 133538fd1498Szrj || TREE_CODE (t1) == OFFSET_TYPE 133638fd1498Szrj || POINTER_TYPE_P (t1)) 133738fd1498Szrj { 133838fd1498Szrj if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)) 133938fd1498Szrj { 134038fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 134138fd1498Szrj G_("a type with different precision is defined " 134238fd1498Szrj "in another translation unit")); 134338fd1498Szrj return false; 134438fd1498Szrj } 134538fd1498Szrj if (TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2)) 134638fd1498Szrj { 134738fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 134838fd1498Szrj G_("a type with different signedness is defined " 134938fd1498Szrj "in another translation unit")); 135038fd1498Szrj return false; 135138fd1498Szrj } 135238fd1498Szrj 135338fd1498Szrj if (TREE_CODE (t1) == INTEGER_TYPE 135438fd1498Szrj && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)) 135538fd1498Szrj { 135638fd1498Szrj /* char WRT uint_8? */ 135738fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 135838fd1498Szrj G_("a different type is defined in another " 135938fd1498Szrj "translation unit")); 136038fd1498Szrj return false; 136138fd1498Szrj } 136238fd1498Szrj 136338fd1498Szrj /* For canonical type comparisons we do not want to build SCCs 136438fd1498Szrj so we cannot compare pointed-to types. But we can, for now, 136538fd1498Szrj require the same pointed-to type kind and match what 136638fd1498Szrj useless_type_conversion_p would do. */ 136738fd1498Szrj if (POINTER_TYPE_P (t1)) 136838fd1498Szrj { 136938fd1498Szrj if (TYPE_ADDR_SPACE (TREE_TYPE (t1)) 137038fd1498Szrj != TYPE_ADDR_SPACE (TREE_TYPE (t2))) 137138fd1498Szrj { 137238fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 137338fd1498Szrj G_("it is defined as a pointer in different address " 137438fd1498Szrj "space in another translation unit")); 137538fd1498Szrj return false; 137638fd1498Szrj } 137738fd1498Szrj 137838fd1498Szrj if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2), 137938fd1498Szrj visited, loc1, loc2)) 138038fd1498Szrj { 138138fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 138238fd1498Szrj G_("it is defined as a pointer to different type " 138338fd1498Szrj "in another translation unit")); 138438fd1498Szrj if (warn && warned) 138538fd1498Szrj warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), 138638fd1498Szrj loc1, loc2); 138738fd1498Szrj return false; 138838fd1498Szrj } 138938fd1498Szrj } 139038fd1498Szrj 139138fd1498Szrj if ((TREE_CODE (t1) == VECTOR_TYPE || TREE_CODE (t1) == COMPLEX_TYPE) 139238fd1498Szrj && !odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2), 139338fd1498Szrj visited, loc1, loc2)) 139438fd1498Szrj { 139538fd1498Szrj /* Probably specific enough. */ 139638fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 139738fd1498Szrj G_("a different type is defined " 139838fd1498Szrj "in another translation unit")); 139938fd1498Szrj if (warn && warned) 140038fd1498Szrj warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), loc1, loc2); 140138fd1498Szrj return false; 140238fd1498Szrj } 140338fd1498Szrj } 140438fd1498Szrj /* Do type-specific comparisons. */ 140538fd1498Szrj else switch (TREE_CODE (t1)) 140638fd1498Szrj { 140738fd1498Szrj case ARRAY_TYPE: 140838fd1498Szrj { 140938fd1498Szrj /* Array types are the same if the element types are the same and 141038fd1498Szrj the number of elements are the same. */ 141138fd1498Szrj if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2), 141238fd1498Szrj visited, loc1, loc2)) 141338fd1498Szrj { 141438fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 141538fd1498Szrj G_("a different type is defined in another " 141638fd1498Szrj "translation unit")); 141738fd1498Szrj if (warn && warned) 141838fd1498Szrj warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), loc1, loc2); 141938fd1498Szrj } 142038fd1498Szrj gcc_assert (TYPE_STRING_FLAG (t1) == TYPE_STRING_FLAG (t2)); 142138fd1498Szrj gcc_assert (TYPE_NONALIASED_COMPONENT (t1) 142238fd1498Szrj == TYPE_NONALIASED_COMPONENT (t2)); 142338fd1498Szrj 142438fd1498Szrj tree i1 = TYPE_DOMAIN (t1); 142538fd1498Szrj tree i2 = TYPE_DOMAIN (t2); 142638fd1498Szrj 142738fd1498Szrj /* For an incomplete external array, the type domain can be 142838fd1498Szrj NULL_TREE. Check this condition also. */ 142938fd1498Szrj if (i1 == NULL_TREE || i2 == NULL_TREE) 143038fd1498Szrj return true; 143138fd1498Szrj 143238fd1498Szrj tree min1 = TYPE_MIN_VALUE (i1); 143338fd1498Szrj tree min2 = TYPE_MIN_VALUE (i2); 143438fd1498Szrj tree max1 = TYPE_MAX_VALUE (i1); 143538fd1498Szrj tree max2 = TYPE_MAX_VALUE (i2); 143638fd1498Szrj 143738fd1498Szrj /* In C++, minimums should be always 0. */ 143838fd1498Szrj gcc_assert (min1 == min2); 143938fd1498Szrj if (!operand_equal_p (max1, max2, 0)) 144038fd1498Szrj { 144138fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 144238fd1498Szrj G_("an array of different size is defined " 144338fd1498Szrj "in another translation unit")); 144438fd1498Szrj return false; 144538fd1498Szrj } 144638fd1498Szrj } 144738fd1498Szrj break; 144838fd1498Szrj 144938fd1498Szrj case METHOD_TYPE: 145038fd1498Szrj case FUNCTION_TYPE: 145138fd1498Szrj /* Function types are the same if the return type and arguments types 145238fd1498Szrj are the same. */ 145338fd1498Szrj if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2), 145438fd1498Szrj visited, loc1, loc2)) 145538fd1498Szrj { 145638fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 145738fd1498Szrj G_("has different return value " 145838fd1498Szrj "in another translation unit")); 145938fd1498Szrj if (warn && warned) 146038fd1498Szrj warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), loc1, loc2); 146138fd1498Szrj return false; 146238fd1498Szrj } 146338fd1498Szrj 146438fd1498Szrj if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2) 146538fd1498Szrj || !prototype_p (t1) || !prototype_p (t2)) 146638fd1498Szrj return true; 146738fd1498Szrj else 146838fd1498Szrj { 146938fd1498Szrj tree parms1, parms2; 147038fd1498Szrj 147138fd1498Szrj for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2); 147238fd1498Szrj parms1 && parms2; 147338fd1498Szrj parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2)) 147438fd1498Szrj { 147538fd1498Szrj if (!odr_subtypes_equivalent_p 147638fd1498Szrj (TREE_VALUE (parms1), TREE_VALUE (parms2), visited, 147738fd1498Szrj loc1, loc2)) 147838fd1498Szrj { 147938fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 148038fd1498Szrj G_("has different parameters in another " 148138fd1498Szrj "translation unit")); 148238fd1498Szrj if (warn && warned) 148338fd1498Szrj warn_types_mismatch (TREE_VALUE (parms1), 148438fd1498Szrj TREE_VALUE (parms2), loc1, loc2); 148538fd1498Szrj return false; 148638fd1498Szrj } 148738fd1498Szrj } 148838fd1498Szrj 148938fd1498Szrj if (parms1 || parms2) 149038fd1498Szrj { 149138fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 149238fd1498Szrj G_("has different parameters " 149338fd1498Szrj "in another translation unit")); 149438fd1498Szrj return false; 149538fd1498Szrj } 149638fd1498Szrj 149738fd1498Szrj return true; 149838fd1498Szrj } 149938fd1498Szrj 150038fd1498Szrj case RECORD_TYPE: 150138fd1498Szrj case UNION_TYPE: 150238fd1498Szrj case QUAL_UNION_TYPE: 150338fd1498Szrj { 150438fd1498Szrj tree f1, f2; 150538fd1498Szrj 150638fd1498Szrj /* For aggregate types, all the fields must be the same. */ 150738fd1498Szrj if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2)) 150838fd1498Szrj { 150938fd1498Szrj if (TYPE_BINFO (t1) && TYPE_BINFO (t2) 151038fd1498Szrj && polymorphic_type_binfo_p (TYPE_BINFO (t1)) 151138fd1498Szrj != polymorphic_type_binfo_p (TYPE_BINFO (t2))) 151238fd1498Szrj { 151338fd1498Szrj if (polymorphic_type_binfo_p (TYPE_BINFO (t1))) 151438fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 151538fd1498Szrj G_("a type defined in another translation unit " 151638fd1498Szrj "is not polymorphic")); 151738fd1498Szrj else 151838fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 151938fd1498Szrj G_("a type defined in another translation unit " 152038fd1498Szrj "is polymorphic")); 152138fd1498Szrj return false; 152238fd1498Szrj } 152338fd1498Szrj for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2); 152438fd1498Szrj f1 || f2; 152538fd1498Szrj f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2)) 152638fd1498Szrj { 152738fd1498Szrj /* Skip non-fields. */ 152838fd1498Szrj while (f1 && TREE_CODE (f1) != FIELD_DECL) 152938fd1498Szrj f1 = TREE_CHAIN (f1); 153038fd1498Szrj while (f2 && TREE_CODE (f2) != FIELD_DECL) 153138fd1498Szrj f2 = TREE_CHAIN (f2); 153238fd1498Szrj if (!f1 || !f2) 153338fd1498Szrj break; 153438fd1498Szrj if (DECL_VIRTUAL_P (f1) != DECL_VIRTUAL_P (f2)) 153538fd1498Szrj { 153638fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 153738fd1498Szrj G_("a type with different virtual table pointers" 153838fd1498Szrj " is defined in another translation unit")); 153938fd1498Szrj return false; 154038fd1498Szrj } 154138fd1498Szrj if (DECL_ARTIFICIAL (f1) != DECL_ARTIFICIAL (f2)) 154238fd1498Szrj { 154338fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 154438fd1498Szrj G_("a type with different bases is defined " 154538fd1498Szrj "in another translation unit")); 154638fd1498Szrj return false; 154738fd1498Szrj } 154838fd1498Szrj if (DECL_NAME (f1) != DECL_NAME (f2) 154938fd1498Szrj && !DECL_ARTIFICIAL (f1)) 155038fd1498Szrj { 155138fd1498Szrj warn_odr (t1, t2, f1, f2, warn, warned, 155238fd1498Szrj G_("a field with different name is defined " 155338fd1498Szrj "in another translation unit")); 155438fd1498Szrj return false; 155538fd1498Szrj } 155638fd1498Szrj if (!odr_subtypes_equivalent_p (TREE_TYPE (f1), 155738fd1498Szrj TREE_TYPE (f2), visited, 155838fd1498Szrj loc1, loc2)) 155938fd1498Szrj { 156038fd1498Szrj /* Do not warn about artificial fields and just go into 156138fd1498Szrj generic field mismatch warning. */ 156238fd1498Szrj if (DECL_ARTIFICIAL (f1)) 156338fd1498Szrj break; 156438fd1498Szrj 156538fd1498Szrj warn_odr (t1, t2, f1, f2, warn, warned, 156638fd1498Szrj G_("a field of same name but different type " 156738fd1498Szrj "is defined in another translation unit")); 156838fd1498Szrj if (warn && warned) 156938fd1498Szrj warn_types_mismatch (TREE_TYPE (f1), TREE_TYPE (f2), loc1, loc2); 157038fd1498Szrj return false; 157138fd1498Szrj } 157238fd1498Szrj if (!gimple_compare_field_offset (f1, f2)) 157338fd1498Szrj { 157438fd1498Szrj /* Do not warn about artificial fields and just go into 157538fd1498Szrj generic field mismatch warning. */ 157638fd1498Szrj if (DECL_ARTIFICIAL (f1)) 157738fd1498Szrj break; 157838fd1498Szrj warn_odr (t1, t2, f1, f2, warn, warned, 157938fd1498Szrj G_("fields have different layout " 158038fd1498Szrj "in another translation unit")); 158138fd1498Szrj return false; 158238fd1498Szrj } 158338fd1498Szrj if (DECL_BIT_FIELD (f1) != DECL_BIT_FIELD (f2)) 158438fd1498Szrj { 158538fd1498Szrj warn_odr (t1, t2, f1, f2, warn, warned, 158638fd1498Szrj G_("one field is bitfield while other is not")); 158738fd1498Szrj return false; 158838fd1498Szrj } 158938fd1498Szrj else 159038fd1498Szrj gcc_assert (DECL_NONADDRESSABLE_P (f1) 159138fd1498Szrj == DECL_NONADDRESSABLE_P (f2)); 159238fd1498Szrj } 159338fd1498Szrj 159438fd1498Szrj /* If one aggregate has more fields than the other, they 159538fd1498Szrj are not the same. */ 159638fd1498Szrj if (f1 || f2) 159738fd1498Szrj { 159838fd1498Szrj if ((f1 && DECL_VIRTUAL_P (f1)) || (f2 && DECL_VIRTUAL_P (f2))) 159938fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 160038fd1498Szrj G_("a type with different virtual table pointers" 160138fd1498Szrj " is defined in another translation unit")); 160238fd1498Szrj else if ((f1 && DECL_ARTIFICIAL (f1)) 160338fd1498Szrj || (f2 && DECL_ARTIFICIAL (f2))) 160438fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 160538fd1498Szrj G_("a type with different bases is defined " 160638fd1498Szrj "in another translation unit")); 160738fd1498Szrj else 160838fd1498Szrj warn_odr (t1, t2, f1, f2, warn, warned, 160938fd1498Szrj G_("a type with different number of fields " 161038fd1498Szrj "is defined in another translation unit")); 161138fd1498Szrj 161238fd1498Szrj return false; 161338fd1498Szrj } 161438fd1498Szrj } 161538fd1498Szrj break; 161638fd1498Szrj } 161738fd1498Szrj case VOID_TYPE: 161838fd1498Szrj case NULLPTR_TYPE: 161938fd1498Szrj break; 162038fd1498Szrj 162138fd1498Szrj default: 162238fd1498Szrj debug_tree (t1); 162338fd1498Szrj gcc_unreachable (); 162438fd1498Szrj } 162538fd1498Szrj 162638fd1498Szrj /* Those are better to come last as they are utterly uninformative. */ 162738fd1498Szrj if (TYPE_SIZE (t1) && TYPE_SIZE (t2) 162838fd1498Szrj && !operand_equal_p (TYPE_SIZE (t1), TYPE_SIZE (t2), 0)) 162938fd1498Szrj { 163038fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 163138fd1498Szrj G_("a type with different size " 163238fd1498Szrj "is defined in another translation unit")); 163338fd1498Szrj return false; 163438fd1498Szrj } 163538fd1498Szrj if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2) 163638fd1498Szrj && TYPE_ALIGN (t1) != TYPE_ALIGN (t2)) 163738fd1498Szrj { 163838fd1498Szrj warn_odr (t1, t2, NULL, NULL, warn, warned, 163938fd1498Szrj G_("a type with different alignment " 164038fd1498Szrj "is defined in another translation unit")); 164138fd1498Szrj return false; 164238fd1498Szrj } 164338fd1498Szrj gcc_assert (!TYPE_SIZE_UNIT (t1) || !TYPE_SIZE_UNIT (t2) 164438fd1498Szrj || operand_equal_p (TYPE_SIZE_UNIT (t1), 164538fd1498Szrj TYPE_SIZE_UNIT (t2), 0)); 164638fd1498Szrj return true; 164738fd1498Szrj } 164838fd1498Szrj 164938fd1498Szrj /* Return true if TYPE1 and TYPE2 are equivalent for One Definition Rule. */ 165038fd1498Szrj 165138fd1498Szrj bool 165238fd1498Szrj odr_types_equivalent_p (tree type1, tree type2) 165338fd1498Szrj { 165438fd1498Szrj gcc_checking_assert (odr_or_derived_type_p (type1) 165538fd1498Szrj && odr_or_derived_type_p (type2)); 165638fd1498Szrj 165738fd1498Szrj hash_set<type_pair> visited; 165838fd1498Szrj return odr_types_equivalent_p (type1, type2, false, NULL, 165938fd1498Szrj &visited, UNKNOWN_LOCATION, UNKNOWN_LOCATION); 166038fd1498Szrj } 166138fd1498Szrj 166238fd1498Szrj /* TYPE is equivalent to VAL by ODR, but its tree representation differs 166338fd1498Szrj from VAL->type. This may happen in LTO where tree merging did not merge 166438fd1498Szrj all variants of the same type or due to ODR violation. 166538fd1498Szrj 166638fd1498Szrj Analyze and report ODR violations and add type to duplicate list. 166738fd1498Szrj If TYPE is more specified than VAL->type, prevail VAL->type. Also if 166838fd1498Szrj this is first time we see definition of a class return true so the 166938fd1498Szrj base types are analyzed. */ 167038fd1498Szrj 167138fd1498Szrj static bool 167238fd1498Szrj add_type_duplicate (odr_type val, tree type) 167338fd1498Szrj { 167438fd1498Szrj bool build_bases = false; 167538fd1498Szrj bool prevail = false; 167638fd1498Szrj bool odr_must_violate = false; 167738fd1498Szrj 167838fd1498Szrj if (!val->types_set) 167938fd1498Szrj val->types_set = new hash_set<tree>; 168038fd1498Szrj 168138fd1498Szrj /* Chose polymorphic type as leader (this happens only in case of ODR 168238fd1498Szrj violations. */ 168338fd1498Szrj if ((TREE_CODE (type) == RECORD_TYPE && TYPE_BINFO (type) 168438fd1498Szrj && polymorphic_type_binfo_p (TYPE_BINFO (type))) 168538fd1498Szrj && (TREE_CODE (val->type) != RECORD_TYPE || !TYPE_BINFO (val->type) 168638fd1498Szrj || !polymorphic_type_binfo_p (TYPE_BINFO (val->type)))) 168738fd1498Szrj { 168838fd1498Szrj prevail = true; 168938fd1498Szrj build_bases = true; 169038fd1498Szrj } 169138fd1498Szrj /* Always prefer complete type to be the leader. */ 169238fd1498Szrj else if (!COMPLETE_TYPE_P (val->type) && COMPLETE_TYPE_P (type)) 169338fd1498Szrj { 169438fd1498Szrj prevail = true; 169538fd1498Szrj build_bases = TYPE_BINFO (type); 169638fd1498Szrj } 169738fd1498Szrj else if (COMPLETE_TYPE_P (val->type) && !COMPLETE_TYPE_P (type)) 169838fd1498Szrj ; 169938fd1498Szrj else if (TREE_CODE (val->type) == ENUMERAL_TYPE 170038fd1498Szrj && TREE_CODE (type) == ENUMERAL_TYPE 170138fd1498Szrj && !TYPE_VALUES (val->type) && TYPE_VALUES (type)) 170238fd1498Szrj prevail = true; 170338fd1498Szrj else if (TREE_CODE (val->type) == RECORD_TYPE 170438fd1498Szrj && TREE_CODE (type) == RECORD_TYPE 170538fd1498Szrj && TYPE_BINFO (type) && !TYPE_BINFO (val->type)) 170638fd1498Szrj { 170738fd1498Szrj gcc_assert (!val->bases.length ()); 170838fd1498Szrj build_bases = true; 170938fd1498Szrj prevail = true; 171038fd1498Szrj } 171138fd1498Szrj 171238fd1498Szrj if (prevail) 171338fd1498Szrj std::swap (val->type, type); 171438fd1498Szrj 171538fd1498Szrj val->types_set->add (type); 171638fd1498Szrj 171738fd1498Szrj /* If we now have a mangled name, be sure to record it to val->type 171838fd1498Szrj so ODR hash can work. */ 171938fd1498Szrj 172038fd1498Szrj if (can_be_name_hashed_p (type) && !can_be_name_hashed_p (val->type)) 172138fd1498Szrj SET_DECL_ASSEMBLER_NAME (TYPE_NAME (val->type), 172238fd1498Szrj DECL_ASSEMBLER_NAME (TYPE_NAME (type))); 172338fd1498Szrj 172438fd1498Szrj bool merge = true; 172538fd1498Szrj bool base_mismatch = false; 172638fd1498Szrj unsigned int i; 172738fd1498Szrj bool warned = false; 172838fd1498Szrj hash_set<type_pair> visited; 172938fd1498Szrj 173038fd1498Szrj gcc_assert (in_lto_p); 173138fd1498Szrj vec_safe_push (val->types, type); 173238fd1498Szrj 173338fd1498Szrj /* If both are class types, compare the bases. */ 173438fd1498Szrj if (COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (val->type) 173538fd1498Szrj && TREE_CODE (val->type) == RECORD_TYPE 173638fd1498Szrj && TREE_CODE (type) == RECORD_TYPE 173738fd1498Szrj && TYPE_BINFO (val->type) && TYPE_BINFO (type)) 173838fd1498Szrj { 173938fd1498Szrj if (BINFO_N_BASE_BINFOS (TYPE_BINFO (type)) 174038fd1498Szrj != BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type))) 174138fd1498Szrj { 174238fd1498Szrj if (!flag_ltrans && !warned && !val->odr_violated) 174338fd1498Szrj { 174438fd1498Szrj tree extra_base; 174538fd1498Szrj warn_odr (type, val->type, NULL, NULL, !warned, &warned, 174638fd1498Szrj "a type with the same name but different " 174738fd1498Szrj "number of polymorphic bases is " 174838fd1498Szrj "defined in another translation unit"); 174938fd1498Szrj if (warned) 175038fd1498Szrj { 175138fd1498Szrj if (BINFO_N_BASE_BINFOS (TYPE_BINFO (type)) 175238fd1498Szrj > BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type))) 175338fd1498Szrj extra_base = BINFO_BASE_BINFO 175438fd1498Szrj (TYPE_BINFO (type), 175538fd1498Szrj BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type))); 175638fd1498Szrj else 175738fd1498Szrj extra_base = BINFO_BASE_BINFO 175838fd1498Szrj (TYPE_BINFO (val->type), 175938fd1498Szrj BINFO_N_BASE_BINFOS (TYPE_BINFO (type))); 176038fd1498Szrj tree extra_base_type = BINFO_TYPE (extra_base); 176138fd1498Szrj inform (DECL_SOURCE_LOCATION (TYPE_NAME (extra_base_type)), 176238fd1498Szrj "the extra base is defined here"); 176338fd1498Szrj } 176438fd1498Szrj } 176538fd1498Szrj base_mismatch = true; 176638fd1498Szrj } 176738fd1498Szrj else 176838fd1498Szrj for (i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++) 176938fd1498Szrj { 177038fd1498Szrj tree base1 = BINFO_BASE_BINFO (TYPE_BINFO (type), i); 177138fd1498Szrj tree base2 = BINFO_BASE_BINFO (TYPE_BINFO (val->type), i); 177238fd1498Szrj tree type1 = BINFO_TYPE (base1); 177338fd1498Szrj tree type2 = BINFO_TYPE (base2); 177438fd1498Szrj 177538fd1498Szrj if (types_odr_comparable (type1, type2)) 177638fd1498Szrj { 177738fd1498Szrj if (!types_same_for_odr (type1, type2)) 177838fd1498Szrj base_mismatch = true; 177938fd1498Szrj } 178038fd1498Szrj else 178138fd1498Szrj if (!odr_types_equivalent_p (type1, type2)) 178238fd1498Szrj base_mismatch = true; 178338fd1498Szrj if (base_mismatch) 178438fd1498Szrj { 178538fd1498Szrj if (!warned && !val->odr_violated) 178638fd1498Szrj { 178738fd1498Szrj warn_odr (type, val->type, NULL, NULL, 178838fd1498Szrj !warned, &warned, 178938fd1498Szrj "a type with the same name but different base " 179038fd1498Szrj "type is defined in another translation unit"); 179138fd1498Szrj if (warned) 179238fd1498Szrj warn_types_mismatch (type1, type2, 179338fd1498Szrj UNKNOWN_LOCATION, UNKNOWN_LOCATION); 179438fd1498Szrj } 179538fd1498Szrj break; 179638fd1498Szrj } 179738fd1498Szrj if (BINFO_OFFSET (base1) != BINFO_OFFSET (base2)) 179838fd1498Szrj { 179938fd1498Szrj base_mismatch = true; 180038fd1498Szrj if (!warned && !val->odr_violated) 180138fd1498Szrj warn_odr (type, val->type, NULL, NULL, 180238fd1498Szrj !warned, &warned, 180338fd1498Szrj "a type with the same name but different base " 180438fd1498Szrj "layout is defined in another translation unit"); 180538fd1498Szrj break; 180638fd1498Szrj } 180738fd1498Szrj /* One of bases is not of complete type. */ 180838fd1498Szrj if (!TYPE_BINFO (type1) != !TYPE_BINFO (type2)) 180938fd1498Szrj { 181038fd1498Szrj /* If we have a polymorphic type info specified for TYPE1 181138fd1498Szrj but not for TYPE2 we possibly missed a base when recording 181238fd1498Szrj VAL->type earlier. 181338fd1498Szrj Be sure this does not happen. */ 181438fd1498Szrj if (TYPE_BINFO (type1) 181538fd1498Szrj && polymorphic_type_binfo_p (TYPE_BINFO (type1)) 181638fd1498Szrj && !build_bases) 181738fd1498Szrj odr_must_violate = true; 181838fd1498Szrj break; 181938fd1498Szrj } 182038fd1498Szrj /* One base is polymorphic and the other not. 182138fd1498Szrj This ought to be diagnosed earlier, but do not ICE in the 182238fd1498Szrj checking bellow. */ 182338fd1498Szrj else if (TYPE_BINFO (type1) 182438fd1498Szrj && polymorphic_type_binfo_p (TYPE_BINFO (type1)) 182538fd1498Szrj != polymorphic_type_binfo_p (TYPE_BINFO (type2))) 182638fd1498Szrj { 182738fd1498Szrj if (!warned && !val->odr_violated) 182838fd1498Szrj warn_odr (type, val->type, NULL, NULL, 182938fd1498Szrj !warned, &warned, 183038fd1498Szrj "a base of the type is polymorphic only in one " 183138fd1498Szrj "translation unit"); 183238fd1498Szrj base_mismatch = true; 183338fd1498Szrj break; 183438fd1498Szrj } 183538fd1498Szrj } 183638fd1498Szrj if (base_mismatch) 183738fd1498Szrj { 183838fd1498Szrj merge = false; 183938fd1498Szrj odr_violation_reported = true; 184038fd1498Szrj val->odr_violated = true; 184138fd1498Szrj 184238fd1498Szrj if (symtab->dump_file) 184338fd1498Szrj { 184438fd1498Szrj fprintf (symtab->dump_file, "ODR base violation\n"); 184538fd1498Szrj 184638fd1498Szrj print_node (symtab->dump_file, "", val->type, 0); 184738fd1498Szrj putc ('\n',symtab->dump_file); 184838fd1498Szrj print_node (symtab->dump_file, "", type, 0); 184938fd1498Szrj putc ('\n',symtab->dump_file); 185038fd1498Szrj } 185138fd1498Szrj } 185238fd1498Szrj } 185338fd1498Szrj 185438fd1498Szrj /* Next compare memory layout. 185538fd1498Szrj The DECL_SOURCE_LOCATIONs in this invocation came from LTO streaming. 185638fd1498Szrj We must apply the location cache to ensure that they are valid 185738fd1498Szrj before we can pass them to odr_types_equivalent_p (PR lto/83121). */ 185838fd1498Szrj if (lto_location_cache::current_cache) 185938fd1498Szrj lto_location_cache::current_cache->apply_location_cache (); 186038fd1498Szrj if (!odr_types_equivalent_p (val->type, type, 186138fd1498Szrj !flag_ltrans && !val->odr_violated && !warned, 186238fd1498Szrj &warned, &visited, 186338fd1498Szrj DECL_SOURCE_LOCATION (TYPE_NAME (val->type)), 186438fd1498Szrj DECL_SOURCE_LOCATION (TYPE_NAME (type)))) 186538fd1498Szrj { 186638fd1498Szrj merge = false; 186738fd1498Szrj odr_violation_reported = true; 186838fd1498Szrj val->odr_violated = true; 186938fd1498Szrj } 187038fd1498Szrj gcc_assert (val->odr_violated || !odr_must_violate); 187138fd1498Szrj /* Sanity check that all bases will be build same way again. */ 187238fd1498Szrj if (flag_checking 187338fd1498Szrj && COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (val->type) 187438fd1498Szrj && TREE_CODE (val->type) == RECORD_TYPE 187538fd1498Szrj && TREE_CODE (type) == RECORD_TYPE 187638fd1498Szrj && TYPE_BINFO (val->type) && TYPE_BINFO (type) 187738fd1498Szrj && !val->odr_violated 187838fd1498Szrj && !base_mismatch && val->bases.length ()) 187938fd1498Szrj { 188038fd1498Szrj unsigned int num_poly_bases = 0; 188138fd1498Szrj unsigned int j; 188238fd1498Szrj 188338fd1498Szrj for (i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++) 188438fd1498Szrj if (polymorphic_type_binfo_p (BINFO_BASE_BINFO 188538fd1498Szrj (TYPE_BINFO (type), i))) 188638fd1498Szrj num_poly_bases++; 188738fd1498Szrj gcc_assert (num_poly_bases == val->bases.length ()); 188838fd1498Szrj for (j = 0, i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); 188938fd1498Szrj i++) 189038fd1498Szrj if (polymorphic_type_binfo_p (BINFO_BASE_BINFO 189138fd1498Szrj (TYPE_BINFO (type), i))) 189238fd1498Szrj { 189338fd1498Szrj odr_type base = get_odr_type 189438fd1498Szrj (BINFO_TYPE 189538fd1498Szrj (BINFO_BASE_BINFO (TYPE_BINFO (type), 189638fd1498Szrj i)), 189738fd1498Szrj true); 189838fd1498Szrj gcc_assert (val->bases[j] == base); 189938fd1498Szrj j++; 190038fd1498Szrj } 190138fd1498Szrj } 190238fd1498Szrj 190338fd1498Szrj 190438fd1498Szrj /* Regularize things a little. During LTO same types may come with 190538fd1498Szrj different BINFOs. Either because their virtual table was 190638fd1498Szrj not merged by tree merging and only later at decl merging or 190738fd1498Szrj because one type comes with external vtable, while other 190838fd1498Szrj with internal. We want to merge equivalent binfos to conserve 190938fd1498Szrj memory and streaming overhead. 191038fd1498Szrj 191138fd1498Szrj The external vtables are more harmful: they contain references 191238fd1498Szrj to external declarations of methods that may be defined in the 191338fd1498Szrj merged LTO unit. For this reason we absolutely need to remove 191438fd1498Szrj them and replace by internal variants. Not doing so will lead 191538fd1498Szrj to incomplete answers from possible_polymorphic_call_targets. 191638fd1498Szrj 191738fd1498Szrj FIXME: disable for now; because ODR types are now build during 191838fd1498Szrj streaming in, the variants do not need to be linked to the type, 191938fd1498Szrj yet. We need to do the merging in cleanup pass to be implemented 192038fd1498Szrj soon. */ 192138fd1498Szrj if (!flag_ltrans && merge 192238fd1498Szrj && 0 192338fd1498Szrj && TREE_CODE (val->type) == RECORD_TYPE 192438fd1498Szrj && TREE_CODE (type) == RECORD_TYPE 192538fd1498Szrj && TYPE_BINFO (val->type) && TYPE_BINFO (type) 192638fd1498Szrj && TYPE_MAIN_VARIANT (type) == type 192738fd1498Szrj && TYPE_MAIN_VARIANT (val->type) == val->type 192838fd1498Szrj && BINFO_VTABLE (TYPE_BINFO (val->type)) 192938fd1498Szrj && BINFO_VTABLE (TYPE_BINFO (type))) 193038fd1498Szrj { 193138fd1498Szrj tree master_binfo = TYPE_BINFO (val->type); 193238fd1498Szrj tree v1 = BINFO_VTABLE (master_binfo); 193338fd1498Szrj tree v2 = BINFO_VTABLE (TYPE_BINFO (type)); 193438fd1498Szrj 193538fd1498Szrj if (TREE_CODE (v1) == POINTER_PLUS_EXPR) 193638fd1498Szrj { 193738fd1498Szrj gcc_assert (TREE_CODE (v2) == POINTER_PLUS_EXPR 193838fd1498Szrj && operand_equal_p (TREE_OPERAND (v1, 1), 193938fd1498Szrj TREE_OPERAND (v2, 1), 0)); 194038fd1498Szrj v1 = TREE_OPERAND (TREE_OPERAND (v1, 0), 0); 194138fd1498Szrj v2 = TREE_OPERAND (TREE_OPERAND (v2, 0), 0); 194238fd1498Szrj } 194338fd1498Szrj gcc_assert (DECL_ASSEMBLER_NAME (v1) 194438fd1498Szrj == DECL_ASSEMBLER_NAME (v2)); 194538fd1498Szrj 194638fd1498Szrj if (DECL_EXTERNAL (v1) && !DECL_EXTERNAL (v2)) 194738fd1498Szrj { 194838fd1498Szrj unsigned int i; 194938fd1498Szrj 195038fd1498Szrj set_type_binfo (val->type, TYPE_BINFO (type)); 195138fd1498Szrj for (i = 0; i < val->types->length (); i++) 195238fd1498Szrj { 195338fd1498Szrj if (TYPE_BINFO ((*val->types)[i]) 195438fd1498Szrj == master_binfo) 195538fd1498Szrj set_type_binfo ((*val->types)[i], TYPE_BINFO (type)); 195638fd1498Szrj } 195738fd1498Szrj BINFO_TYPE (TYPE_BINFO (type)) = val->type; 195838fd1498Szrj } 195938fd1498Szrj else 196038fd1498Szrj set_type_binfo (type, master_binfo); 196138fd1498Szrj } 196238fd1498Szrj return build_bases; 196338fd1498Szrj } 196438fd1498Szrj 196538fd1498Szrj /* Get ODR type hash entry for TYPE. If INSERT is true, create 196638fd1498Szrj possibly new entry. */ 196738fd1498Szrj 196838fd1498Szrj odr_type 196938fd1498Szrj get_odr_type (tree type, bool insert) 197038fd1498Szrj { 197138fd1498Szrj odr_type_d **slot = NULL; 197238fd1498Szrj odr_type_d **vtable_slot = NULL; 197338fd1498Szrj odr_type val = NULL; 197438fd1498Szrj hashval_t hash; 197538fd1498Szrj bool build_bases = false; 197638fd1498Szrj bool insert_to_odr_array = false; 197738fd1498Szrj int base_id = -1; 197838fd1498Szrj 197938fd1498Szrj type = main_odr_variant (type); 198038fd1498Szrj 198138fd1498Szrj gcc_checking_assert (can_be_name_hashed_p (type) 198238fd1498Szrj || can_be_vtable_hashed_p (type)); 198338fd1498Szrj 198438fd1498Szrj /* Lookup entry, first try name hash, fallback to vtable hash. */ 198538fd1498Szrj if (can_be_name_hashed_p (type)) 198638fd1498Szrj { 198738fd1498Szrj hash = hash_odr_name (type); 198838fd1498Szrj slot = odr_hash->find_slot_with_hash (type, hash, 198938fd1498Szrj insert ? INSERT : NO_INSERT); 199038fd1498Szrj } 199138fd1498Szrj if ((!slot || !*slot) && in_lto_p && can_be_vtable_hashed_p (type)) 199238fd1498Szrj { 199338fd1498Szrj hash = hash_odr_vtable (type); 199438fd1498Szrj vtable_slot = odr_vtable_hash->find_slot_with_hash (type, hash, 199538fd1498Szrj insert ? INSERT : NO_INSERT); 199638fd1498Szrj } 199738fd1498Szrj 199838fd1498Szrj if (!slot && !vtable_slot) 199938fd1498Szrj return NULL; 200038fd1498Szrj 200138fd1498Szrj /* See if we already have entry for type. */ 200238fd1498Szrj if ((slot && *slot) || (vtable_slot && *vtable_slot)) 200338fd1498Szrj { 200438fd1498Szrj if (slot && *slot) 200538fd1498Szrj { 200638fd1498Szrj val = *slot; 200738fd1498Szrj if (flag_checking 200838fd1498Szrj && in_lto_p && can_be_vtable_hashed_p (type)) 200938fd1498Szrj { 201038fd1498Szrj hash = hash_odr_vtable (type); 201138fd1498Szrj vtable_slot = odr_vtable_hash->find_slot_with_hash (type, hash, 201238fd1498Szrj NO_INSERT); 201338fd1498Szrj gcc_assert (!vtable_slot || *vtable_slot == *slot); 201438fd1498Szrj vtable_slot = NULL; 201538fd1498Szrj } 201638fd1498Szrj } 201738fd1498Szrj else if (*vtable_slot) 201838fd1498Szrj val = *vtable_slot; 201938fd1498Szrj 202038fd1498Szrj if (val->type != type 202138fd1498Szrj && (!val->types_set || !val->types_set->add (type))) 202238fd1498Szrj { 202338fd1498Szrj gcc_assert (insert); 202438fd1498Szrj /* We have type duplicate, but it may introduce vtable name or 202538fd1498Szrj mangled name; be sure to keep hashes in sync. */ 202638fd1498Szrj if (in_lto_p && can_be_vtable_hashed_p (type) 202738fd1498Szrj && (!vtable_slot || !*vtable_slot)) 202838fd1498Szrj { 202938fd1498Szrj if (!vtable_slot) 203038fd1498Szrj { 203138fd1498Szrj hash = hash_odr_vtable (type); 203238fd1498Szrj vtable_slot = odr_vtable_hash->find_slot_with_hash 203338fd1498Szrj (type, hash, INSERT); 203438fd1498Szrj gcc_checking_assert (!*vtable_slot || *vtable_slot == val); 203538fd1498Szrj } 203638fd1498Szrj *vtable_slot = val; 203738fd1498Szrj } 203838fd1498Szrj if (slot && !*slot) 203938fd1498Szrj *slot = val; 204038fd1498Szrj build_bases = add_type_duplicate (val, type); 204138fd1498Szrj } 204238fd1498Szrj } 204338fd1498Szrj else 204438fd1498Szrj { 204538fd1498Szrj val = ggc_cleared_alloc<odr_type_d> (); 204638fd1498Szrj val->type = type; 204738fd1498Szrj val->bases = vNULL; 204838fd1498Szrj val->derived_types = vNULL; 204938fd1498Szrj if (type_with_linkage_p (type)) 205038fd1498Szrj val->anonymous_namespace = type_in_anonymous_namespace_p (type); 205138fd1498Szrj else 205238fd1498Szrj val->anonymous_namespace = 0; 205338fd1498Szrj build_bases = COMPLETE_TYPE_P (val->type); 205438fd1498Szrj insert_to_odr_array = true; 205538fd1498Szrj if (slot) 205638fd1498Szrj *slot = val; 205738fd1498Szrj if (vtable_slot) 205838fd1498Szrj *vtable_slot = val; 205938fd1498Szrj } 206038fd1498Szrj 206138fd1498Szrj if (build_bases && TREE_CODE (type) == RECORD_TYPE && TYPE_BINFO (type) 206238fd1498Szrj && type_with_linkage_p (type) 206338fd1498Szrj && type == TYPE_MAIN_VARIANT (type)) 206438fd1498Szrj { 206538fd1498Szrj tree binfo = TYPE_BINFO (type); 206638fd1498Szrj unsigned int i; 206738fd1498Szrj 206838fd1498Szrj gcc_assert (BINFO_TYPE (TYPE_BINFO (val->type)) == type); 206938fd1498Szrj 207038fd1498Szrj val->all_derivations_known = type_all_derivations_known_p (type); 207138fd1498Szrj for (i = 0; i < BINFO_N_BASE_BINFOS (binfo); i++) 207238fd1498Szrj /* For now record only polymorphic types. other are 207338fd1498Szrj pointless for devirtualization and we can not precisely 207438fd1498Szrj determine ODR equivalency of these during LTO. */ 207538fd1498Szrj if (polymorphic_type_binfo_p (BINFO_BASE_BINFO (binfo, i))) 207638fd1498Szrj { 207738fd1498Szrj tree base_type= BINFO_TYPE (BINFO_BASE_BINFO (binfo, i)); 207838fd1498Szrj odr_type base = get_odr_type (base_type, true); 207938fd1498Szrj gcc_assert (TYPE_MAIN_VARIANT (base_type) == base_type); 208038fd1498Szrj base->derived_types.safe_push (val); 208138fd1498Szrj val->bases.safe_push (base); 208238fd1498Szrj if (base->id > base_id) 208338fd1498Szrj base_id = base->id; 208438fd1498Szrj } 208538fd1498Szrj } 208638fd1498Szrj /* Ensure that type always appears after bases. */ 208738fd1498Szrj if (insert_to_odr_array) 208838fd1498Szrj { 208938fd1498Szrj if (odr_types_ptr) 209038fd1498Szrj val->id = odr_types.length (); 209138fd1498Szrj vec_safe_push (odr_types_ptr, val); 209238fd1498Szrj } 209338fd1498Szrj else if (base_id > val->id) 209438fd1498Szrj { 209538fd1498Szrj odr_types[val->id] = 0; 209638fd1498Szrj /* Be sure we did not recorded any derived types; these may need 209738fd1498Szrj renumbering too. */ 209838fd1498Szrj gcc_assert (val->derived_types.length() == 0); 209938fd1498Szrj val->id = odr_types.length (); 210038fd1498Szrj vec_safe_push (odr_types_ptr, val); 210138fd1498Szrj } 210238fd1498Szrj return val; 210338fd1498Szrj } 210438fd1498Szrj 210538fd1498Szrj /* Add TYPE od ODR type hash. */ 210638fd1498Szrj 210738fd1498Szrj void 210838fd1498Szrj register_odr_type (tree type) 210938fd1498Szrj { 211038fd1498Szrj if (!odr_hash) 211138fd1498Szrj { 211238fd1498Szrj odr_hash = new odr_hash_type (23); 211338fd1498Szrj if (in_lto_p) 211438fd1498Szrj odr_vtable_hash = new odr_vtable_hash_type (23); 211538fd1498Szrj } 211638fd1498Szrj /* Arrange things to be nicer and insert main variants first. 211738fd1498Szrj ??? fundamental prerecorded types do not have mangled names; this 211838fd1498Szrj makes it possible that non-ODR type is main_odr_variant of ODR type. 211938fd1498Szrj Things may get smoother if LTO FE set mangled name of those types same 212038fd1498Szrj way as C++ FE does. */ 212138fd1498Szrj if (odr_type_p (main_odr_variant (TYPE_MAIN_VARIANT (type))) 212238fd1498Szrj && odr_type_p (TYPE_MAIN_VARIANT (type))) 212338fd1498Szrj get_odr_type (TYPE_MAIN_VARIANT (type), true); 212438fd1498Szrj if (TYPE_MAIN_VARIANT (type) != type && odr_type_p (main_odr_variant (type))) 212538fd1498Szrj get_odr_type (type, true); 212638fd1498Szrj } 212738fd1498Szrj 212838fd1498Szrj /* Return true if type is known to have no derivations. */ 212938fd1498Szrj 213038fd1498Szrj bool 213138fd1498Szrj type_known_to_have_no_derivations_p (tree t) 213238fd1498Szrj { 213338fd1498Szrj return (type_all_derivations_known_p (t) 213438fd1498Szrj && (TYPE_FINAL_P (t) 213538fd1498Szrj || (odr_hash 213638fd1498Szrj && !get_odr_type (t, true)->derived_types.length()))); 213738fd1498Szrj } 213838fd1498Szrj 213938fd1498Szrj /* Dump ODR type T and all its derived types. INDENT specifies indentation for 214038fd1498Szrj recursive printing. */ 214138fd1498Szrj 214238fd1498Szrj static void 214338fd1498Szrj dump_odr_type (FILE *f, odr_type t, int indent=0) 214438fd1498Szrj { 214538fd1498Szrj unsigned int i; 214638fd1498Szrj fprintf (f, "%*s type %i: ", indent * 2, "", t->id); 214738fd1498Szrj print_generic_expr (f, t->type, TDF_SLIM); 214838fd1498Szrj fprintf (f, "%s", t->anonymous_namespace ? " (anonymous namespace)":""); 214938fd1498Szrj fprintf (f, "%s\n", t->all_derivations_known ? " (derivations known)":""); 215038fd1498Szrj if (TYPE_NAME (t->type)) 215138fd1498Szrj { 215238fd1498Szrj /*fprintf (f, "%*s defined at: %s:%i\n", indent * 2, "", 215338fd1498Szrj DECL_SOURCE_FILE (TYPE_NAME (t->type)), 215438fd1498Szrj DECL_SOURCE_LINE (TYPE_NAME (t->type)));*/ 215538fd1498Szrj if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t->type))) 215638fd1498Szrj fprintf (f, "%*s mangled name: %s\n", indent * 2, "", 215738fd1498Szrj IDENTIFIER_POINTER 215838fd1498Szrj (DECL_ASSEMBLER_NAME (TYPE_NAME (t->type)))); 215938fd1498Szrj } 216038fd1498Szrj if (t->bases.length ()) 216138fd1498Szrj { 216238fd1498Szrj fprintf (f, "%*s base odr type ids: ", indent * 2, ""); 216338fd1498Szrj for (i = 0; i < t->bases.length (); i++) 216438fd1498Szrj fprintf (f, " %i", t->bases[i]->id); 216538fd1498Szrj fprintf (f, "\n"); 216638fd1498Szrj } 216738fd1498Szrj if (t->derived_types.length ()) 216838fd1498Szrj { 216938fd1498Szrj fprintf (f, "%*s derived types:\n", indent * 2, ""); 217038fd1498Szrj for (i = 0; i < t->derived_types.length (); i++) 217138fd1498Szrj dump_odr_type (f, t->derived_types[i], indent + 1); 217238fd1498Szrj } 217338fd1498Szrj fprintf (f, "\n"); 217438fd1498Szrj } 217538fd1498Szrj 217638fd1498Szrj /* Dump the type inheritance graph. */ 217738fd1498Szrj 217838fd1498Szrj static void 217938fd1498Szrj dump_type_inheritance_graph (FILE *f) 218038fd1498Szrj { 218138fd1498Szrj unsigned int i; 218238fd1498Szrj if (!odr_types_ptr) 218338fd1498Szrj return; 218438fd1498Szrj fprintf (f, "\n\nType inheritance graph:\n"); 218538fd1498Szrj for (i = 0; i < odr_types.length (); i++) 218638fd1498Szrj { 218738fd1498Szrj if (odr_types[i] && odr_types[i]->bases.length () == 0) 218838fd1498Szrj dump_odr_type (f, odr_types[i]); 218938fd1498Szrj } 219038fd1498Szrj for (i = 0; i < odr_types.length (); i++) 219138fd1498Szrj { 219238fd1498Szrj if (odr_types[i] && odr_types[i]->types && odr_types[i]->types->length ()) 219338fd1498Szrj { 219438fd1498Szrj unsigned int j; 219538fd1498Szrj fprintf (f, "Duplicate tree types for odr type %i\n", i); 219638fd1498Szrj print_node (f, "", odr_types[i]->type, 0); 219738fd1498Szrj for (j = 0; j < odr_types[i]->types->length (); j++) 219838fd1498Szrj { 219938fd1498Szrj tree t; 220038fd1498Szrj fprintf (f, "duplicate #%i\n", j); 220138fd1498Szrj print_node (f, "", (*odr_types[i]->types)[j], 0); 220238fd1498Szrj t = (*odr_types[i]->types)[j]; 220338fd1498Szrj while (TYPE_P (t) && TYPE_CONTEXT (t)) 220438fd1498Szrj { 220538fd1498Szrj t = TYPE_CONTEXT (t); 220638fd1498Szrj print_node (f, "", t, 0); 220738fd1498Szrj } 220838fd1498Szrj putc ('\n',f); 220938fd1498Szrj } 221038fd1498Szrj } 221138fd1498Szrj } 221238fd1498Szrj } 221338fd1498Szrj 221438fd1498Szrj /* Initialize IPA devirt and build inheritance tree graph. */ 221538fd1498Szrj 221638fd1498Szrj void 221738fd1498Szrj build_type_inheritance_graph (void) 221838fd1498Szrj { 221938fd1498Szrj struct symtab_node *n; 222038fd1498Szrj FILE *inheritance_dump_file; 222138fd1498Szrj dump_flags_t flags; 222238fd1498Szrj 222338fd1498Szrj if (odr_hash) 222438fd1498Szrj return; 222538fd1498Szrj timevar_push (TV_IPA_INHERITANCE); 222638fd1498Szrj inheritance_dump_file = dump_begin (TDI_inheritance, &flags); 222738fd1498Szrj odr_hash = new odr_hash_type (23); 222838fd1498Szrj if (in_lto_p) 222938fd1498Szrj odr_vtable_hash = new odr_vtable_hash_type (23); 223038fd1498Szrj 223138fd1498Szrj /* We reconstruct the graph starting of types of all methods seen in the 223238fd1498Szrj unit. */ 223338fd1498Szrj FOR_EACH_SYMBOL (n) 223438fd1498Szrj if (is_a <cgraph_node *> (n) 223538fd1498Szrj && DECL_VIRTUAL_P (n->decl) 223638fd1498Szrj && n->real_symbol_p ()) 223738fd1498Szrj get_odr_type (TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl)), true); 223838fd1498Szrj 223938fd1498Szrj /* Look also for virtual tables of types that do not define any methods. 224038fd1498Szrj 224138fd1498Szrj We need it in a case where class B has virtual base of class A 224238fd1498Szrj re-defining its virtual method and there is class C with no virtual 224338fd1498Szrj methods with B as virtual base. 224438fd1498Szrj 224538fd1498Szrj Here we output B's virtual method in two variant - for non-virtual 224638fd1498Szrj and virtual inheritance. B's virtual table has non-virtual version, 224738fd1498Szrj while C's has virtual. 224838fd1498Szrj 224938fd1498Szrj For this reason we need to know about C in order to include both 225038fd1498Szrj variants of B. More correctly, record_target_from_binfo should 225138fd1498Szrj add both variants of the method when walking B, but we have no 225238fd1498Szrj link in between them. 225338fd1498Szrj 225438fd1498Szrj We rely on fact that either the method is exported and thus we 225538fd1498Szrj assume it is called externally or C is in anonymous namespace and 225638fd1498Szrj thus we will see the vtable. */ 225738fd1498Szrj 225838fd1498Szrj else if (is_a <varpool_node *> (n) 225938fd1498Szrj && DECL_VIRTUAL_P (n->decl) 226038fd1498Szrj && TREE_CODE (DECL_CONTEXT (n->decl)) == RECORD_TYPE 226138fd1498Szrj && TYPE_BINFO (DECL_CONTEXT (n->decl)) 226238fd1498Szrj && polymorphic_type_binfo_p (TYPE_BINFO (DECL_CONTEXT (n->decl)))) 226338fd1498Szrj get_odr_type (TYPE_MAIN_VARIANT (DECL_CONTEXT (n->decl)), true); 226438fd1498Szrj if (inheritance_dump_file) 226538fd1498Szrj { 226638fd1498Szrj dump_type_inheritance_graph (inheritance_dump_file); 226738fd1498Szrj dump_end (TDI_inheritance, inheritance_dump_file); 226838fd1498Szrj } 226938fd1498Szrj timevar_pop (TV_IPA_INHERITANCE); 227038fd1498Szrj } 227138fd1498Szrj 227238fd1498Szrj /* Return true if N has reference from live virtual table 227338fd1498Szrj (and thus can be a destination of polymorphic call). 227438fd1498Szrj Be conservatively correct when callgraph is not built or 227538fd1498Szrj if the method may be referred externally. */ 227638fd1498Szrj 227738fd1498Szrj static bool 227838fd1498Szrj referenced_from_vtable_p (struct cgraph_node *node) 227938fd1498Szrj { 228038fd1498Szrj int i; 228138fd1498Szrj struct ipa_ref *ref; 228238fd1498Szrj bool found = false; 228338fd1498Szrj 228438fd1498Szrj if (node->externally_visible 228538fd1498Szrj || DECL_EXTERNAL (node->decl) 228638fd1498Szrj || node->used_from_other_partition) 228738fd1498Szrj return true; 228838fd1498Szrj 228938fd1498Szrj /* Keep this test constant time. 229038fd1498Szrj It is unlikely this can happen except for the case where speculative 229138fd1498Szrj devirtualization introduced many speculative edges to this node. 229238fd1498Szrj In this case the target is very likely alive anyway. */ 229338fd1498Szrj if (node->ref_list.referring.length () > 100) 229438fd1498Szrj return true; 229538fd1498Szrj 229638fd1498Szrj /* We need references built. */ 229738fd1498Szrj if (symtab->state <= CONSTRUCTION) 229838fd1498Szrj return true; 229938fd1498Szrj 230038fd1498Szrj for (i = 0; node->iterate_referring (i, ref); i++) 230138fd1498Szrj if ((ref->use == IPA_REF_ALIAS 230238fd1498Szrj && referenced_from_vtable_p (dyn_cast<cgraph_node *> (ref->referring))) 230338fd1498Szrj || (ref->use == IPA_REF_ADDR 230438fd1498Szrj && VAR_P (ref->referring->decl) 230538fd1498Szrj && DECL_VIRTUAL_P (ref->referring->decl))) 230638fd1498Szrj { 230738fd1498Szrj found = true; 230838fd1498Szrj break; 230938fd1498Szrj } 231038fd1498Szrj return found; 231138fd1498Szrj } 231238fd1498Szrj 231338fd1498Szrj /* Return if TARGET is cxa_pure_virtual. */ 231438fd1498Szrj 231538fd1498Szrj static bool 231638fd1498Szrj is_cxa_pure_virtual_p (tree target) 231738fd1498Szrj { 231838fd1498Szrj return target && TREE_CODE (TREE_TYPE (target)) != METHOD_TYPE 231938fd1498Szrj && DECL_NAME (target) 232038fd1498Szrj && id_equal (DECL_NAME (target), 232138fd1498Szrj "__cxa_pure_virtual"); 232238fd1498Szrj } 232338fd1498Szrj 232438fd1498Szrj /* If TARGET has associated node, record it in the NODES array. 232538fd1498Szrj CAN_REFER specify if program can refer to the target directly. 232638fd1498Szrj if TARGET is unknown (NULL) or it can not be inserted (for example because 232738fd1498Szrj its body was already removed and there is no way to refer to it), clear 232838fd1498Szrj COMPLETEP. */ 232938fd1498Szrj 233038fd1498Szrj static void 233138fd1498Szrj maybe_record_node (vec <cgraph_node *> &nodes, 233238fd1498Szrj tree target, hash_set<tree> *inserted, 233338fd1498Szrj bool can_refer, 233438fd1498Szrj bool *completep) 233538fd1498Szrj { 233638fd1498Szrj struct cgraph_node *target_node, *alias_target; 233738fd1498Szrj enum availability avail; 233838fd1498Szrj bool pure_virtual = is_cxa_pure_virtual_p (target); 233938fd1498Szrj 234038fd1498Szrj /* __builtin_unreachable do not need to be added into 234138fd1498Szrj list of targets; the runtime effect of calling them is undefined. 234238fd1498Szrj Only "real" virtual methods should be accounted. */ 234338fd1498Szrj if (target && TREE_CODE (TREE_TYPE (target)) != METHOD_TYPE && !pure_virtual) 234438fd1498Szrj return; 234538fd1498Szrj 234638fd1498Szrj if (!can_refer) 234738fd1498Szrj { 234838fd1498Szrj /* The only case when method of anonymous namespace becomes unreferable 234938fd1498Szrj is when we completely optimized it out. */ 235038fd1498Szrj if (flag_ltrans 235138fd1498Szrj || !target 235238fd1498Szrj || !type_in_anonymous_namespace_p (DECL_CONTEXT (target))) 235338fd1498Szrj *completep = false; 235438fd1498Szrj return; 235538fd1498Szrj } 235638fd1498Szrj 235738fd1498Szrj if (!target) 235838fd1498Szrj return; 235938fd1498Szrj 236038fd1498Szrj target_node = cgraph_node::get (target); 236138fd1498Szrj 236238fd1498Szrj /* Prefer alias target over aliases, so we do not get confused by 236338fd1498Szrj fake duplicates. */ 236438fd1498Szrj if (target_node) 236538fd1498Szrj { 236638fd1498Szrj alias_target = target_node->ultimate_alias_target (&avail); 236738fd1498Szrj if (target_node != alias_target 236838fd1498Szrj && avail >= AVAIL_AVAILABLE 236938fd1498Szrj && target_node->get_availability ()) 237038fd1498Szrj target_node = alias_target; 237138fd1498Szrj } 237238fd1498Szrj 237338fd1498Szrj /* Method can only be called by polymorphic call if any 237438fd1498Szrj of vtables referring to it are alive. 237538fd1498Szrj 237638fd1498Szrj While this holds for non-anonymous functions, too, there are 237738fd1498Szrj cases where we want to keep them in the list; for example 237838fd1498Szrj inline functions with -fno-weak are static, but we still 237938fd1498Szrj may devirtualize them when instance comes from other unit. 238038fd1498Szrj The same holds for LTO. 238138fd1498Szrj 238238fd1498Szrj Currently we ignore these functions in speculative devirtualization. 238338fd1498Szrj ??? Maybe it would make sense to be more aggressive for LTO even 238438fd1498Szrj elsewhere. */ 238538fd1498Szrj if (!flag_ltrans 238638fd1498Szrj && !pure_virtual 238738fd1498Szrj && type_in_anonymous_namespace_p (DECL_CONTEXT (target)) 238838fd1498Szrj && (!target_node 238938fd1498Szrj || !referenced_from_vtable_p (target_node))) 239038fd1498Szrj ; 239138fd1498Szrj /* See if TARGET is useful function we can deal with. */ 239238fd1498Szrj else if (target_node != NULL 239338fd1498Szrj && (TREE_PUBLIC (target) 239438fd1498Szrj || DECL_EXTERNAL (target) 239538fd1498Szrj || target_node->definition) 239638fd1498Szrj && target_node->real_symbol_p ()) 239738fd1498Szrj { 239838fd1498Szrj gcc_assert (!target_node->global.inlined_to); 239938fd1498Szrj gcc_assert (target_node->real_symbol_p ()); 240038fd1498Szrj /* When sanitizing, do not assume that __cxa_pure_virtual is not called 240138fd1498Szrj by valid program. */ 240238fd1498Szrj if (flag_sanitize & SANITIZE_UNREACHABLE) 240338fd1498Szrj ; 240438fd1498Szrj /* Only add pure virtual if it is the only possible target. This way 240538fd1498Szrj we will preserve the diagnostics about pure virtual called in many 240638fd1498Szrj cases without disabling optimization in other. */ 240738fd1498Szrj else if (pure_virtual) 240838fd1498Szrj { 240938fd1498Szrj if (nodes.length ()) 241038fd1498Szrj return; 241138fd1498Szrj } 241238fd1498Szrj /* If we found a real target, take away cxa_pure_virtual. */ 241338fd1498Szrj else if (!pure_virtual && nodes.length () == 1 241438fd1498Szrj && is_cxa_pure_virtual_p (nodes[0]->decl)) 241538fd1498Szrj nodes.pop (); 241638fd1498Szrj if (pure_virtual && nodes.length ()) 241738fd1498Szrj return; 241838fd1498Szrj if (!inserted->add (target)) 241938fd1498Szrj { 242038fd1498Szrj cached_polymorphic_call_targets->add (target_node); 242138fd1498Szrj nodes.safe_push (target_node); 242238fd1498Szrj } 242338fd1498Szrj } 242438fd1498Szrj else if (!completep) 242538fd1498Szrj ; 242638fd1498Szrj /* We have definition of __cxa_pure_virtual that is not accessible (it is 242738fd1498Szrj optimized out or partitioned to other unit) so we can not add it. When 242838fd1498Szrj not sanitizing, there is nothing to do. 242938fd1498Szrj Otherwise declare the list incomplete. */ 243038fd1498Szrj else if (pure_virtual) 243138fd1498Szrj { 243238fd1498Szrj if (flag_sanitize & SANITIZE_UNREACHABLE) 243338fd1498Szrj *completep = false; 243438fd1498Szrj } 243538fd1498Szrj else if (flag_ltrans 243638fd1498Szrj || !type_in_anonymous_namespace_p (DECL_CONTEXT (target))) 243738fd1498Szrj *completep = false; 243838fd1498Szrj } 243938fd1498Szrj 244038fd1498Szrj /* See if BINFO's type matches OUTER_TYPE. If so, look up 244138fd1498Szrj BINFO of subtype of OTR_TYPE at OFFSET and in that BINFO find 244238fd1498Szrj method in vtable and insert method to NODES array 244338fd1498Szrj or BASES_TO_CONSIDER if this array is non-NULL. 244438fd1498Szrj Otherwise recurse to base BINFOs. 244538fd1498Szrj This matches what get_binfo_at_offset does, but with offset 244638fd1498Szrj being unknown. 244738fd1498Szrj 244838fd1498Szrj TYPE_BINFOS is a stack of BINFOS of types with defined 244938fd1498Szrj virtual table seen on way from class type to BINFO. 245038fd1498Szrj 245138fd1498Szrj MATCHED_VTABLES tracks virtual tables we already did lookup 245238fd1498Szrj for virtual function in. INSERTED tracks nodes we already 245338fd1498Szrj inserted. 245438fd1498Szrj 245538fd1498Szrj ANONYMOUS is true if BINFO is part of anonymous namespace. 245638fd1498Szrj 245738fd1498Szrj Clear COMPLETEP when we hit unreferable target. 245838fd1498Szrj */ 245938fd1498Szrj 246038fd1498Szrj static void 246138fd1498Szrj record_target_from_binfo (vec <cgraph_node *> &nodes, 246238fd1498Szrj vec <tree> *bases_to_consider, 246338fd1498Szrj tree binfo, 246438fd1498Szrj tree otr_type, 246538fd1498Szrj vec <tree> &type_binfos, 246638fd1498Szrj HOST_WIDE_INT otr_token, 246738fd1498Szrj tree outer_type, 246838fd1498Szrj HOST_WIDE_INT offset, 246938fd1498Szrj hash_set<tree> *inserted, 247038fd1498Szrj hash_set<tree> *matched_vtables, 247138fd1498Szrj bool anonymous, 247238fd1498Szrj bool *completep) 247338fd1498Szrj { 247438fd1498Szrj tree type = BINFO_TYPE (binfo); 247538fd1498Szrj int i; 247638fd1498Szrj tree base_binfo; 247738fd1498Szrj 247838fd1498Szrj 247938fd1498Szrj if (BINFO_VTABLE (binfo)) 248038fd1498Szrj type_binfos.safe_push (binfo); 248138fd1498Szrj if (types_same_for_odr (type, outer_type)) 248238fd1498Szrj { 248338fd1498Szrj int i; 248438fd1498Szrj tree type_binfo = NULL; 248538fd1498Szrj 248638fd1498Szrj /* Look up BINFO with virtual table. For normal types it is always last 248738fd1498Szrj binfo on stack. */ 248838fd1498Szrj for (i = type_binfos.length () - 1; i >= 0; i--) 248938fd1498Szrj if (BINFO_OFFSET (type_binfos[i]) == BINFO_OFFSET (binfo)) 249038fd1498Szrj { 249138fd1498Szrj type_binfo = type_binfos[i]; 249238fd1498Szrj break; 249338fd1498Szrj } 249438fd1498Szrj if (BINFO_VTABLE (binfo)) 249538fd1498Szrj type_binfos.pop (); 249638fd1498Szrj /* If this is duplicated BINFO for base shared by virtual inheritance, 249738fd1498Szrj we may not have its associated vtable. This is not a problem, since 249838fd1498Szrj we will walk it on the other path. */ 249938fd1498Szrj if (!type_binfo) 250038fd1498Szrj return; 250138fd1498Szrj tree inner_binfo = get_binfo_at_offset (type_binfo, 250238fd1498Szrj offset, otr_type); 250338fd1498Szrj if (!inner_binfo) 250438fd1498Szrj { 250538fd1498Szrj gcc_assert (odr_violation_reported); 250638fd1498Szrj return; 250738fd1498Szrj } 250838fd1498Szrj /* For types in anonymous namespace first check if the respective vtable 250938fd1498Szrj is alive. If not, we know the type can't be called. */ 251038fd1498Szrj if (!flag_ltrans && anonymous) 251138fd1498Szrj { 251238fd1498Szrj tree vtable = BINFO_VTABLE (inner_binfo); 251338fd1498Szrj varpool_node *vnode; 251438fd1498Szrj 251538fd1498Szrj if (TREE_CODE (vtable) == POINTER_PLUS_EXPR) 251638fd1498Szrj vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0); 251738fd1498Szrj vnode = varpool_node::get (vtable); 251838fd1498Szrj if (!vnode || !vnode->definition) 251938fd1498Szrj return; 252038fd1498Szrj } 252138fd1498Szrj gcc_assert (inner_binfo); 252238fd1498Szrj if (bases_to_consider 252338fd1498Szrj ? !matched_vtables->contains (BINFO_VTABLE (inner_binfo)) 252438fd1498Szrj : !matched_vtables->add (BINFO_VTABLE (inner_binfo))) 252538fd1498Szrj { 252638fd1498Szrj bool can_refer; 252738fd1498Szrj tree target = gimple_get_virt_method_for_binfo (otr_token, 252838fd1498Szrj inner_binfo, 252938fd1498Szrj &can_refer); 253038fd1498Szrj if (!bases_to_consider) 253138fd1498Szrj maybe_record_node (nodes, target, inserted, can_refer, completep); 253238fd1498Szrj /* Destructors are never called via construction vtables. */ 253338fd1498Szrj else if (!target || !DECL_CXX_DESTRUCTOR_P (target)) 253438fd1498Szrj bases_to_consider->safe_push (target); 253538fd1498Szrj } 253638fd1498Szrj return; 253738fd1498Szrj } 253838fd1498Szrj 253938fd1498Szrj /* Walk bases. */ 254038fd1498Szrj for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) 254138fd1498Szrj /* Walking bases that have no virtual method is pointless exercise. */ 254238fd1498Szrj if (polymorphic_type_binfo_p (base_binfo)) 254338fd1498Szrj record_target_from_binfo (nodes, bases_to_consider, base_binfo, otr_type, 254438fd1498Szrj type_binfos, 254538fd1498Szrj otr_token, outer_type, offset, inserted, 254638fd1498Szrj matched_vtables, anonymous, completep); 254738fd1498Szrj if (BINFO_VTABLE (binfo)) 254838fd1498Szrj type_binfos.pop (); 254938fd1498Szrj } 255038fd1498Szrj 255138fd1498Szrj /* Look up virtual methods matching OTR_TYPE (with OFFSET and OTR_TOKEN) 255238fd1498Szrj of TYPE, insert them to NODES, recurse into derived nodes. 255338fd1498Szrj INSERTED is used to avoid duplicate insertions of methods into NODES. 255438fd1498Szrj MATCHED_VTABLES are used to avoid duplicate walking vtables. 255538fd1498Szrj Clear COMPLETEP if unreferable target is found. 255638fd1498Szrj 255738fd1498Szrj If CONSIDER_CONSTRUCTION is true, record to BASES_TO_CONSIDER 255838fd1498Szrj all cases where BASE_SKIPPED is true (because the base is abstract 255938fd1498Szrj class). */ 256038fd1498Szrj 256138fd1498Szrj static void 256238fd1498Szrj possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes, 256338fd1498Szrj hash_set<tree> *inserted, 256438fd1498Szrj hash_set<tree> *matched_vtables, 256538fd1498Szrj tree otr_type, 256638fd1498Szrj odr_type type, 256738fd1498Szrj HOST_WIDE_INT otr_token, 256838fd1498Szrj tree outer_type, 256938fd1498Szrj HOST_WIDE_INT offset, 257038fd1498Szrj bool *completep, 257138fd1498Szrj vec <tree> &bases_to_consider, 257238fd1498Szrj bool consider_construction) 257338fd1498Szrj { 257438fd1498Szrj tree binfo = TYPE_BINFO (type->type); 257538fd1498Szrj unsigned int i; 257638fd1498Szrj auto_vec <tree, 8> type_binfos; 257738fd1498Szrj bool possibly_instantiated = type_possibly_instantiated_p (type->type); 257838fd1498Szrj 257938fd1498Szrj /* We may need to consider types w/o instances because of possible derived 258038fd1498Szrj types using their methods either directly or via construction vtables. 258138fd1498Szrj We are safe to skip them when all derivations are known, since we will 258238fd1498Szrj handle them later. 258338fd1498Szrj This is done by recording them to BASES_TO_CONSIDER array. */ 258438fd1498Szrj if (possibly_instantiated || consider_construction) 258538fd1498Szrj { 258638fd1498Szrj record_target_from_binfo (nodes, 258738fd1498Szrj (!possibly_instantiated 258838fd1498Szrj && type_all_derivations_known_p (type->type)) 258938fd1498Szrj ? &bases_to_consider : NULL, 259038fd1498Szrj binfo, otr_type, type_binfos, otr_token, 259138fd1498Szrj outer_type, offset, 259238fd1498Szrj inserted, matched_vtables, 259338fd1498Szrj type->anonymous_namespace, completep); 259438fd1498Szrj } 259538fd1498Szrj for (i = 0; i < type->derived_types.length (); i++) 259638fd1498Szrj possible_polymorphic_call_targets_1 (nodes, inserted, 259738fd1498Szrj matched_vtables, 259838fd1498Szrj otr_type, 259938fd1498Szrj type->derived_types[i], 260038fd1498Szrj otr_token, outer_type, offset, completep, 260138fd1498Szrj bases_to_consider, consider_construction); 260238fd1498Szrj } 260338fd1498Szrj 260438fd1498Szrj /* Cache of queries for polymorphic call targets. 260538fd1498Szrj 260638fd1498Szrj Enumerating all call targets may get expensive when there are many 260738fd1498Szrj polymorphic calls in the program, so we memoize all the previous 260838fd1498Szrj queries and avoid duplicated work. */ 260938fd1498Szrj 261038fd1498Szrj struct polymorphic_call_target_d 261138fd1498Szrj { 261238fd1498Szrj HOST_WIDE_INT otr_token; 261338fd1498Szrj ipa_polymorphic_call_context context; 261438fd1498Szrj odr_type type; 261538fd1498Szrj vec <cgraph_node *> targets; 261638fd1498Szrj tree decl_warning; 261738fd1498Szrj int type_warning; 2618*58e805e6Szrj unsigned int n_odr_types; 261938fd1498Szrj bool complete; 262038fd1498Szrj bool speculative; 262138fd1498Szrj }; 262238fd1498Szrj 262338fd1498Szrj /* Polymorphic call target cache helpers. */ 262438fd1498Szrj 262538fd1498Szrj struct polymorphic_call_target_hasher 262638fd1498Szrj : pointer_hash <polymorphic_call_target_d> 262738fd1498Szrj { 262838fd1498Szrj static inline hashval_t hash (const polymorphic_call_target_d *); 262938fd1498Szrj static inline bool equal (const polymorphic_call_target_d *, 263038fd1498Szrj const polymorphic_call_target_d *); 263138fd1498Szrj static inline void remove (polymorphic_call_target_d *); 263238fd1498Szrj }; 263338fd1498Szrj 263438fd1498Szrj /* Return the computed hashcode for ODR_QUERY. */ 263538fd1498Szrj 263638fd1498Szrj inline hashval_t 263738fd1498Szrj polymorphic_call_target_hasher::hash (const polymorphic_call_target_d *odr_query) 263838fd1498Szrj { 263938fd1498Szrj inchash::hash hstate (odr_query->otr_token); 264038fd1498Szrj 264138fd1498Szrj hstate.add_hwi (odr_query->type->id); 264238fd1498Szrj hstate.merge_hash (TYPE_UID (odr_query->context.outer_type)); 264338fd1498Szrj hstate.add_hwi (odr_query->context.offset); 2644*58e805e6Szrj hstate.add_hwi (odr_query->n_odr_types); 264538fd1498Szrj 264638fd1498Szrj if (odr_query->context.speculative_outer_type) 264738fd1498Szrj { 264838fd1498Szrj hstate.merge_hash (TYPE_UID (odr_query->context.speculative_outer_type)); 264938fd1498Szrj hstate.add_hwi (odr_query->context.speculative_offset); 265038fd1498Szrj } 265138fd1498Szrj hstate.add_flag (odr_query->speculative); 265238fd1498Szrj hstate.add_flag (odr_query->context.maybe_in_construction); 265338fd1498Szrj hstate.add_flag (odr_query->context.maybe_derived_type); 265438fd1498Szrj hstate.add_flag (odr_query->context.speculative_maybe_derived_type); 265538fd1498Szrj hstate.commit_flag (); 265638fd1498Szrj return hstate.end (); 265738fd1498Szrj } 265838fd1498Szrj 265938fd1498Szrj /* Compare cache entries T1 and T2. */ 266038fd1498Szrj 266138fd1498Szrj inline bool 266238fd1498Szrj polymorphic_call_target_hasher::equal (const polymorphic_call_target_d *t1, 266338fd1498Szrj const polymorphic_call_target_d *t2) 266438fd1498Szrj { 266538fd1498Szrj return (t1->type == t2->type && t1->otr_token == t2->otr_token 266638fd1498Szrj && t1->speculative == t2->speculative 266738fd1498Szrj && t1->context.offset == t2->context.offset 266838fd1498Szrj && t1->context.speculative_offset == t2->context.speculative_offset 266938fd1498Szrj && t1->context.outer_type == t2->context.outer_type 267038fd1498Szrj && t1->context.speculative_outer_type == t2->context.speculative_outer_type 267138fd1498Szrj && t1->context.maybe_in_construction 267238fd1498Szrj == t2->context.maybe_in_construction 267338fd1498Szrj && t1->context.maybe_derived_type == t2->context.maybe_derived_type 267438fd1498Szrj && (t1->context.speculative_maybe_derived_type 2675*58e805e6Szrj == t2->context.speculative_maybe_derived_type) 2676*58e805e6Szrj /* Adding new type may affect outcome of target search. */ 2677*58e805e6Szrj && t1->n_odr_types == t2->n_odr_types); 267838fd1498Szrj } 267938fd1498Szrj 268038fd1498Szrj /* Remove entry in polymorphic call target cache hash. */ 268138fd1498Szrj 268238fd1498Szrj inline void 268338fd1498Szrj polymorphic_call_target_hasher::remove (polymorphic_call_target_d *v) 268438fd1498Szrj { 268538fd1498Szrj v->targets.release (); 268638fd1498Szrj free (v); 268738fd1498Szrj } 268838fd1498Szrj 268938fd1498Szrj /* Polymorphic call target query cache. */ 269038fd1498Szrj 269138fd1498Szrj typedef hash_table<polymorphic_call_target_hasher> 269238fd1498Szrj polymorphic_call_target_hash_type; 269338fd1498Szrj static polymorphic_call_target_hash_type *polymorphic_call_target_hash; 269438fd1498Szrj 269538fd1498Szrj /* Destroy polymorphic call target query cache. */ 269638fd1498Szrj 269738fd1498Szrj static void 269838fd1498Szrj free_polymorphic_call_targets_hash () 269938fd1498Szrj { 270038fd1498Szrj if (cached_polymorphic_call_targets) 270138fd1498Szrj { 270238fd1498Szrj delete polymorphic_call_target_hash; 270338fd1498Szrj polymorphic_call_target_hash = NULL; 270438fd1498Szrj delete cached_polymorphic_call_targets; 270538fd1498Szrj cached_polymorphic_call_targets = NULL; 270638fd1498Szrj } 270738fd1498Szrj } 270838fd1498Szrj 270938fd1498Szrj /* Force rebuilding type inheritance graph from scratch. 271038fd1498Szrj This is use to make sure that we do not keep references to types 271138fd1498Szrj which was not visible to free_lang_data. */ 271238fd1498Szrj 271338fd1498Szrj void 271438fd1498Szrj rebuild_type_inheritance_graph () 271538fd1498Szrj { 271638fd1498Szrj if (!odr_hash) 271738fd1498Szrj return; 271838fd1498Szrj delete odr_hash; 271938fd1498Szrj if (in_lto_p) 272038fd1498Szrj delete odr_vtable_hash; 272138fd1498Szrj odr_hash = NULL; 272238fd1498Szrj odr_vtable_hash = NULL; 272338fd1498Szrj odr_types_ptr = NULL; 272438fd1498Szrj free_polymorphic_call_targets_hash (); 272538fd1498Szrj } 272638fd1498Szrj 272738fd1498Szrj /* When virtual function is removed, we may need to flush the cache. */ 272838fd1498Szrj 272938fd1498Szrj static void 273038fd1498Szrj devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED) 273138fd1498Szrj { 273238fd1498Szrj if (cached_polymorphic_call_targets 273338fd1498Szrj && cached_polymorphic_call_targets->contains (n)) 273438fd1498Szrj free_polymorphic_call_targets_hash (); 273538fd1498Szrj } 273638fd1498Szrj 273738fd1498Szrj /* Look up base of BINFO that has virtual table VTABLE with OFFSET. */ 273838fd1498Szrj 273938fd1498Szrj tree 274038fd1498Szrj subbinfo_with_vtable_at_offset (tree binfo, unsigned HOST_WIDE_INT offset, 274138fd1498Szrj tree vtable) 274238fd1498Szrj { 274338fd1498Szrj tree v = BINFO_VTABLE (binfo); 274438fd1498Szrj int i; 274538fd1498Szrj tree base_binfo; 274638fd1498Szrj unsigned HOST_WIDE_INT this_offset; 274738fd1498Szrj 274838fd1498Szrj if (v) 274938fd1498Szrj { 275038fd1498Szrj if (!vtable_pointer_value_to_vtable (v, &v, &this_offset)) 275138fd1498Szrj gcc_unreachable (); 275238fd1498Szrj 275338fd1498Szrj if (offset == this_offset 275438fd1498Szrj && DECL_ASSEMBLER_NAME (v) == DECL_ASSEMBLER_NAME (vtable)) 275538fd1498Szrj return binfo; 275638fd1498Szrj } 275738fd1498Szrj 275838fd1498Szrj for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) 275938fd1498Szrj if (polymorphic_type_binfo_p (base_binfo)) 276038fd1498Szrj { 276138fd1498Szrj base_binfo = subbinfo_with_vtable_at_offset (base_binfo, offset, vtable); 276238fd1498Szrj if (base_binfo) 276338fd1498Szrj return base_binfo; 276438fd1498Szrj } 276538fd1498Szrj return NULL; 276638fd1498Szrj } 276738fd1498Szrj 276838fd1498Szrj /* T is known constant value of virtual table pointer. 276938fd1498Szrj Store virtual table to V and its offset to OFFSET. 277038fd1498Szrj Return false if T does not look like virtual table reference. */ 277138fd1498Szrj 277238fd1498Szrj bool 277338fd1498Szrj vtable_pointer_value_to_vtable (const_tree t, tree *v, 277438fd1498Szrj unsigned HOST_WIDE_INT *offset) 277538fd1498Szrj { 277638fd1498Szrj /* We expect &MEM[(void *)&virtual_table + 16B]. 277738fd1498Szrj We obtain object's BINFO from the context of the virtual table. 277838fd1498Szrj This one contains pointer to virtual table represented via 277938fd1498Szrj POINTER_PLUS_EXPR. Verify that this pointer matches what 278038fd1498Szrj we propagated through. 278138fd1498Szrj 278238fd1498Szrj In the case of virtual inheritance, the virtual tables may 278338fd1498Szrj be nested, i.e. the offset may be different from 16 and we may 278438fd1498Szrj need to dive into the type representation. */ 278538fd1498Szrj if (TREE_CODE (t) == ADDR_EXPR 278638fd1498Szrj && TREE_CODE (TREE_OPERAND (t, 0)) == MEM_REF 278738fd1498Szrj && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)) == ADDR_EXPR 278838fd1498Szrj && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == INTEGER_CST 278938fd1498Szrj && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 0), 0), 0)) 279038fd1498Szrj == VAR_DECL) 279138fd1498Szrj && DECL_VIRTUAL_P (TREE_OPERAND (TREE_OPERAND 279238fd1498Szrj (TREE_OPERAND (t, 0), 0), 0))) 279338fd1498Szrj { 279438fd1498Szrj *v = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 0), 0), 0); 279538fd1498Szrj *offset = tree_to_uhwi (TREE_OPERAND (TREE_OPERAND (t, 0), 1)); 279638fd1498Szrj return true; 279738fd1498Szrj } 279838fd1498Szrj 279938fd1498Szrj /* Alternative representation, used by C++ frontend is POINTER_PLUS_EXPR. 280038fd1498Szrj We need to handle it when T comes from static variable initializer or 280138fd1498Szrj BINFO. */ 280238fd1498Szrj if (TREE_CODE (t) == POINTER_PLUS_EXPR) 280338fd1498Szrj { 280438fd1498Szrj *offset = tree_to_uhwi (TREE_OPERAND (t, 1)); 280538fd1498Szrj t = TREE_OPERAND (t, 0); 280638fd1498Szrj } 280738fd1498Szrj else 280838fd1498Szrj *offset = 0; 280938fd1498Szrj 281038fd1498Szrj if (TREE_CODE (t) != ADDR_EXPR) 281138fd1498Szrj return false; 281238fd1498Szrj *v = TREE_OPERAND (t, 0); 281338fd1498Szrj return true; 281438fd1498Szrj } 281538fd1498Szrj 281638fd1498Szrj /* T is known constant value of virtual table pointer. Return BINFO of the 281738fd1498Szrj instance type. */ 281838fd1498Szrj 281938fd1498Szrj tree 282038fd1498Szrj vtable_pointer_value_to_binfo (const_tree t) 282138fd1498Szrj { 282238fd1498Szrj tree vtable; 282338fd1498Szrj unsigned HOST_WIDE_INT offset; 282438fd1498Szrj 282538fd1498Szrj if (!vtable_pointer_value_to_vtable (t, &vtable, &offset)) 282638fd1498Szrj return NULL_TREE; 282738fd1498Szrj 282838fd1498Szrj /* FIXME: for stores of construction vtables we return NULL, 282938fd1498Szrj because we do not have BINFO for those. Eventually we should fix 283038fd1498Szrj our representation to allow this case to be handled, too. 283138fd1498Szrj In the case we see store of BINFO we however may assume 283238fd1498Szrj that standard folding will be able to cope with it. */ 283338fd1498Szrj return subbinfo_with_vtable_at_offset (TYPE_BINFO (DECL_CONTEXT (vtable)), 283438fd1498Szrj offset, vtable); 283538fd1498Szrj } 283638fd1498Szrj 283738fd1498Szrj /* Walk bases of OUTER_TYPE that contain OTR_TYPE at OFFSET. 283838fd1498Szrj Look up their respective virtual methods for OTR_TOKEN and OTR_TYPE 283938fd1498Szrj and insert them in NODES. 284038fd1498Szrj 284138fd1498Szrj MATCHED_VTABLES and INSERTED is used to avoid duplicated work. */ 284238fd1498Szrj 284338fd1498Szrj static void 284438fd1498Szrj record_targets_from_bases (tree otr_type, 284538fd1498Szrj HOST_WIDE_INT otr_token, 284638fd1498Szrj tree outer_type, 284738fd1498Szrj HOST_WIDE_INT offset, 284838fd1498Szrj vec <cgraph_node *> &nodes, 284938fd1498Szrj hash_set<tree> *inserted, 285038fd1498Szrj hash_set<tree> *matched_vtables, 285138fd1498Szrj bool *completep) 285238fd1498Szrj { 285338fd1498Szrj while (true) 285438fd1498Szrj { 285538fd1498Szrj HOST_WIDE_INT pos, size; 285638fd1498Szrj tree base_binfo; 285738fd1498Szrj tree fld; 285838fd1498Szrj 285938fd1498Szrj if (types_same_for_odr (outer_type, otr_type)) 286038fd1498Szrj return; 286138fd1498Szrj 286238fd1498Szrj for (fld = TYPE_FIELDS (outer_type); fld; fld = DECL_CHAIN (fld)) 286338fd1498Szrj { 286438fd1498Szrj if (TREE_CODE (fld) != FIELD_DECL) 286538fd1498Szrj continue; 286638fd1498Szrj 286738fd1498Szrj pos = int_bit_position (fld); 286838fd1498Szrj size = tree_to_shwi (DECL_SIZE (fld)); 286938fd1498Szrj if (pos <= offset && (pos + size) > offset 287038fd1498Szrj /* Do not get confused by zero sized bases. */ 287138fd1498Szrj && polymorphic_type_binfo_p (TYPE_BINFO (TREE_TYPE (fld)))) 287238fd1498Szrj break; 287338fd1498Szrj } 287438fd1498Szrj /* Within a class type we should always find corresponding fields. */ 287538fd1498Szrj gcc_assert (fld && TREE_CODE (TREE_TYPE (fld)) == RECORD_TYPE); 287638fd1498Szrj 287738fd1498Szrj /* Nonbase types should have been stripped by outer_class_type. */ 287838fd1498Szrj gcc_assert (DECL_ARTIFICIAL (fld)); 287938fd1498Szrj 288038fd1498Szrj outer_type = TREE_TYPE (fld); 288138fd1498Szrj offset -= pos; 288238fd1498Szrj 288338fd1498Szrj base_binfo = get_binfo_at_offset (TYPE_BINFO (outer_type), 288438fd1498Szrj offset, otr_type); 288538fd1498Szrj if (!base_binfo) 288638fd1498Szrj { 288738fd1498Szrj gcc_assert (odr_violation_reported); 288838fd1498Szrj return; 288938fd1498Szrj } 289038fd1498Szrj gcc_assert (base_binfo); 289138fd1498Szrj if (!matched_vtables->add (BINFO_VTABLE (base_binfo))) 289238fd1498Szrj { 289338fd1498Szrj bool can_refer; 289438fd1498Szrj tree target = gimple_get_virt_method_for_binfo (otr_token, 289538fd1498Szrj base_binfo, 289638fd1498Szrj &can_refer); 289738fd1498Szrj if (!target || ! DECL_CXX_DESTRUCTOR_P (target)) 289838fd1498Szrj maybe_record_node (nodes, target, inserted, can_refer, completep); 289938fd1498Szrj matched_vtables->add (BINFO_VTABLE (base_binfo)); 290038fd1498Szrj } 290138fd1498Szrj } 290238fd1498Szrj } 290338fd1498Szrj 290438fd1498Szrj /* When virtual table is removed, we may need to flush the cache. */ 290538fd1498Szrj 290638fd1498Szrj static void 290738fd1498Szrj devirt_variable_node_removal_hook (varpool_node *n, 290838fd1498Szrj void *d ATTRIBUTE_UNUSED) 290938fd1498Szrj { 291038fd1498Szrj if (cached_polymorphic_call_targets 291138fd1498Szrj && DECL_VIRTUAL_P (n->decl) 291238fd1498Szrj && type_in_anonymous_namespace_p (DECL_CONTEXT (n->decl))) 291338fd1498Szrj free_polymorphic_call_targets_hash (); 291438fd1498Szrj } 291538fd1498Szrj 291638fd1498Szrj /* Record about how many calls would benefit from given type to be final. */ 291738fd1498Szrj 291838fd1498Szrj struct odr_type_warn_count 291938fd1498Szrj { 292038fd1498Szrj tree type; 292138fd1498Szrj int count; 292238fd1498Szrj profile_count dyn_count; 292338fd1498Szrj }; 292438fd1498Szrj 292538fd1498Szrj /* Record about how many calls would benefit from given method to be final. */ 292638fd1498Szrj 292738fd1498Szrj struct decl_warn_count 292838fd1498Szrj { 292938fd1498Szrj tree decl; 293038fd1498Szrj int count; 293138fd1498Szrj profile_count dyn_count; 293238fd1498Szrj }; 293338fd1498Szrj 293438fd1498Szrj /* Information about type and decl warnings. */ 293538fd1498Szrj 293638fd1498Szrj struct final_warning_record 293738fd1498Szrj { 293838fd1498Szrj /* If needed grow type_warnings vector and initialize new decl_warn_count 293938fd1498Szrj to have dyn_count set to profile_count::zero (). */ 294038fd1498Szrj void grow_type_warnings (unsigned newlen); 294138fd1498Szrj 294238fd1498Szrj profile_count dyn_count; 294338fd1498Szrj auto_vec<odr_type_warn_count> type_warnings; 294438fd1498Szrj hash_map<tree, decl_warn_count> decl_warnings; 294538fd1498Szrj }; 294638fd1498Szrj 294738fd1498Szrj void 294838fd1498Szrj final_warning_record::grow_type_warnings (unsigned newlen) 294938fd1498Szrj { 295038fd1498Szrj unsigned len = type_warnings.length (); 295138fd1498Szrj if (newlen > len) 295238fd1498Szrj { 295338fd1498Szrj type_warnings.safe_grow_cleared (newlen); 295438fd1498Szrj for (unsigned i = len; i < newlen; i++) 295538fd1498Szrj type_warnings[i].dyn_count = profile_count::zero (); 295638fd1498Szrj } 295738fd1498Szrj } 295838fd1498Szrj 295938fd1498Szrj struct final_warning_record *final_warning_records; 296038fd1498Szrj 296138fd1498Szrj /* Return vector containing possible targets of polymorphic call of type 296238fd1498Szrj OTR_TYPE calling method OTR_TOKEN within type of OTR_OUTER_TYPE and OFFSET. 296338fd1498Szrj If INCLUDE_BASES is true, walk also base types of OUTER_TYPES containing 296438fd1498Szrj OTR_TYPE and include their virtual method. This is useful for types 296538fd1498Szrj possibly in construction or destruction where the virtual table may 296638fd1498Szrj temporarily change to one of base types. INCLUDE_DERIVER_TYPES make 296738fd1498Szrj us to walk the inheritance graph for all derivations. 296838fd1498Szrj 296938fd1498Szrj If COMPLETEP is non-NULL, store true if the list is complete. 297038fd1498Szrj CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry 297138fd1498Szrj in the target cache. If user needs to visit every target list 297238fd1498Szrj just once, it can memoize them. 297338fd1498Szrj 297438fd1498Szrj If SPECULATIVE is set, the list will not contain targets that 297538fd1498Szrj are not speculatively taken. 297638fd1498Szrj 297738fd1498Szrj Returned vector is placed into cache. It is NOT caller's responsibility 297838fd1498Szrj to free it. The vector can be freed on cgraph_remove_node call if 297938fd1498Szrj the particular node is a virtual function present in the cache. */ 298038fd1498Szrj 298138fd1498Szrj vec <cgraph_node *> 298238fd1498Szrj possible_polymorphic_call_targets (tree otr_type, 298338fd1498Szrj HOST_WIDE_INT otr_token, 298438fd1498Szrj ipa_polymorphic_call_context context, 298538fd1498Szrj bool *completep, 298638fd1498Szrj void **cache_token, 298738fd1498Szrj bool speculative) 298838fd1498Szrj { 298938fd1498Szrj static struct cgraph_node_hook_list *node_removal_hook_holder; 299038fd1498Szrj vec <cgraph_node *> nodes = vNULL; 299138fd1498Szrj auto_vec <tree, 8> bases_to_consider; 299238fd1498Szrj odr_type type, outer_type; 299338fd1498Szrj polymorphic_call_target_d key; 299438fd1498Szrj polymorphic_call_target_d **slot; 299538fd1498Szrj unsigned int i; 299638fd1498Szrj tree binfo, target; 299738fd1498Szrj bool complete; 299838fd1498Szrj bool can_refer = false; 299938fd1498Szrj bool skipped = false; 300038fd1498Szrj 300138fd1498Szrj otr_type = TYPE_MAIN_VARIANT (otr_type); 300238fd1498Szrj 300338fd1498Szrj /* If ODR is not initialized or the context is invalid, return empty 300438fd1498Szrj incomplete list. */ 300538fd1498Szrj if (!odr_hash || context.invalid || !TYPE_BINFO (otr_type)) 300638fd1498Szrj { 300738fd1498Szrj if (completep) 300838fd1498Szrj *completep = context.invalid; 300938fd1498Szrj if (cache_token) 301038fd1498Szrj *cache_token = NULL; 301138fd1498Szrj return nodes; 301238fd1498Szrj } 301338fd1498Szrj 301438fd1498Szrj /* Do not bother to compute speculative info when user do not asks for it. */ 301538fd1498Szrj if (!speculative || !context.speculative_outer_type) 301638fd1498Szrj context.clear_speculation (); 301738fd1498Szrj 301838fd1498Szrj type = get_odr_type (otr_type, true); 301938fd1498Szrj 302038fd1498Szrj /* Recording type variants would waste results cache. */ 302138fd1498Szrj gcc_assert (!context.outer_type 302238fd1498Szrj || TYPE_MAIN_VARIANT (context.outer_type) == context.outer_type); 302338fd1498Szrj 302438fd1498Szrj /* Look up the outer class type we want to walk. 302538fd1498Szrj If we fail to do so, the context is invalid. */ 302638fd1498Szrj if ((context.outer_type || context.speculative_outer_type) 302738fd1498Szrj && !context.restrict_to_inner_class (otr_type)) 302838fd1498Szrj { 302938fd1498Szrj if (completep) 303038fd1498Szrj *completep = true; 303138fd1498Szrj if (cache_token) 303238fd1498Szrj *cache_token = NULL; 303338fd1498Szrj return nodes; 303438fd1498Szrj } 303538fd1498Szrj gcc_assert (!context.invalid); 303638fd1498Szrj 303738fd1498Szrj /* Check that restrict_to_inner_class kept the main variant. */ 303838fd1498Szrj gcc_assert (!context.outer_type 303938fd1498Szrj || TYPE_MAIN_VARIANT (context.outer_type) == context.outer_type); 304038fd1498Szrj 304138fd1498Szrj /* We canonicalize our query, so we do not need extra hashtable entries. */ 304238fd1498Szrj 304338fd1498Szrj /* Without outer type, we have no use for offset. Just do the 304438fd1498Szrj basic search from inner type. */ 304538fd1498Szrj if (!context.outer_type) 304638fd1498Szrj context.clear_outer_type (otr_type); 304738fd1498Szrj /* We need to update our hierarchy if the type does not exist. */ 304838fd1498Szrj outer_type = get_odr_type (context.outer_type, true); 304938fd1498Szrj /* If the type is complete, there are no derivations. */ 305038fd1498Szrj if (TYPE_FINAL_P (outer_type->type)) 305138fd1498Szrj context.maybe_derived_type = false; 305238fd1498Szrj 305338fd1498Szrj /* Initialize query cache. */ 305438fd1498Szrj if (!cached_polymorphic_call_targets) 305538fd1498Szrj { 305638fd1498Szrj cached_polymorphic_call_targets = new hash_set<cgraph_node *>; 305738fd1498Szrj polymorphic_call_target_hash 305838fd1498Szrj = new polymorphic_call_target_hash_type (23); 305938fd1498Szrj if (!node_removal_hook_holder) 306038fd1498Szrj { 306138fd1498Szrj node_removal_hook_holder = 306238fd1498Szrj symtab->add_cgraph_removal_hook (&devirt_node_removal_hook, NULL); 306338fd1498Szrj symtab->add_varpool_removal_hook (&devirt_variable_node_removal_hook, 306438fd1498Szrj NULL); 306538fd1498Szrj } 306638fd1498Szrj } 306738fd1498Szrj 306838fd1498Szrj if (in_lto_p) 306938fd1498Szrj { 307038fd1498Szrj if (context.outer_type != otr_type) 307138fd1498Szrj context.outer_type 307238fd1498Szrj = get_odr_type (context.outer_type, true)->type; 307338fd1498Szrj if (context.speculative_outer_type) 307438fd1498Szrj context.speculative_outer_type 307538fd1498Szrj = get_odr_type (context.speculative_outer_type, true)->type; 307638fd1498Szrj } 307738fd1498Szrj 307838fd1498Szrj /* Look up cached answer. */ 307938fd1498Szrj key.type = type; 308038fd1498Szrj key.otr_token = otr_token; 308138fd1498Szrj key.speculative = speculative; 308238fd1498Szrj key.context = context; 3083*58e805e6Szrj key.n_odr_types = odr_types.length (); 308438fd1498Szrj slot = polymorphic_call_target_hash->find_slot (&key, INSERT); 308538fd1498Szrj if (cache_token) 308638fd1498Szrj *cache_token = (void *)*slot; 308738fd1498Szrj if (*slot) 308838fd1498Szrj { 308938fd1498Szrj if (completep) 309038fd1498Szrj *completep = (*slot)->complete; 309138fd1498Szrj if ((*slot)->type_warning && final_warning_records) 309238fd1498Szrj { 309338fd1498Szrj final_warning_records->type_warnings[(*slot)->type_warning - 1].count++; 309438fd1498Szrj if (!final_warning_records->type_warnings 309538fd1498Szrj [(*slot)->type_warning - 1].dyn_count.initialized_p ()) 309638fd1498Szrj final_warning_records->type_warnings 309738fd1498Szrj [(*slot)->type_warning - 1].dyn_count = profile_count::zero (); 309838fd1498Szrj if (final_warning_records->dyn_count > 0) 309938fd1498Szrj final_warning_records->type_warnings[(*slot)->type_warning - 1].dyn_count 310038fd1498Szrj = final_warning_records->type_warnings[(*slot)->type_warning - 1].dyn_count 310138fd1498Szrj + final_warning_records->dyn_count; 310238fd1498Szrj } 310338fd1498Szrj if (!speculative && (*slot)->decl_warning && final_warning_records) 310438fd1498Szrj { 310538fd1498Szrj struct decl_warn_count *c = 310638fd1498Szrj final_warning_records->decl_warnings.get ((*slot)->decl_warning); 310738fd1498Szrj c->count++; 310838fd1498Szrj if (final_warning_records->dyn_count > 0) 310938fd1498Szrj c->dyn_count += final_warning_records->dyn_count; 311038fd1498Szrj } 311138fd1498Szrj return (*slot)->targets; 311238fd1498Szrj } 311338fd1498Szrj 311438fd1498Szrj complete = true; 311538fd1498Szrj 311638fd1498Szrj /* Do actual search. */ 311738fd1498Szrj timevar_push (TV_IPA_VIRTUAL_CALL); 311838fd1498Szrj *slot = XCNEW (polymorphic_call_target_d); 311938fd1498Szrj if (cache_token) 312038fd1498Szrj *cache_token = (void *)*slot; 312138fd1498Szrj (*slot)->type = type; 312238fd1498Szrj (*slot)->otr_token = otr_token; 312338fd1498Szrj (*slot)->context = context; 312438fd1498Szrj (*slot)->speculative = speculative; 312538fd1498Szrj 312638fd1498Szrj hash_set<tree> inserted; 312738fd1498Szrj hash_set<tree> matched_vtables; 312838fd1498Szrj 312938fd1498Szrj /* First insert targets we speculatively identified as likely. */ 313038fd1498Szrj if (context.speculative_outer_type) 313138fd1498Szrj { 313238fd1498Szrj odr_type speculative_outer_type; 313338fd1498Szrj bool speculation_complete = true; 313438fd1498Szrj 313538fd1498Szrj /* First insert target from type itself and check if it may have 313638fd1498Szrj derived types. */ 313738fd1498Szrj speculative_outer_type = get_odr_type (context.speculative_outer_type, true); 313838fd1498Szrj if (TYPE_FINAL_P (speculative_outer_type->type)) 313938fd1498Szrj context.speculative_maybe_derived_type = false; 314038fd1498Szrj binfo = get_binfo_at_offset (TYPE_BINFO (speculative_outer_type->type), 314138fd1498Szrj context.speculative_offset, otr_type); 314238fd1498Szrj if (binfo) 314338fd1498Szrj target = gimple_get_virt_method_for_binfo (otr_token, binfo, 314438fd1498Szrj &can_refer); 314538fd1498Szrj else 314638fd1498Szrj target = NULL; 314738fd1498Szrj 314838fd1498Szrj /* In the case we get complete method, we don't need 314938fd1498Szrj to walk derivations. */ 315038fd1498Szrj if (target && DECL_FINAL_P (target)) 315138fd1498Szrj context.speculative_maybe_derived_type = false; 315238fd1498Szrj if (type_possibly_instantiated_p (speculative_outer_type->type)) 315338fd1498Szrj maybe_record_node (nodes, target, &inserted, can_refer, &speculation_complete); 315438fd1498Szrj if (binfo) 315538fd1498Szrj matched_vtables.add (BINFO_VTABLE (binfo)); 315638fd1498Szrj 315738fd1498Szrj 315838fd1498Szrj /* Next walk recursively all derived types. */ 315938fd1498Szrj if (context.speculative_maybe_derived_type) 316038fd1498Szrj for (i = 0; i < speculative_outer_type->derived_types.length(); i++) 316138fd1498Szrj possible_polymorphic_call_targets_1 (nodes, &inserted, 316238fd1498Szrj &matched_vtables, 316338fd1498Szrj otr_type, 316438fd1498Szrj speculative_outer_type->derived_types[i], 316538fd1498Szrj otr_token, speculative_outer_type->type, 316638fd1498Szrj context.speculative_offset, 316738fd1498Szrj &speculation_complete, 316838fd1498Szrj bases_to_consider, 316938fd1498Szrj false); 317038fd1498Szrj } 317138fd1498Szrj 317238fd1498Szrj if (!speculative || !nodes.length ()) 317338fd1498Szrj { 317438fd1498Szrj /* First see virtual method of type itself. */ 317538fd1498Szrj binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type), 317638fd1498Szrj context.offset, otr_type); 317738fd1498Szrj if (binfo) 317838fd1498Szrj target = gimple_get_virt_method_for_binfo (otr_token, binfo, 317938fd1498Szrj &can_refer); 318038fd1498Szrj else 318138fd1498Szrj { 318238fd1498Szrj gcc_assert (odr_violation_reported); 318338fd1498Szrj target = NULL; 318438fd1498Szrj } 318538fd1498Szrj 318638fd1498Szrj /* Destructors are never called through construction virtual tables, 318738fd1498Szrj because the type is always known. */ 318838fd1498Szrj if (target && DECL_CXX_DESTRUCTOR_P (target)) 318938fd1498Szrj context.maybe_in_construction = false; 319038fd1498Szrj 319138fd1498Szrj if (target) 319238fd1498Szrj { 319338fd1498Szrj /* In the case we get complete method, we don't need 319438fd1498Szrj to walk derivations. */ 319538fd1498Szrj if (DECL_FINAL_P (target)) 319638fd1498Szrj context.maybe_derived_type = false; 319738fd1498Szrj } 319838fd1498Szrj 319938fd1498Szrj /* If OUTER_TYPE is abstract, we know we are not seeing its instance. */ 320038fd1498Szrj if (type_possibly_instantiated_p (outer_type->type)) 320138fd1498Szrj maybe_record_node (nodes, target, &inserted, can_refer, &complete); 320238fd1498Szrj else 320338fd1498Szrj skipped = true; 320438fd1498Szrj 320538fd1498Szrj if (binfo) 320638fd1498Szrj matched_vtables.add (BINFO_VTABLE (binfo)); 320738fd1498Szrj 320838fd1498Szrj /* Next walk recursively all derived types. */ 320938fd1498Szrj if (context.maybe_derived_type) 321038fd1498Szrj { 321138fd1498Szrj for (i = 0; i < outer_type->derived_types.length(); i++) 321238fd1498Szrj possible_polymorphic_call_targets_1 (nodes, &inserted, 321338fd1498Szrj &matched_vtables, 321438fd1498Szrj otr_type, 321538fd1498Szrj outer_type->derived_types[i], 321638fd1498Szrj otr_token, outer_type->type, 321738fd1498Szrj context.offset, &complete, 321838fd1498Szrj bases_to_consider, 321938fd1498Szrj context.maybe_in_construction); 322038fd1498Szrj 322138fd1498Szrj if (!outer_type->all_derivations_known) 322238fd1498Szrj { 322338fd1498Szrj if (!speculative && final_warning_records 322438fd1498Szrj && nodes.length () == 1 322538fd1498Szrj && TREE_CODE (TREE_TYPE (nodes[0]->decl)) == METHOD_TYPE) 322638fd1498Szrj { 322738fd1498Szrj if (complete 322838fd1498Szrj && warn_suggest_final_types 322938fd1498Szrj && !outer_type->derived_types.length ()) 323038fd1498Szrj { 323138fd1498Szrj final_warning_records->grow_type_warnings 323238fd1498Szrj (outer_type->id); 323338fd1498Szrj final_warning_records->type_warnings[outer_type->id].count++; 323438fd1498Szrj if (!final_warning_records->type_warnings 323538fd1498Szrj [outer_type->id].dyn_count.initialized_p ()) 323638fd1498Szrj final_warning_records->type_warnings 323738fd1498Szrj [outer_type->id].dyn_count = profile_count::zero (); 323838fd1498Szrj final_warning_records->type_warnings[outer_type->id].dyn_count 323938fd1498Szrj += final_warning_records->dyn_count; 324038fd1498Szrj final_warning_records->type_warnings[outer_type->id].type 324138fd1498Szrj = outer_type->type; 324238fd1498Szrj (*slot)->type_warning = outer_type->id + 1; 324338fd1498Szrj } 324438fd1498Szrj if (complete 324538fd1498Szrj && warn_suggest_final_methods 324638fd1498Szrj && types_same_for_odr (DECL_CONTEXT (nodes[0]->decl), 324738fd1498Szrj outer_type->type)) 324838fd1498Szrj { 324938fd1498Szrj bool existed; 325038fd1498Szrj struct decl_warn_count &c = 325138fd1498Szrj final_warning_records->decl_warnings.get_or_insert 325238fd1498Szrj (nodes[0]->decl, &existed); 325338fd1498Szrj 325438fd1498Szrj if (existed) 325538fd1498Szrj { 325638fd1498Szrj c.count++; 325738fd1498Szrj c.dyn_count += final_warning_records->dyn_count; 325838fd1498Szrj } 325938fd1498Szrj else 326038fd1498Szrj { 326138fd1498Szrj c.count = 1; 326238fd1498Szrj c.dyn_count = final_warning_records->dyn_count; 326338fd1498Szrj c.decl = nodes[0]->decl; 326438fd1498Szrj } 326538fd1498Szrj (*slot)->decl_warning = nodes[0]->decl; 326638fd1498Szrj } 326738fd1498Szrj } 326838fd1498Szrj complete = false; 326938fd1498Szrj } 327038fd1498Szrj } 327138fd1498Szrj 327238fd1498Szrj if (!speculative) 327338fd1498Szrj { 327438fd1498Szrj /* Destructors are never called through construction virtual tables, 327538fd1498Szrj because the type is always known. One of entries may be 327638fd1498Szrj cxa_pure_virtual so look to at least two of them. */ 327738fd1498Szrj if (context.maybe_in_construction) 327838fd1498Szrj for (i =0 ; i < MIN (nodes.length (), 2); i++) 327938fd1498Szrj if (DECL_CXX_DESTRUCTOR_P (nodes[i]->decl)) 328038fd1498Szrj context.maybe_in_construction = false; 328138fd1498Szrj if (context.maybe_in_construction) 328238fd1498Szrj { 328338fd1498Szrj if (type != outer_type 328438fd1498Szrj && (!skipped 328538fd1498Szrj || (context.maybe_derived_type 328638fd1498Szrj && !type_all_derivations_known_p (outer_type->type)))) 328738fd1498Szrj record_targets_from_bases (otr_type, otr_token, outer_type->type, 328838fd1498Szrj context.offset, nodes, &inserted, 328938fd1498Szrj &matched_vtables, &complete); 329038fd1498Szrj if (skipped) 329138fd1498Szrj maybe_record_node (nodes, target, &inserted, can_refer, &complete); 329238fd1498Szrj for (i = 0; i < bases_to_consider.length(); i++) 329338fd1498Szrj maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete); 329438fd1498Szrj } 329538fd1498Szrj } 329638fd1498Szrj } 329738fd1498Szrj 329838fd1498Szrj (*slot)->targets = nodes; 329938fd1498Szrj (*slot)->complete = complete; 3300*58e805e6Szrj (*slot)->n_odr_types = odr_types.length (); 330138fd1498Szrj if (completep) 330238fd1498Szrj *completep = complete; 330338fd1498Szrj 330438fd1498Szrj timevar_pop (TV_IPA_VIRTUAL_CALL); 330538fd1498Szrj return nodes; 330638fd1498Szrj } 330738fd1498Szrj 330838fd1498Szrj bool 330938fd1498Szrj add_decl_warning (const tree &key ATTRIBUTE_UNUSED, const decl_warn_count &value, 331038fd1498Szrj vec<const decl_warn_count*> *vec) 331138fd1498Szrj { 331238fd1498Szrj vec->safe_push (&value); 331338fd1498Szrj return true; 331438fd1498Szrj } 331538fd1498Szrj 331638fd1498Szrj /* Dump target list TARGETS into FILE. */ 331738fd1498Szrj 331838fd1498Szrj static void 331938fd1498Szrj dump_targets (FILE *f, vec <cgraph_node *> targets) 332038fd1498Szrj { 332138fd1498Szrj unsigned int i; 332238fd1498Szrj 332338fd1498Szrj for (i = 0; i < targets.length (); i++) 332438fd1498Szrj { 332538fd1498Szrj char *name = NULL; 332638fd1498Szrj if (in_lto_p) 332738fd1498Szrj name = cplus_demangle_v3 (targets[i]->asm_name (), 0); 332838fd1498Szrj fprintf (f, " %s/%i", name ? name : targets[i]->name (), 332938fd1498Szrj targets[i]->order); 333038fd1498Szrj if (in_lto_p) 333138fd1498Szrj free (name); 333238fd1498Szrj if (!targets[i]->definition) 333338fd1498Szrj fprintf (f, " (no definition%s)", 333438fd1498Szrj DECL_DECLARED_INLINE_P (targets[i]->decl) 333538fd1498Szrj ? " inline" : ""); 333638fd1498Szrj } 333738fd1498Szrj fprintf (f, "\n"); 333838fd1498Szrj } 333938fd1498Szrj 334038fd1498Szrj /* Dump all possible targets of a polymorphic call. */ 334138fd1498Szrj 334238fd1498Szrj void 334338fd1498Szrj dump_possible_polymorphic_call_targets (FILE *f, 334438fd1498Szrj tree otr_type, 334538fd1498Szrj HOST_WIDE_INT otr_token, 334638fd1498Szrj const ipa_polymorphic_call_context &ctx) 334738fd1498Szrj { 334838fd1498Szrj vec <cgraph_node *> targets; 334938fd1498Szrj bool final; 335038fd1498Szrj odr_type type = get_odr_type (TYPE_MAIN_VARIANT (otr_type), false); 335138fd1498Szrj unsigned int len; 335238fd1498Szrj 335338fd1498Szrj if (!type) 335438fd1498Szrj return; 335538fd1498Szrj targets = possible_polymorphic_call_targets (otr_type, otr_token, 335638fd1498Szrj ctx, 335738fd1498Szrj &final, NULL, false); 335838fd1498Szrj fprintf (f, " Targets of polymorphic call of type %i:", type->id); 335938fd1498Szrj print_generic_expr (f, type->type, TDF_SLIM); 336038fd1498Szrj fprintf (f, " token %i\n", (int)otr_token); 336138fd1498Szrj 336238fd1498Szrj ctx.dump (f); 336338fd1498Szrj 336438fd1498Szrj fprintf (f, " %s%s%s%s\n ", 336538fd1498Szrj final ? "This is a complete list." : 336638fd1498Szrj "This is partial list; extra targets may be defined in other units.", 336738fd1498Szrj ctx.maybe_in_construction ? " (base types included)" : "", 336838fd1498Szrj ctx.maybe_derived_type ? " (derived types included)" : "", 336938fd1498Szrj ctx.speculative_maybe_derived_type ? " (speculative derived types included)" : ""); 337038fd1498Szrj len = targets.length (); 337138fd1498Szrj dump_targets (f, targets); 337238fd1498Szrj 337338fd1498Szrj targets = possible_polymorphic_call_targets (otr_type, otr_token, 337438fd1498Szrj ctx, 337538fd1498Szrj &final, NULL, true); 337638fd1498Szrj if (targets.length () != len) 337738fd1498Szrj { 337838fd1498Szrj fprintf (f, " Speculative targets:"); 337938fd1498Szrj dump_targets (f, targets); 338038fd1498Szrj } 338138fd1498Szrj /* Ugly: during callgraph construction the target cache may get populated 338238fd1498Szrj before all targets are found. While this is harmless (because all local 338338fd1498Szrj types are discovered and only in those case we devirtualize fully and we 338438fd1498Szrj don't do speculative devirtualization before IPA stage) it triggers 338538fd1498Szrj assert here when dumping at that stage also populates the case with 338638fd1498Szrj speculative targets. Quietly ignore this. */ 338738fd1498Szrj gcc_assert (symtab->state < IPA_SSA || targets.length () <= len); 338838fd1498Szrj fprintf (f, "\n"); 338938fd1498Szrj } 339038fd1498Szrj 339138fd1498Szrj 339238fd1498Szrj /* Return true if N can be possibly target of a polymorphic call of 339338fd1498Szrj OTR_TYPE/OTR_TOKEN. */ 339438fd1498Szrj 339538fd1498Szrj bool 339638fd1498Szrj possible_polymorphic_call_target_p (tree otr_type, 339738fd1498Szrj HOST_WIDE_INT otr_token, 339838fd1498Szrj const ipa_polymorphic_call_context &ctx, 339938fd1498Szrj struct cgraph_node *n) 340038fd1498Szrj { 340138fd1498Szrj vec <cgraph_node *> targets; 340238fd1498Szrj unsigned int i; 340338fd1498Szrj enum built_in_function fcode; 340438fd1498Szrj bool final; 340538fd1498Szrj 340638fd1498Szrj if (TREE_CODE (TREE_TYPE (n->decl)) == FUNCTION_TYPE 340738fd1498Szrj && ((fcode = DECL_FUNCTION_CODE (n->decl)) == BUILT_IN_UNREACHABLE 340838fd1498Szrj || fcode == BUILT_IN_TRAP)) 340938fd1498Szrj return true; 341038fd1498Szrj 341138fd1498Szrj if (is_cxa_pure_virtual_p (n->decl)) 341238fd1498Szrj return true; 341338fd1498Szrj 341438fd1498Szrj if (!odr_hash) 341538fd1498Szrj return true; 341638fd1498Szrj targets = possible_polymorphic_call_targets (otr_type, otr_token, ctx, &final); 341738fd1498Szrj for (i = 0; i < targets.length (); i++) 341838fd1498Szrj if (n->semantically_equivalent_p (targets[i])) 341938fd1498Szrj return true; 342038fd1498Szrj 342138fd1498Szrj /* At a moment we allow middle end to dig out new external declarations 342238fd1498Szrj as a targets of polymorphic calls. */ 342338fd1498Szrj if (!final && !n->definition) 342438fd1498Szrj return true; 342538fd1498Szrj return false; 342638fd1498Szrj } 342738fd1498Szrj 342838fd1498Szrj 342938fd1498Szrj 343038fd1498Szrj /* Return true if N can be possibly target of a polymorphic call of 343138fd1498Szrj OBJ_TYPE_REF expression REF in STMT. */ 343238fd1498Szrj 343338fd1498Szrj bool 343438fd1498Szrj possible_polymorphic_call_target_p (tree ref, 343538fd1498Szrj gimple *stmt, 343638fd1498Szrj struct cgraph_node *n) 343738fd1498Szrj { 343838fd1498Szrj ipa_polymorphic_call_context context (current_function_decl, ref, stmt); 343938fd1498Szrj tree call_fn = gimple_call_fn (stmt); 344038fd1498Szrj 344138fd1498Szrj return possible_polymorphic_call_target_p (obj_type_ref_class (call_fn), 344238fd1498Szrj tree_to_uhwi 344338fd1498Szrj (OBJ_TYPE_REF_TOKEN (call_fn)), 344438fd1498Szrj context, 344538fd1498Szrj n); 344638fd1498Szrj } 344738fd1498Szrj 344838fd1498Szrj 344938fd1498Szrj /* After callgraph construction new external nodes may appear. 345038fd1498Szrj Add them into the graph. */ 345138fd1498Szrj 345238fd1498Szrj void 345338fd1498Szrj update_type_inheritance_graph (void) 345438fd1498Szrj { 345538fd1498Szrj struct cgraph_node *n; 345638fd1498Szrj 345738fd1498Szrj if (!odr_hash) 345838fd1498Szrj return; 345938fd1498Szrj free_polymorphic_call_targets_hash (); 346038fd1498Szrj timevar_push (TV_IPA_INHERITANCE); 346138fd1498Szrj /* We reconstruct the graph starting from types of all methods seen in the 346238fd1498Szrj unit. */ 346338fd1498Szrj FOR_EACH_FUNCTION (n) 346438fd1498Szrj if (DECL_VIRTUAL_P (n->decl) 346538fd1498Szrj && !n->definition 346638fd1498Szrj && n->real_symbol_p ()) 346738fd1498Szrj get_odr_type (TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl)), true); 346838fd1498Szrj timevar_pop (TV_IPA_INHERITANCE); 346938fd1498Szrj } 347038fd1498Szrj 347138fd1498Szrj 347238fd1498Szrj /* Return true if N looks like likely target of a polymorphic call. 347338fd1498Szrj Rule out cxa_pure_virtual, noreturns, function declared cold and 347438fd1498Szrj other obvious cases. */ 347538fd1498Szrj 347638fd1498Szrj bool 347738fd1498Szrj likely_target_p (struct cgraph_node *n) 347838fd1498Szrj { 347938fd1498Szrj int flags; 348038fd1498Szrj /* cxa_pure_virtual and similar things are not likely. */ 348138fd1498Szrj if (TREE_CODE (TREE_TYPE (n->decl)) != METHOD_TYPE) 348238fd1498Szrj return false; 348338fd1498Szrj flags = flags_from_decl_or_type (n->decl); 348438fd1498Szrj if (flags & ECF_NORETURN) 348538fd1498Szrj return false; 348638fd1498Szrj if (lookup_attribute ("cold", 348738fd1498Szrj DECL_ATTRIBUTES (n->decl))) 348838fd1498Szrj return false; 348938fd1498Szrj if (n->frequency < NODE_FREQUENCY_NORMAL) 349038fd1498Szrj return false; 349138fd1498Szrj /* If there are no live virtual tables referring the target, 349238fd1498Szrj the only way the target can be called is an instance coming from other 349338fd1498Szrj compilation unit; speculative devirtualization is built around an 349438fd1498Szrj assumption that won't happen. */ 349538fd1498Szrj if (!referenced_from_vtable_p (n)) 349638fd1498Szrj return false; 349738fd1498Szrj return true; 349838fd1498Szrj } 349938fd1498Szrj 350038fd1498Szrj /* Compare type warning records P1 and P2 and choose one with larger count; 350138fd1498Szrj helper for qsort. */ 350238fd1498Szrj 350338fd1498Szrj int 350438fd1498Szrj type_warning_cmp (const void *p1, const void *p2) 350538fd1498Szrj { 350638fd1498Szrj const odr_type_warn_count *t1 = (const odr_type_warn_count *)p1; 350738fd1498Szrj const odr_type_warn_count *t2 = (const odr_type_warn_count *)p2; 350838fd1498Szrj 350938fd1498Szrj if (t1->dyn_count < t2->dyn_count) 351038fd1498Szrj return 1; 351138fd1498Szrj if (t1->dyn_count > t2->dyn_count) 351238fd1498Szrj return -1; 351338fd1498Szrj return t2->count - t1->count; 351438fd1498Szrj } 351538fd1498Szrj 351638fd1498Szrj /* Compare decl warning records P1 and P2 and choose one with larger count; 351738fd1498Szrj helper for qsort. */ 351838fd1498Szrj 351938fd1498Szrj int 352038fd1498Szrj decl_warning_cmp (const void *p1, const void *p2) 352138fd1498Szrj { 352238fd1498Szrj const decl_warn_count *t1 = *(const decl_warn_count * const *)p1; 352338fd1498Szrj const decl_warn_count *t2 = *(const decl_warn_count * const *)p2; 352438fd1498Szrj 352538fd1498Szrj if (t1->dyn_count < t2->dyn_count) 352638fd1498Szrj return 1; 352738fd1498Szrj if (t1->dyn_count > t2->dyn_count) 352838fd1498Szrj return -1; 352938fd1498Szrj return t2->count - t1->count; 353038fd1498Szrj } 353138fd1498Szrj 353238fd1498Szrj 353338fd1498Szrj /* Try to speculatively devirtualize call to OTR_TYPE with OTR_TOKEN with 353438fd1498Szrj context CTX. */ 353538fd1498Szrj 353638fd1498Szrj struct cgraph_node * 353738fd1498Szrj try_speculative_devirtualization (tree otr_type, HOST_WIDE_INT otr_token, 353838fd1498Szrj ipa_polymorphic_call_context ctx) 353938fd1498Szrj { 354038fd1498Szrj vec <cgraph_node *>targets 354138fd1498Szrj = possible_polymorphic_call_targets 354238fd1498Szrj (otr_type, otr_token, ctx, NULL, NULL, true); 354338fd1498Szrj unsigned int i; 354438fd1498Szrj struct cgraph_node *likely_target = NULL; 354538fd1498Szrj 354638fd1498Szrj for (i = 0; i < targets.length (); i++) 354738fd1498Szrj if (likely_target_p (targets[i])) 354838fd1498Szrj { 354938fd1498Szrj if (likely_target) 355038fd1498Szrj return NULL; 355138fd1498Szrj likely_target = targets[i]; 355238fd1498Szrj } 355338fd1498Szrj if (!likely_target 355438fd1498Szrj ||!likely_target->definition 355538fd1498Szrj || DECL_EXTERNAL (likely_target->decl)) 355638fd1498Szrj return NULL; 355738fd1498Szrj 355838fd1498Szrj /* Don't use an implicitly-declared destructor (c++/58678). */ 355938fd1498Szrj struct cgraph_node *non_thunk_target 356038fd1498Szrj = likely_target->function_symbol (); 356138fd1498Szrj if (DECL_ARTIFICIAL (non_thunk_target->decl)) 356238fd1498Szrj return NULL; 356338fd1498Szrj if (likely_target->get_availability () <= AVAIL_INTERPOSABLE 356438fd1498Szrj && likely_target->can_be_discarded_p ()) 356538fd1498Szrj return NULL; 356638fd1498Szrj return likely_target; 356738fd1498Szrj } 356838fd1498Szrj 356938fd1498Szrj /* The ipa-devirt pass. 357038fd1498Szrj When polymorphic call has only one likely target in the unit, 357138fd1498Szrj turn it into a speculative call. */ 357238fd1498Szrj 357338fd1498Szrj static unsigned int 357438fd1498Szrj ipa_devirt (void) 357538fd1498Szrj { 357638fd1498Szrj struct cgraph_node *n; 357738fd1498Szrj hash_set<void *> bad_call_targets; 357838fd1498Szrj struct cgraph_edge *e; 357938fd1498Szrj 358038fd1498Szrj int npolymorphic = 0, nspeculated = 0, nconverted = 0, ncold = 0; 358138fd1498Szrj int nmultiple = 0, noverwritable = 0, ndevirtualized = 0, nnotdefined = 0; 358238fd1498Szrj int nwrong = 0, nok = 0, nexternal = 0, nartificial = 0; 358338fd1498Szrj int ndropped = 0; 358438fd1498Szrj 358538fd1498Szrj if (!odr_types_ptr) 358638fd1498Szrj return 0; 358738fd1498Szrj 358838fd1498Szrj if (dump_file) 358938fd1498Szrj dump_type_inheritance_graph (dump_file); 359038fd1498Szrj 359138fd1498Szrj /* We can output -Wsuggest-final-methods and -Wsuggest-final-types warnings. 359238fd1498Szrj This is implemented by setting up final_warning_records that are updated 359338fd1498Szrj by get_polymorphic_call_targets. 359438fd1498Szrj We need to clear cache in this case to trigger recomputation of all 359538fd1498Szrj entries. */ 359638fd1498Szrj if (warn_suggest_final_methods || warn_suggest_final_types) 359738fd1498Szrj { 359838fd1498Szrj final_warning_records = new (final_warning_record); 359938fd1498Szrj final_warning_records->dyn_count = profile_count::zero (); 360038fd1498Szrj final_warning_records->grow_type_warnings (odr_types.length ()); 360138fd1498Szrj free_polymorphic_call_targets_hash (); 360238fd1498Szrj } 360338fd1498Szrj 360438fd1498Szrj FOR_EACH_DEFINED_FUNCTION (n) 360538fd1498Szrj { 360638fd1498Szrj bool update = false; 360738fd1498Szrj if (!opt_for_fn (n->decl, flag_devirtualize)) 360838fd1498Szrj continue; 360938fd1498Szrj if (dump_file && n->indirect_calls) 361038fd1498Szrj fprintf (dump_file, "\n\nProcesing function %s\n", 361138fd1498Szrj n->dump_name ()); 361238fd1498Szrj for (e = n->indirect_calls; e; e = e->next_callee) 361338fd1498Szrj if (e->indirect_info->polymorphic) 361438fd1498Szrj { 361538fd1498Szrj struct cgraph_node *likely_target = NULL; 361638fd1498Szrj void *cache_token; 361738fd1498Szrj bool final; 361838fd1498Szrj 361938fd1498Szrj if (final_warning_records) 362038fd1498Szrj final_warning_records->dyn_count = e->count.ipa (); 362138fd1498Szrj 362238fd1498Szrj vec <cgraph_node *>targets 362338fd1498Szrj = possible_polymorphic_call_targets 362438fd1498Szrj (e, &final, &cache_token, true); 362538fd1498Szrj unsigned int i; 362638fd1498Szrj 362738fd1498Szrj /* Trigger warnings by calculating non-speculative targets. */ 362838fd1498Szrj if (warn_suggest_final_methods || warn_suggest_final_types) 362938fd1498Szrj possible_polymorphic_call_targets (e); 363038fd1498Szrj 363138fd1498Szrj if (dump_file) 363238fd1498Szrj dump_possible_polymorphic_call_targets 363338fd1498Szrj (dump_file, e); 363438fd1498Szrj 363538fd1498Szrj npolymorphic++; 363638fd1498Szrj 363738fd1498Szrj /* See if the call can be devirtualized by means of ipa-prop's 363838fd1498Szrj polymorphic call context propagation. If not, we can just 363938fd1498Szrj forget about this call being polymorphic and avoid some heavy 364038fd1498Szrj lifting in remove_unreachable_nodes that will otherwise try to 364138fd1498Szrj keep all possible targets alive until inlining and in the inliner 364238fd1498Szrj itself. 364338fd1498Szrj 364438fd1498Szrj This may need to be revisited once we add further ways to use 364538fd1498Szrj the may edges, but it is a resonable thing to do right now. */ 364638fd1498Szrj 364738fd1498Szrj if ((e->indirect_info->param_index == -1 364838fd1498Szrj || (!opt_for_fn (n->decl, flag_devirtualize_speculatively) 364938fd1498Szrj && e->indirect_info->vptr_changed)) 365038fd1498Szrj && !flag_ltrans_devirtualize) 365138fd1498Szrj { 365238fd1498Szrj e->indirect_info->polymorphic = false; 365338fd1498Szrj ndropped++; 365438fd1498Szrj if (dump_file) 365538fd1498Szrj fprintf (dump_file, "Dropping polymorphic call info;" 365638fd1498Szrj " it can not be used by ipa-prop\n"); 365738fd1498Szrj } 365838fd1498Szrj 365938fd1498Szrj if (!opt_for_fn (n->decl, flag_devirtualize_speculatively)) 366038fd1498Szrj continue; 366138fd1498Szrj 366238fd1498Szrj if (!e->maybe_hot_p ()) 366338fd1498Szrj { 366438fd1498Szrj if (dump_file) 366538fd1498Szrj fprintf (dump_file, "Call is cold\n\n"); 366638fd1498Szrj ncold++; 366738fd1498Szrj continue; 366838fd1498Szrj } 366938fd1498Szrj if (e->speculative) 367038fd1498Szrj { 367138fd1498Szrj if (dump_file) 367238fd1498Szrj fprintf (dump_file, "Call is already speculated\n\n"); 367338fd1498Szrj nspeculated++; 367438fd1498Szrj 367538fd1498Szrj /* When dumping see if we agree with speculation. */ 367638fd1498Szrj if (!dump_file) 367738fd1498Szrj continue; 367838fd1498Szrj } 367938fd1498Szrj if (bad_call_targets.contains (cache_token)) 368038fd1498Szrj { 368138fd1498Szrj if (dump_file) 368238fd1498Szrj fprintf (dump_file, "Target list is known to be useless\n\n"); 368338fd1498Szrj nmultiple++; 368438fd1498Szrj continue; 368538fd1498Szrj } 368638fd1498Szrj for (i = 0; i < targets.length (); i++) 368738fd1498Szrj if (likely_target_p (targets[i])) 368838fd1498Szrj { 368938fd1498Szrj if (likely_target) 369038fd1498Szrj { 369138fd1498Szrj likely_target = NULL; 369238fd1498Szrj if (dump_file) 369338fd1498Szrj fprintf (dump_file, "More than one likely target\n\n"); 369438fd1498Szrj nmultiple++; 369538fd1498Szrj break; 369638fd1498Szrj } 369738fd1498Szrj likely_target = targets[i]; 369838fd1498Szrj } 369938fd1498Szrj if (!likely_target) 370038fd1498Szrj { 370138fd1498Szrj bad_call_targets.add (cache_token); 370238fd1498Szrj continue; 370338fd1498Szrj } 370438fd1498Szrj /* This is reached only when dumping; check if we agree or disagree 370538fd1498Szrj with the speculation. */ 370638fd1498Szrj if (e->speculative) 370738fd1498Szrj { 370838fd1498Szrj struct cgraph_edge *e2; 370938fd1498Szrj struct ipa_ref *ref; 371038fd1498Szrj e->speculative_call_info (e2, e, ref); 371138fd1498Szrj if (e2->callee->ultimate_alias_target () 371238fd1498Szrj == likely_target->ultimate_alias_target ()) 371338fd1498Szrj { 371438fd1498Szrj fprintf (dump_file, "We agree with speculation\n\n"); 371538fd1498Szrj nok++; 371638fd1498Szrj } 371738fd1498Szrj else 371838fd1498Szrj { 371938fd1498Szrj fprintf (dump_file, "We disagree with speculation\n\n"); 372038fd1498Szrj nwrong++; 372138fd1498Szrj } 372238fd1498Szrj continue; 372338fd1498Szrj } 372438fd1498Szrj if (!likely_target->definition) 372538fd1498Szrj { 372638fd1498Szrj if (dump_file) 372738fd1498Szrj fprintf (dump_file, "Target is not a definition\n\n"); 372838fd1498Szrj nnotdefined++; 372938fd1498Szrj continue; 373038fd1498Szrj } 373138fd1498Szrj /* Do not introduce new references to external symbols. While we 373238fd1498Szrj can handle these just well, it is common for programs to 373338fd1498Szrj incorrectly with headers defining methods they are linked 373438fd1498Szrj with. */ 373538fd1498Szrj if (DECL_EXTERNAL (likely_target->decl)) 373638fd1498Szrj { 373738fd1498Szrj if (dump_file) 373838fd1498Szrj fprintf (dump_file, "Target is external\n\n"); 373938fd1498Szrj nexternal++; 374038fd1498Szrj continue; 374138fd1498Szrj } 374238fd1498Szrj /* Don't use an implicitly-declared destructor (c++/58678). */ 374338fd1498Szrj struct cgraph_node *non_thunk_target 374438fd1498Szrj = likely_target->function_symbol (); 374538fd1498Szrj if (DECL_ARTIFICIAL (non_thunk_target->decl)) 374638fd1498Szrj { 374738fd1498Szrj if (dump_file) 374838fd1498Szrj fprintf (dump_file, "Target is artificial\n\n"); 374938fd1498Szrj nartificial++; 375038fd1498Szrj continue; 375138fd1498Szrj } 375238fd1498Szrj if (likely_target->get_availability () <= AVAIL_INTERPOSABLE 375338fd1498Szrj && likely_target->can_be_discarded_p ()) 375438fd1498Szrj { 375538fd1498Szrj if (dump_file) 375638fd1498Szrj fprintf (dump_file, "Target is overwritable\n\n"); 375738fd1498Szrj noverwritable++; 375838fd1498Szrj continue; 375938fd1498Szrj } 376038fd1498Szrj else if (dbg_cnt (devirt)) 376138fd1498Szrj { 376238fd1498Szrj if (dump_enabled_p ()) 376338fd1498Szrj { 376438fd1498Szrj location_t locus = gimple_location_safe (e->call_stmt); 376538fd1498Szrj dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, locus, 376638fd1498Szrj "speculatively devirtualizing call " 376738fd1498Szrj "in %s to %s\n", 376838fd1498Szrj n->dump_name (), 376938fd1498Szrj likely_target->dump_name ()); 377038fd1498Szrj } 377138fd1498Szrj if (!likely_target->can_be_discarded_p ()) 377238fd1498Szrj { 377338fd1498Szrj cgraph_node *alias; 377438fd1498Szrj alias = dyn_cast<cgraph_node *> (likely_target->noninterposable_alias ()); 377538fd1498Szrj if (alias) 377638fd1498Szrj likely_target = alias; 377738fd1498Szrj } 377838fd1498Szrj nconverted++; 377938fd1498Szrj update = true; 378038fd1498Szrj e->make_speculative 378138fd1498Szrj (likely_target, e->count.apply_scale (8, 10)); 378238fd1498Szrj } 378338fd1498Szrj } 378438fd1498Szrj if (update) 378538fd1498Szrj ipa_update_overall_fn_summary (n); 378638fd1498Szrj } 378738fd1498Szrj if (warn_suggest_final_methods || warn_suggest_final_types) 378838fd1498Szrj { 378938fd1498Szrj if (warn_suggest_final_types) 379038fd1498Szrj { 379138fd1498Szrj final_warning_records->type_warnings.qsort (type_warning_cmp); 379238fd1498Szrj for (unsigned int i = 0; 379338fd1498Szrj i < final_warning_records->type_warnings.length (); i++) 379438fd1498Szrj if (final_warning_records->type_warnings[i].count) 379538fd1498Szrj { 379638fd1498Szrj tree type = final_warning_records->type_warnings[i].type; 379738fd1498Szrj int count = final_warning_records->type_warnings[i].count; 379838fd1498Szrj profile_count dyn_count 379938fd1498Szrj = final_warning_records->type_warnings[i].dyn_count; 380038fd1498Szrj 380138fd1498Szrj if (!(dyn_count > 0)) 380238fd1498Szrj warning_n (DECL_SOURCE_LOCATION (TYPE_NAME (type)), 380338fd1498Szrj OPT_Wsuggest_final_types, count, 380438fd1498Szrj "Declaring type %qD final " 380538fd1498Szrj "would enable devirtualization of %i call", 380638fd1498Szrj "Declaring type %qD final " 380738fd1498Szrj "would enable devirtualization of %i calls", 380838fd1498Szrj type, 380938fd1498Szrj count); 381038fd1498Szrj else 381138fd1498Szrj warning_n (DECL_SOURCE_LOCATION (TYPE_NAME (type)), 381238fd1498Szrj OPT_Wsuggest_final_types, count, 381338fd1498Szrj "Declaring type %qD final " 381438fd1498Szrj "would enable devirtualization of %i call " 381538fd1498Szrj "executed %lli times", 381638fd1498Szrj "Declaring type %qD final " 381738fd1498Szrj "would enable devirtualization of %i calls " 381838fd1498Szrj "executed %lli times", 381938fd1498Szrj type, 382038fd1498Szrj count, 382138fd1498Szrj (long long) dyn_count.to_gcov_type ()); 382238fd1498Szrj } 382338fd1498Szrj } 382438fd1498Szrj 382538fd1498Szrj if (warn_suggest_final_methods) 382638fd1498Szrj { 382738fd1498Szrj auto_vec<const decl_warn_count*> decl_warnings_vec; 382838fd1498Szrj 382938fd1498Szrj final_warning_records->decl_warnings.traverse 383038fd1498Szrj <vec<const decl_warn_count *> *, add_decl_warning> (&decl_warnings_vec); 383138fd1498Szrj decl_warnings_vec.qsort (decl_warning_cmp); 383238fd1498Szrj for (unsigned int i = 0; i < decl_warnings_vec.length (); i++) 383338fd1498Szrj { 383438fd1498Szrj tree decl = decl_warnings_vec[i]->decl; 383538fd1498Szrj int count = decl_warnings_vec[i]->count; 383638fd1498Szrj profile_count dyn_count 383738fd1498Szrj = decl_warnings_vec[i]->dyn_count; 383838fd1498Szrj 383938fd1498Szrj if (!(dyn_count > 0)) 384038fd1498Szrj if (DECL_CXX_DESTRUCTOR_P (decl)) 384138fd1498Szrj warning_n (DECL_SOURCE_LOCATION (decl), 384238fd1498Szrj OPT_Wsuggest_final_methods, count, 384338fd1498Szrj "Declaring virtual destructor of %qD final " 384438fd1498Szrj "would enable devirtualization of %i call", 384538fd1498Szrj "Declaring virtual destructor of %qD final " 384638fd1498Szrj "would enable devirtualization of %i calls", 384738fd1498Szrj DECL_CONTEXT (decl), count); 384838fd1498Szrj else 384938fd1498Szrj warning_n (DECL_SOURCE_LOCATION (decl), 385038fd1498Szrj OPT_Wsuggest_final_methods, count, 385138fd1498Szrj "Declaring method %qD final " 385238fd1498Szrj "would enable devirtualization of %i call", 385338fd1498Szrj "Declaring method %qD final " 385438fd1498Szrj "would enable devirtualization of %i calls", 385538fd1498Szrj decl, count); 385638fd1498Szrj else if (DECL_CXX_DESTRUCTOR_P (decl)) 385738fd1498Szrj warning_n (DECL_SOURCE_LOCATION (decl), 385838fd1498Szrj OPT_Wsuggest_final_methods, count, 385938fd1498Szrj "Declaring virtual destructor of %qD final " 386038fd1498Szrj "would enable devirtualization of %i call " 386138fd1498Szrj "executed %lli times", 386238fd1498Szrj "Declaring virtual destructor of %qD final " 386338fd1498Szrj "would enable devirtualization of %i calls " 386438fd1498Szrj "executed %lli times", 386538fd1498Szrj DECL_CONTEXT (decl), count, 386638fd1498Szrj (long long)dyn_count.to_gcov_type ()); 386738fd1498Szrj else 386838fd1498Szrj warning_n (DECL_SOURCE_LOCATION (decl), 386938fd1498Szrj OPT_Wsuggest_final_methods, count, 387038fd1498Szrj "Declaring method %qD final " 387138fd1498Szrj "would enable devirtualization of %i call " 387238fd1498Szrj "executed %lli times", 387338fd1498Szrj "Declaring method %qD final " 387438fd1498Szrj "would enable devirtualization of %i calls " 387538fd1498Szrj "executed %lli times", 387638fd1498Szrj decl, count, 387738fd1498Szrj (long long)dyn_count.to_gcov_type ()); 387838fd1498Szrj } 387938fd1498Szrj } 388038fd1498Szrj 388138fd1498Szrj delete (final_warning_records); 388238fd1498Szrj final_warning_records = 0; 388338fd1498Szrj } 388438fd1498Szrj 388538fd1498Szrj if (dump_file) 388638fd1498Szrj fprintf (dump_file, 388738fd1498Szrj "%i polymorphic calls, %i devirtualized," 388838fd1498Szrj " %i speculatively devirtualized, %i cold\n" 388938fd1498Szrj "%i have multiple targets, %i overwritable," 389038fd1498Szrj " %i already speculated (%i agree, %i disagree)," 389138fd1498Szrj " %i external, %i not defined, %i artificial, %i infos dropped\n", 389238fd1498Szrj npolymorphic, ndevirtualized, nconverted, ncold, 389338fd1498Szrj nmultiple, noverwritable, nspeculated, nok, nwrong, 389438fd1498Szrj nexternal, nnotdefined, nartificial, ndropped); 389538fd1498Szrj return ndevirtualized || ndropped ? TODO_remove_functions : 0; 389638fd1498Szrj } 389738fd1498Szrj 389838fd1498Szrj namespace { 389938fd1498Szrj 390038fd1498Szrj const pass_data pass_data_ipa_devirt = 390138fd1498Szrj { 390238fd1498Szrj IPA_PASS, /* type */ 390338fd1498Szrj "devirt", /* name */ 390438fd1498Szrj OPTGROUP_NONE, /* optinfo_flags */ 390538fd1498Szrj TV_IPA_DEVIRT, /* tv_id */ 390638fd1498Szrj 0, /* properties_required */ 390738fd1498Szrj 0, /* properties_provided */ 390838fd1498Szrj 0, /* properties_destroyed */ 390938fd1498Szrj 0, /* todo_flags_start */ 391038fd1498Szrj ( TODO_dump_symtab ), /* todo_flags_finish */ 391138fd1498Szrj }; 391238fd1498Szrj 391338fd1498Szrj class pass_ipa_devirt : public ipa_opt_pass_d 391438fd1498Szrj { 391538fd1498Szrj public: 391638fd1498Szrj pass_ipa_devirt (gcc::context *ctxt) 391738fd1498Szrj : ipa_opt_pass_d (pass_data_ipa_devirt, ctxt, 391838fd1498Szrj NULL, /* generate_summary */ 391938fd1498Szrj NULL, /* write_summary */ 392038fd1498Szrj NULL, /* read_summary */ 392138fd1498Szrj NULL, /* write_optimization_summary */ 392238fd1498Szrj NULL, /* read_optimization_summary */ 392338fd1498Szrj NULL, /* stmt_fixup */ 392438fd1498Szrj 0, /* function_transform_todo_flags_start */ 392538fd1498Szrj NULL, /* function_transform */ 392638fd1498Szrj NULL) /* variable_transform */ 392738fd1498Szrj {} 392838fd1498Szrj 392938fd1498Szrj /* opt_pass methods: */ 393038fd1498Szrj virtual bool gate (function *) 393138fd1498Szrj { 393238fd1498Szrj /* In LTO, always run the IPA passes and decide on function basis if the 393338fd1498Szrj pass is enabled. */ 393438fd1498Szrj if (in_lto_p) 393538fd1498Szrj return true; 393638fd1498Szrj return (flag_devirtualize 393738fd1498Szrj && (flag_devirtualize_speculatively 393838fd1498Szrj || (warn_suggest_final_methods 393938fd1498Szrj || warn_suggest_final_types)) 394038fd1498Szrj && optimize); 394138fd1498Szrj } 394238fd1498Szrj 394338fd1498Szrj virtual unsigned int execute (function *) { return ipa_devirt (); } 394438fd1498Szrj 394538fd1498Szrj }; // class pass_ipa_devirt 394638fd1498Szrj 394738fd1498Szrj } // anon namespace 394838fd1498Szrj 394938fd1498Szrj ipa_opt_pass_d * 395038fd1498Szrj make_pass_ipa_devirt (gcc::context *ctxt) 395138fd1498Szrj { 395238fd1498Szrj return new pass_ipa_devirt (ctxt); 395338fd1498Szrj } 395438fd1498Szrj 395538fd1498Szrj #include "gt-ipa-devirt.h" 3956