xref: /dflybsd-src/contrib/gcc-8.0/gcc/ipa-devirt.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
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