annotate gcc/ipa-devirt.c @ 158:494b0b89df80 default tip

...
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Mon, 25 May 2020 18:13:55 +0900
parents 1830386684a0
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Basic IPA utilities for type inheritance graph construction and
kono
parents:
diff changeset
2 devirtualization.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3 Copyright (C) 2013-2020 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
4 Contributed by Jan Hubicka
kono
parents:
diff changeset
5
kono
parents:
diff changeset
6 This file is part of GCC.
kono
parents:
diff changeset
7
kono
parents:
diff changeset
8 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
9 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
10 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
11 version.
kono
parents:
diff changeset
12
kono
parents:
diff changeset
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
16 for more details.
kono
parents:
diff changeset
17
kono
parents:
diff changeset
18 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
19 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
20 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
21
kono
parents:
diff changeset
22 /* Brief vocabulary:
kono
parents:
diff changeset
23 ODR = One Definition Rule
kono
parents:
diff changeset
24 In short, the ODR states that:
kono
parents:
diff changeset
25 1 In any translation unit, a template, type, function, or object can
kono
parents:
diff changeset
26 have no more than one definition. Some of these can have any number
kono
parents:
diff changeset
27 of declarations. A definition provides an instance.
kono
parents:
diff changeset
28 2 In the entire program, an object or non-inline function cannot have
kono
parents:
diff changeset
29 more than one definition; if an object or function is used, it must
kono
parents:
diff changeset
30 have exactly one definition. You can declare an object or function
kono
parents:
diff changeset
31 that is never used, in which case you don't have to provide
kono
parents:
diff changeset
32 a definition. In no event can there be more than one definition.
kono
parents:
diff changeset
33 3 Some things, like types, templates, and extern inline functions, can
kono
parents:
diff changeset
34 be defined in more than one translation unit. For a given entity,
kono
parents:
diff changeset
35 each definition must be the same. Non-extern objects and functions
kono
parents:
diff changeset
36 in different translation units are different entities, even if their
kono
parents:
diff changeset
37 names and types are the same.
kono
parents:
diff changeset
38
kono
parents:
diff changeset
39 OTR = OBJ_TYPE_REF
kono
parents:
diff changeset
40 This is the Gimple representation of type information of a polymorphic call.
kono
parents:
diff changeset
41 It contains two parameters:
kono
parents:
diff changeset
42 otr_type is a type of class whose method is called.
kono
parents:
diff changeset
43 otr_token is the index into virtual table where address is taken.
kono
parents:
diff changeset
44
kono
parents:
diff changeset
45 BINFO
kono
parents:
diff changeset
46 This is the type inheritance information attached to each tree
kono
parents:
diff changeset
47 RECORD_TYPE by the C++ frontend. It provides information about base
kono
parents:
diff changeset
48 types and virtual tables.
kono
parents:
diff changeset
49
kono
parents:
diff changeset
50 BINFO is linked to the RECORD_TYPE by TYPE_BINFO.
kono
parents:
diff changeset
51 BINFO also links to its type by BINFO_TYPE and to the virtual table by
kono
parents:
diff changeset
52 BINFO_VTABLE.
kono
parents:
diff changeset
53
kono
parents:
diff changeset
54 Base types of a given type are enumerated by BINFO_BASE_BINFO
kono
parents:
diff changeset
55 vector. Members of this vectors are not BINFOs associated
kono
parents:
diff changeset
56 with a base type. Rather they are new copies of BINFOs
kono
parents:
diff changeset
57 (base BINFOs). Their virtual tables may differ from
kono
parents:
diff changeset
58 virtual table of the base type. Also BINFO_OFFSET specifies
kono
parents:
diff changeset
59 offset of the base within the type.
kono
parents:
diff changeset
60
kono
parents:
diff changeset
61 In the case of single inheritance, the virtual table is shared
kono
parents:
diff changeset
62 and BINFO_VTABLE of base BINFO is NULL. In the case of multiple
kono
parents:
diff changeset
63 inheritance the individual virtual tables are pointer to by
kono
parents:
diff changeset
64 BINFO_VTABLE of base binfos (that differs of BINFO_VTABLE of
kono
parents:
diff changeset
65 binfo associated to the base type).
kono
parents:
diff changeset
66
kono
parents:
diff changeset
67 BINFO lookup for a given base type and offset can be done by
kono
parents:
diff changeset
68 get_binfo_at_offset. It returns proper BINFO whose virtual table
kono
parents:
diff changeset
69 can be used for lookup of virtual methods associated with the
kono
parents:
diff changeset
70 base type.
kono
parents:
diff changeset
71
kono
parents:
diff changeset
72 token
kono
parents:
diff changeset
73 This is an index of virtual method in virtual table associated
kono
parents:
diff changeset
74 to the type defining it. Token can be looked up from OBJ_TYPE_REF
kono
parents:
diff changeset
75 or from DECL_VINDEX of a given virtual table.
kono
parents:
diff changeset
76
kono
parents:
diff changeset
77 polymorphic (indirect) call
kono
parents:
diff changeset
78 This is callgraph representation of virtual method call. Every
kono
parents:
diff changeset
79 polymorphic call contains otr_type and otr_token taken from
kono
parents:
diff changeset
80 original OBJ_TYPE_REF at callgraph construction time.
kono
parents:
diff changeset
81
kono
parents:
diff changeset
82 What we do here:
kono
parents:
diff changeset
83
kono
parents:
diff changeset
84 build_type_inheritance_graph triggers a construction of the type inheritance
kono
parents:
diff changeset
85 graph.
kono
parents:
diff changeset
86
kono
parents:
diff changeset
87 We reconstruct it based on types of methods we see in the unit.
kono
parents:
diff changeset
88 This means that the graph is not complete. Types with no methods are not
kono
parents:
diff changeset
89 inserted into the graph. Also types without virtual methods are not
kono
parents:
diff changeset
90 represented at all, though it may be easy to add this.
kono
parents:
diff changeset
91
kono
parents:
diff changeset
92 The inheritance graph is represented as follows:
kono
parents:
diff changeset
93
kono
parents:
diff changeset
94 Vertices are structures odr_type. Every odr_type may correspond
kono
parents:
diff changeset
95 to one or more tree type nodes that are equivalent by ODR rule.
kono
parents:
diff changeset
96 (the multiple type nodes appear only with linktime optimization)
kono
parents:
diff changeset
97
kono
parents:
diff changeset
98 Edges are represented by odr_type->base and odr_type->derived_types.
kono
parents:
diff changeset
99 At the moment we do not track offsets of types for multiple inheritance.
kono
parents:
diff changeset
100 Adding this is easy.
kono
parents:
diff changeset
101
kono
parents:
diff changeset
102 possible_polymorphic_call_targets returns, given an parameters found in
kono
parents:
diff changeset
103 indirect polymorphic edge all possible polymorphic call targets of the call.
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 pass_ipa_devirt performs simple speculative devirtualization.
kono
parents:
diff changeset
106 */
kono
parents:
diff changeset
107
kono
parents:
diff changeset
108 #include "config.h"
kono
parents:
diff changeset
109 #include "system.h"
kono
parents:
diff changeset
110 #include "coretypes.h"
kono
parents:
diff changeset
111 #include "backend.h"
kono
parents:
diff changeset
112 #include "rtl.h"
kono
parents:
diff changeset
113 #include "tree.h"
kono
parents:
diff changeset
114 #include "gimple.h"
kono
parents:
diff changeset
115 #include "alloc-pool.h"
kono
parents:
diff changeset
116 #include "tree-pass.h"
kono
parents:
diff changeset
117 #include "cgraph.h"
kono
parents:
diff changeset
118 #include "lto-streamer.h"
kono
parents:
diff changeset
119 #include "fold-const.h"
kono
parents:
diff changeset
120 #include "print-tree.h"
kono
parents:
diff changeset
121 #include "calls.h"
kono
parents:
diff changeset
122 #include "ipa-utils.h"
kono
parents:
diff changeset
123 #include "gimple-fold.h"
kono
parents:
diff changeset
124 #include "symbol-summary.h"
kono
parents:
diff changeset
125 #include "tree-vrp.h"
kono
parents:
diff changeset
126 #include "ipa-prop.h"
kono
parents:
diff changeset
127 #include "ipa-fnsummary.h"
kono
parents:
diff changeset
128 #include "demangle.h"
kono
parents:
diff changeset
129 #include "dbgcnt.h"
kono
parents:
diff changeset
130 #include "gimple-pretty-print.h"
kono
parents:
diff changeset
131 #include "intl.h"
kono
parents:
diff changeset
132 #include "stringpool.h"
kono
parents:
diff changeset
133 #include "attribs.h"
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 /* Hash based set of pairs of types. */
kono
parents:
diff changeset
136 struct type_pair
kono
parents:
diff changeset
137 {
kono
parents:
diff changeset
138 tree first;
kono
parents:
diff changeset
139 tree second;
kono
parents:
diff changeset
140 };
kono
parents:
diff changeset
141
kono
parents:
diff changeset
142 template <>
kono
parents:
diff changeset
143 struct default_hash_traits <type_pair>
kono
parents:
diff changeset
144 : typed_noop_remove <type_pair>
kono
parents:
diff changeset
145 {
kono
parents:
diff changeset
146 GTY((skip)) typedef type_pair value_type;
kono
parents:
diff changeset
147 GTY((skip)) typedef type_pair compare_type;
kono
parents:
diff changeset
148 static hashval_t
kono
parents:
diff changeset
149 hash (type_pair p)
kono
parents:
diff changeset
150 {
kono
parents:
diff changeset
151 return TYPE_UID (p.first) ^ TYPE_UID (p.second);
kono
parents:
diff changeset
152 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
153 static const bool empty_zero_p = true;
111
kono
parents:
diff changeset
154 static bool
kono
parents:
diff changeset
155 is_empty (type_pair p)
kono
parents:
diff changeset
156 {
kono
parents:
diff changeset
157 return p.first == NULL;
kono
parents:
diff changeset
158 }
kono
parents:
diff changeset
159 static bool
kono
parents:
diff changeset
160 is_deleted (type_pair p ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
161 {
kono
parents:
diff changeset
162 return false;
kono
parents:
diff changeset
163 }
kono
parents:
diff changeset
164 static bool
kono
parents:
diff changeset
165 equal (const type_pair &a, const type_pair &b)
kono
parents:
diff changeset
166 {
kono
parents:
diff changeset
167 return a.first==b.first && a.second == b.second;
kono
parents:
diff changeset
168 }
kono
parents:
diff changeset
169 static void
kono
parents:
diff changeset
170 mark_empty (type_pair &e)
kono
parents:
diff changeset
171 {
kono
parents:
diff changeset
172 e.first = NULL;
kono
parents:
diff changeset
173 }
kono
parents:
diff changeset
174 };
kono
parents:
diff changeset
175
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
176 /* HACK alert: this is used to communicate with ipa-inline-transform that
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
177 thunk is being expanded and there is no need to clear the polymorphic
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
178 call target cache. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
179 bool thunk_expansion;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
180
111
kono
parents:
diff changeset
181 static bool odr_types_equivalent_p (tree, tree, bool, bool *,
kono
parents:
diff changeset
182 hash_set<type_pair> *,
kono
parents:
diff changeset
183 location_t, location_t);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
184 static void warn_odr (tree t1, tree t2, tree st1, tree st2,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
185 bool warn, bool *warned, const char *reason);
111
kono
parents:
diff changeset
186
kono
parents:
diff changeset
187 static bool odr_violation_reported = false;
kono
parents:
diff changeset
188
kono
parents:
diff changeset
189
kono
parents:
diff changeset
190 /* Pointer set of all call targets appearing in the cache. */
kono
parents:
diff changeset
191 static hash_set<cgraph_node *> *cached_polymorphic_call_targets;
kono
parents:
diff changeset
192
kono
parents:
diff changeset
193 /* The node of type inheritance graph. For each type unique in
kono
parents:
diff changeset
194 One Definition Rule (ODR) sense, we produce one node linking all
kono
parents:
diff changeset
195 main variants of types equivalent to it, bases and derived types. */
kono
parents:
diff changeset
196
kono
parents:
diff changeset
197 struct GTY(()) odr_type_d
kono
parents:
diff changeset
198 {
kono
parents:
diff changeset
199 /* leader type. */
kono
parents:
diff changeset
200 tree type;
kono
parents:
diff changeset
201 /* All bases; built only for main variants of types. */
kono
parents:
diff changeset
202 vec<odr_type> GTY((skip)) bases;
kono
parents:
diff changeset
203 /* All derived types with virtual methods seen in unit;
kono
parents:
diff changeset
204 built only for main variants of types. */
kono
parents:
diff changeset
205 vec<odr_type> GTY((skip)) derived_types;
kono
parents:
diff changeset
206
kono
parents:
diff changeset
207 /* All equivalent types, if more than one. */
kono
parents:
diff changeset
208 vec<tree, va_gc> *types;
kono
parents:
diff changeset
209 /* Set of all equivalent types, if NON-NULL. */
kono
parents:
diff changeset
210 hash_set<tree> * GTY((skip)) types_set;
kono
parents:
diff changeset
211
kono
parents:
diff changeset
212 /* Unique ID indexing the type in odr_types array. */
kono
parents:
diff changeset
213 int id;
kono
parents:
diff changeset
214 /* Is it in anonymous namespace? */
kono
parents:
diff changeset
215 bool anonymous_namespace;
kono
parents:
diff changeset
216 /* Do we know about all derivations of given type? */
kono
parents:
diff changeset
217 bool all_derivations_known;
kono
parents:
diff changeset
218 /* Did we report ODR violation here? */
kono
parents:
diff changeset
219 bool odr_violated;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
220 /* Set when virtual table without RTTI prevailed table with. */
111
kono
parents:
diff changeset
221 bool rtti_broken;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
222 /* Set when the canonical type is determined using the type name. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
223 bool tbaa_enabled;
111
kono
parents:
diff changeset
224 };
kono
parents:
diff changeset
225
kono
parents:
diff changeset
226 /* Return TRUE if all derived types of T are known and thus
kono
parents:
diff changeset
227 we may consider the walk of derived type complete.
kono
parents:
diff changeset
228
kono
parents:
diff changeset
229 This is typically true only for final anonymous namespace types and types
kono
parents:
diff changeset
230 defined within functions (that may be COMDAT and thus shared across units,
kono
parents:
diff changeset
231 but with the same set of derived types). */
kono
parents:
diff changeset
232
kono
parents:
diff changeset
233 bool
kono
parents:
diff changeset
234 type_all_derivations_known_p (const_tree t)
kono
parents:
diff changeset
235 {
kono
parents:
diff changeset
236 if (TYPE_FINAL_P (t))
kono
parents:
diff changeset
237 return true;
kono
parents:
diff changeset
238 if (flag_ltrans)
kono
parents:
diff changeset
239 return false;
kono
parents:
diff changeset
240 /* Non-C++ types may have IDENTIFIER_NODE here, do not crash. */
kono
parents:
diff changeset
241 if (!TYPE_NAME (t) || TREE_CODE (TYPE_NAME (t)) != TYPE_DECL)
kono
parents:
diff changeset
242 return true;
kono
parents:
diff changeset
243 if (type_in_anonymous_namespace_p (t))
kono
parents:
diff changeset
244 return true;
kono
parents:
diff changeset
245 return (decl_function_context (TYPE_NAME (t)) != NULL);
kono
parents:
diff changeset
246 }
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 /* Return TRUE if type's constructors are all visible. */
kono
parents:
diff changeset
249
kono
parents:
diff changeset
250 static bool
kono
parents:
diff changeset
251 type_all_ctors_visible_p (tree t)
kono
parents:
diff changeset
252 {
kono
parents:
diff changeset
253 return !flag_ltrans
kono
parents:
diff changeset
254 && symtab->state >= CONSTRUCTION
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
255 /* We cannot always use type_all_derivations_known_p.
111
kono
parents:
diff changeset
256 For function local types we must assume case where
kono
parents:
diff changeset
257 the function is COMDAT and shared in between units.
kono
parents:
diff changeset
258
kono
parents:
diff changeset
259 TODO: These cases are quite easy to get, but we need
kono
parents:
diff changeset
260 to keep track of C++ privatizing via -Wno-weak
kono
parents:
diff changeset
261 as well as the IPA privatizing. */
kono
parents:
diff changeset
262 && type_in_anonymous_namespace_p (t);
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 /* Return TRUE if type may have instance. */
kono
parents:
diff changeset
266
kono
parents:
diff changeset
267 static bool
kono
parents:
diff changeset
268 type_possibly_instantiated_p (tree t)
kono
parents:
diff changeset
269 {
kono
parents:
diff changeset
270 tree vtable;
kono
parents:
diff changeset
271 varpool_node *vnode;
kono
parents:
diff changeset
272
kono
parents:
diff changeset
273 /* TODO: Add abstract types here. */
kono
parents:
diff changeset
274 if (!type_all_ctors_visible_p (t))
kono
parents:
diff changeset
275 return true;
kono
parents:
diff changeset
276
kono
parents:
diff changeset
277 vtable = BINFO_VTABLE (TYPE_BINFO (t));
kono
parents:
diff changeset
278 if (TREE_CODE (vtable) == POINTER_PLUS_EXPR)
kono
parents:
diff changeset
279 vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0);
kono
parents:
diff changeset
280 vnode = varpool_node::get (vtable);
kono
parents:
diff changeset
281 return vnode && vnode->definition;
kono
parents:
diff changeset
282 }
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 /* Hash used to unify ODR types based on their mangled name and for anonymous
kono
parents:
diff changeset
285 namespace types. */
kono
parents:
diff changeset
286
kono
parents:
diff changeset
287 struct odr_name_hasher : pointer_hash <odr_type_d>
kono
parents:
diff changeset
288 {
kono
parents:
diff changeset
289 typedef union tree_node *compare_type;
kono
parents:
diff changeset
290 static inline hashval_t hash (const odr_type_d *);
kono
parents:
diff changeset
291 static inline bool equal (const odr_type_d *, const tree_node *);
kono
parents:
diff changeset
292 static inline void remove (odr_type_d *);
kono
parents:
diff changeset
293 };
kono
parents:
diff changeset
294
kono
parents:
diff changeset
295 static bool
kono
parents:
diff changeset
296 can_be_name_hashed_p (tree t)
kono
parents:
diff changeset
297 {
kono
parents:
diff changeset
298 return (!in_lto_p || odr_type_p (t));
kono
parents:
diff changeset
299 }
kono
parents:
diff changeset
300
kono
parents:
diff changeset
301 /* Hash type by its ODR name. */
kono
parents:
diff changeset
302
kono
parents:
diff changeset
303 static hashval_t
kono
parents:
diff changeset
304 hash_odr_name (const_tree t)
kono
parents:
diff changeset
305 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
306 gcc_checking_assert (TYPE_MAIN_VARIANT (t) == t);
111
kono
parents:
diff changeset
307
kono
parents:
diff changeset
308 /* If not in LTO, all main variants are unique, so we can do
kono
parents:
diff changeset
309 pointer hash. */
kono
parents:
diff changeset
310 if (!in_lto_p)
kono
parents:
diff changeset
311 return htab_hash_pointer (t);
kono
parents:
diff changeset
312
kono
parents:
diff changeset
313 /* Anonymous types are unique. */
kono
parents:
diff changeset
314 if (type_with_linkage_p (t) && type_in_anonymous_namespace_p (t))
kono
parents:
diff changeset
315 return htab_hash_pointer (t);
kono
parents:
diff changeset
316
kono
parents:
diff changeset
317 gcc_checking_assert (TYPE_NAME (t)
kono
parents:
diff changeset
318 && DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t)));
kono
parents:
diff changeset
319 return IDENTIFIER_HASH_VALUE (DECL_ASSEMBLER_NAME (TYPE_NAME (t)));
kono
parents:
diff changeset
320 }
kono
parents:
diff changeset
321
kono
parents:
diff changeset
322 /* Return the computed hashcode for ODR_TYPE. */
kono
parents:
diff changeset
323
kono
parents:
diff changeset
324 inline hashval_t
kono
parents:
diff changeset
325 odr_name_hasher::hash (const odr_type_d *odr_type)
kono
parents:
diff changeset
326 {
kono
parents:
diff changeset
327 return hash_odr_name (odr_type->type);
kono
parents:
diff changeset
328 }
kono
parents:
diff changeset
329
kono
parents:
diff changeset
330 /* For languages with One Definition Rule, work out if
kono
parents:
diff changeset
331 types are the same based on their name.
kono
parents:
diff changeset
332
kono
parents:
diff changeset
333 This is non-trivial for LTO where minor differences in
kono
parents:
diff changeset
334 the type representation may have prevented type merging
kono
parents:
diff changeset
335 to merge two copies of otherwise equivalent type.
kono
parents:
diff changeset
336
kono
parents:
diff changeset
337 Until we start streaming mangled type names, this function works
kono
parents:
diff changeset
338 only for polymorphic types.
kono
parents:
diff changeset
339 */
kono
parents:
diff changeset
340
kono
parents:
diff changeset
341 bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
342 types_same_for_odr (const_tree type1, const_tree type2)
111
kono
parents:
diff changeset
343 {
kono
parents:
diff changeset
344 gcc_checking_assert (TYPE_P (type1) && TYPE_P (type2));
kono
parents:
diff changeset
345
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
346 type1 = TYPE_MAIN_VARIANT (type1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
347 type2 = TYPE_MAIN_VARIANT (type2);
111
kono
parents:
diff changeset
348
kono
parents:
diff changeset
349 if (type1 == type2)
kono
parents:
diff changeset
350 return true;
kono
parents:
diff changeset
351
kono
parents:
diff changeset
352 if (!in_lto_p)
kono
parents:
diff changeset
353 return false;
kono
parents:
diff changeset
354
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
355 /* Anonymous namespace types are never duplicated. */
111
kono
parents:
diff changeset
356 if ((type_with_linkage_p (type1) && type_in_anonymous_namespace_p (type1))
kono
parents:
diff changeset
357 || (type_with_linkage_p (type2) && type_in_anonymous_namespace_p (type2)))
kono
parents:
diff changeset
358 return false;
kono
parents:
diff changeset
359
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
360 /* If both type has mangled defined check if they are same.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
361 Watch for anonymous types which are all mangled as "<anon">. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
362 if (!type_with_linkage_p (type1) || !type_with_linkage_p (type2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
363 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
364 if (type_in_anonymous_namespace_p (type1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
365 || type_in_anonymous_namespace_p (type2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
366 return false;
111
kono
parents:
diff changeset
367 return (DECL_ASSEMBLER_NAME (TYPE_NAME (type1))
kono
parents:
diff changeset
368 == DECL_ASSEMBLER_NAME (TYPE_NAME (type2)));
kono
parents:
diff changeset
369 }
kono
parents:
diff changeset
370
kono
parents:
diff changeset
371 /* Return true if we can decide on ODR equivalency.
kono
parents:
diff changeset
372
kono
parents:
diff changeset
373 In non-LTO it is always decide, in LTO however it depends in the type has
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
374 ODR info attached. */
111
kono
parents:
diff changeset
375
kono
parents:
diff changeset
376 bool
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
377 types_odr_comparable (tree t1, tree t2)
111
kono
parents:
diff changeset
378 {
kono
parents:
diff changeset
379 return (!in_lto_p
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
380 || TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
381 || (odr_type_p (TYPE_MAIN_VARIANT (t1))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
382 && odr_type_p (TYPE_MAIN_VARIANT (t2))));
111
kono
parents:
diff changeset
383 }
kono
parents:
diff changeset
384
kono
parents:
diff changeset
385 /* Return true if T1 and T2 are ODR equivalent. If ODR equivalency is not
kono
parents:
diff changeset
386 known, be conservative and return false. */
kono
parents:
diff changeset
387
kono
parents:
diff changeset
388 bool
kono
parents:
diff changeset
389 types_must_be_same_for_odr (tree t1, tree t2)
kono
parents:
diff changeset
390 {
kono
parents:
diff changeset
391 if (types_odr_comparable (t1, t2))
kono
parents:
diff changeset
392 return types_same_for_odr (t1, t2);
kono
parents:
diff changeset
393 else
kono
parents:
diff changeset
394 return TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2);
kono
parents:
diff changeset
395 }
kono
parents:
diff changeset
396
kono
parents:
diff changeset
397 /* If T is compound type, return type it is based on. */
kono
parents:
diff changeset
398
kono
parents:
diff changeset
399 static tree
kono
parents:
diff changeset
400 compound_type_base (const_tree t)
kono
parents:
diff changeset
401 {
kono
parents:
diff changeset
402 if (TREE_CODE (t) == ARRAY_TYPE
kono
parents:
diff changeset
403 || POINTER_TYPE_P (t)
kono
parents:
diff changeset
404 || TREE_CODE (t) == COMPLEX_TYPE
kono
parents:
diff changeset
405 || VECTOR_TYPE_P (t))
kono
parents:
diff changeset
406 return TREE_TYPE (t);
kono
parents:
diff changeset
407 if (TREE_CODE (t) == METHOD_TYPE)
kono
parents:
diff changeset
408 return TYPE_METHOD_BASETYPE (t);
kono
parents:
diff changeset
409 if (TREE_CODE (t) == OFFSET_TYPE)
kono
parents:
diff changeset
410 return TYPE_OFFSET_BASETYPE (t);
kono
parents:
diff changeset
411 return NULL_TREE;
kono
parents:
diff changeset
412 }
kono
parents:
diff changeset
413
kono
parents:
diff changeset
414 /* Return true if T is either ODR type or compound type based from it.
kono
parents:
diff changeset
415 If the function return true, we know that T is a type originating from C++
kono
parents:
diff changeset
416 source even at link-time. */
kono
parents:
diff changeset
417
kono
parents:
diff changeset
418 bool
kono
parents:
diff changeset
419 odr_or_derived_type_p (const_tree t)
kono
parents:
diff changeset
420 {
kono
parents:
diff changeset
421 do
kono
parents:
diff changeset
422 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
423 if (odr_type_p (TYPE_MAIN_VARIANT (t)))
111
kono
parents:
diff changeset
424 return true;
kono
parents:
diff changeset
425 /* Function type is a tricky one. Basically we can consider it
kono
parents:
diff changeset
426 ODR derived if return type or any of the parameters is.
kono
parents:
diff changeset
427 We need to check all parameters because LTO streaming merges
kono
parents:
diff changeset
428 common types (such as void) and they are not considered ODR then. */
kono
parents:
diff changeset
429 if (TREE_CODE (t) == FUNCTION_TYPE)
kono
parents:
diff changeset
430 {
kono
parents:
diff changeset
431 if (TYPE_METHOD_BASETYPE (t))
kono
parents:
diff changeset
432 t = TYPE_METHOD_BASETYPE (t);
kono
parents:
diff changeset
433 else
kono
parents:
diff changeset
434 {
kono
parents:
diff changeset
435 if (TREE_TYPE (t) && odr_or_derived_type_p (TREE_TYPE (t)))
kono
parents:
diff changeset
436 return true;
kono
parents:
diff changeset
437 for (t = TYPE_ARG_TYPES (t); t; t = TREE_CHAIN (t))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
438 if (odr_or_derived_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (t))))
111
kono
parents:
diff changeset
439 return true;
kono
parents:
diff changeset
440 return false;
kono
parents:
diff changeset
441 }
kono
parents:
diff changeset
442 }
kono
parents:
diff changeset
443 else
kono
parents:
diff changeset
444 t = compound_type_base (t);
kono
parents:
diff changeset
445 }
kono
parents:
diff changeset
446 while (t);
kono
parents:
diff changeset
447 return t;
kono
parents:
diff changeset
448 }
kono
parents:
diff changeset
449
kono
parents:
diff changeset
450 /* Compare types T1 and T2 and return true if they are
kono
parents:
diff changeset
451 equivalent. */
kono
parents:
diff changeset
452
kono
parents:
diff changeset
453 inline bool
kono
parents:
diff changeset
454 odr_name_hasher::equal (const odr_type_d *o1, const tree_node *t2)
kono
parents:
diff changeset
455 {
kono
parents:
diff changeset
456 tree t1 = o1->type;
kono
parents:
diff changeset
457
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
458 gcc_checking_assert (TYPE_MAIN_VARIANT (t2) == t2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
459 gcc_checking_assert (TYPE_MAIN_VARIANT (t1) == t1);
111
kono
parents:
diff changeset
460 if (t1 == t2)
kono
parents:
diff changeset
461 return true;
kono
parents:
diff changeset
462 if (!in_lto_p)
kono
parents:
diff changeset
463 return false;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
464 /* Check for anonymous namespaces. */
111
kono
parents:
diff changeset
465 if ((type_with_linkage_p (t1) && type_in_anonymous_namespace_p (t1))
kono
parents:
diff changeset
466 || (type_with_linkage_p (t2) && type_in_anonymous_namespace_p (t2)))
kono
parents:
diff changeset
467 return false;
kono
parents:
diff changeset
468 gcc_checking_assert (DECL_ASSEMBLER_NAME (TYPE_NAME (t1)));
kono
parents:
diff changeset
469 gcc_checking_assert (DECL_ASSEMBLER_NAME (TYPE_NAME (t2)));
kono
parents:
diff changeset
470 return (DECL_ASSEMBLER_NAME (TYPE_NAME (t1))
kono
parents:
diff changeset
471 == DECL_ASSEMBLER_NAME (TYPE_NAME (t2)));
kono
parents:
diff changeset
472 }
kono
parents:
diff changeset
473
kono
parents:
diff changeset
474 /* Free ODR type V. */
kono
parents:
diff changeset
475
kono
parents:
diff changeset
476 inline void
kono
parents:
diff changeset
477 odr_name_hasher::remove (odr_type_d *v)
kono
parents:
diff changeset
478 {
kono
parents:
diff changeset
479 v->bases.release ();
kono
parents:
diff changeset
480 v->derived_types.release ();
kono
parents:
diff changeset
481 if (v->types_set)
kono
parents:
diff changeset
482 delete v->types_set;
kono
parents:
diff changeset
483 ggc_free (v);
kono
parents:
diff changeset
484 }
kono
parents:
diff changeset
485
kono
parents:
diff changeset
486 /* ODR type hash used to look up ODR type based on tree type node. */
kono
parents:
diff changeset
487
kono
parents:
diff changeset
488 typedef hash_table<odr_name_hasher> odr_hash_type;
kono
parents:
diff changeset
489 static odr_hash_type *odr_hash;
kono
parents:
diff changeset
490
kono
parents:
diff changeset
491 /* ODR types are also stored into ODR_TYPE vector to allow consistent
kono
parents:
diff changeset
492 walking. Bases appear before derived types. Vector is garbage collected
kono
parents:
diff changeset
493 so we won't end up visiting empty types. */
kono
parents:
diff changeset
494
kono
parents:
diff changeset
495 static GTY(()) vec <odr_type, va_gc> *odr_types_ptr;
kono
parents:
diff changeset
496 #define odr_types (*odr_types_ptr)
kono
parents:
diff changeset
497
kono
parents:
diff changeset
498 /* Set TYPE_BINFO of TYPE and its variants to BINFO. */
kono
parents:
diff changeset
499 void
kono
parents:
diff changeset
500 set_type_binfo (tree type, tree binfo)
kono
parents:
diff changeset
501 {
kono
parents:
diff changeset
502 for (; type; type = TYPE_NEXT_VARIANT (type))
kono
parents:
diff changeset
503 if (COMPLETE_TYPE_P (type))
kono
parents:
diff changeset
504 TYPE_BINFO (type) = binfo;
kono
parents:
diff changeset
505 else
kono
parents:
diff changeset
506 gcc_assert (!TYPE_BINFO (type));
kono
parents:
diff changeset
507 }
kono
parents:
diff changeset
508
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
509 /* Return true if type variants match.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
510 This assumes that we already verified that T1 and T2 are variants of the
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
511 same type. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
512
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
513 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
514 type_variants_equivalent_p (tree t1, tree t2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
515 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
516 if (TYPE_QUALS (t1) != TYPE_QUALS (t2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
517 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
518
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
519 if (comp_type_attributes (t1, t2) != 1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
520 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
521
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
522 if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
523 && TYPE_ALIGN (t1) != TYPE_ALIGN (t2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
524 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
525
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
526 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
527 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
528
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
529 /* Compare T1 and T2 based on name or structure. */
111
kono
parents:
diff changeset
530
kono
parents:
diff changeset
531 static bool
kono
parents:
diff changeset
532 odr_subtypes_equivalent_p (tree t1, tree t2,
kono
parents:
diff changeset
533 hash_set<type_pair> *visited,
kono
parents:
diff changeset
534 location_t loc1, location_t loc2)
kono
parents:
diff changeset
535 {
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 /* This can happen in incomplete types that should be handled earlier. */
kono
parents:
diff changeset
538 gcc_assert (t1 && t2);
kono
parents:
diff changeset
539
kono
parents:
diff changeset
540 if (t1 == t2)
kono
parents:
diff changeset
541 return true;
kono
parents:
diff changeset
542
kono
parents:
diff changeset
543 /* Anonymous namespace types must match exactly. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
544 if ((type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
545 && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
546 || (type_with_linkage_p (TYPE_MAIN_VARIANT (t2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
547 && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t2))))
111
kono
parents:
diff changeset
548 return false;
kono
parents:
diff changeset
549
kono
parents:
diff changeset
550 /* For ODR types be sure to compare their names.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
551 To support -Wno-odr-type-merging we allow one type to be non-ODR
111
kono
parents:
diff changeset
552 and other ODR even though it is a violation. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
553 if (types_odr_comparable (t1, t2))
111
kono
parents:
diff changeset
554 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
555 if (t1 != t2
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
556 && odr_type_p (TYPE_MAIN_VARIANT (t1))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
557 && get_odr_type (TYPE_MAIN_VARIANT (t1), true)->odr_violated)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
558 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
559 if (!types_same_for_odr (t1, t2))
111
kono
parents:
diff changeset
560 return false;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
561 if (!type_variants_equivalent_p (t1, t2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
562 return false;
111
kono
parents:
diff changeset
563 /* Limit recursion: If subtypes are ODR types and we know
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
564 that they are same, be happy. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
565 if (odr_type_p (TYPE_MAIN_VARIANT (t1)))
111
kono
parents:
diff changeset
566 return true;
kono
parents:
diff changeset
567 }
kono
parents:
diff changeset
568
kono
parents:
diff changeset
569 /* Component types, builtins and possibly violating ODR types
kono
parents:
diff changeset
570 have to be compared structurally. */
kono
parents:
diff changeset
571 if (TREE_CODE (t1) != TREE_CODE (t2))
kono
parents:
diff changeset
572 return false;
kono
parents:
diff changeset
573 if (AGGREGATE_TYPE_P (t1)
kono
parents:
diff changeset
574 && (TYPE_NAME (t1) == NULL_TREE) != (TYPE_NAME (t2) == NULL_TREE))
kono
parents:
diff changeset
575 return false;
kono
parents:
diff changeset
576
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
577 type_pair pair={TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2)};
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
578 if (TYPE_UID (TYPE_MAIN_VARIANT (t1)) > TYPE_UID (TYPE_MAIN_VARIANT (t2)))
111
kono
parents:
diff changeset
579 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
580 pair.first = TYPE_MAIN_VARIANT (t2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
581 pair.second = TYPE_MAIN_VARIANT (t1);
111
kono
parents:
diff changeset
582 }
kono
parents:
diff changeset
583 if (visited->add (pair))
kono
parents:
diff changeset
584 return true;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
585 if (!odr_types_equivalent_p (TYPE_MAIN_VARIANT (t1), TYPE_MAIN_VARIANT (t2),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
586 false, NULL, visited, loc1, loc2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
587 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
588 if (!type_variants_equivalent_p (t1, t2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
589 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
590 return true;
111
kono
parents:
diff changeset
591 }
kono
parents:
diff changeset
592
kono
parents:
diff changeset
593 /* Return true if DECL1 and DECL2 are identical methods. Consider
kono
parents:
diff changeset
594 name equivalent to name.localalias.xyz. */
kono
parents:
diff changeset
595
kono
parents:
diff changeset
596 static bool
kono
parents:
diff changeset
597 methods_equal_p (tree decl1, tree decl2)
kono
parents:
diff changeset
598 {
kono
parents:
diff changeset
599 if (DECL_ASSEMBLER_NAME (decl1) == DECL_ASSEMBLER_NAME (decl2))
kono
parents:
diff changeset
600 return true;
kono
parents:
diff changeset
601 const char sep = symbol_table::symbol_suffix_separator ();
kono
parents:
diff changeset
602
kono
parents:
diff changeset
603 const char *name1 = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl1));
kono
parents:
diff changeset
604 const char *ptr1 = strchr (name1, sep);
kono
parents:
diff changeset
605 int len1 = ptr1 ? ptr1 - name1 : strlen (name1);
kono
parents:
diff changeset
606
kono
parents:
diff changeset
607 const char *name2 = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl2));
kono
parents:
diff changeset
608 const char *ptr2 = strchr (name2, sep);
kono
parents:
diff changeset
609 int len2 = ptr2 ? ptr2 - name2 : strlen (name2);
kono
parents:
diff changeset
610
kono
parents:
diff changeset
611 if (len1 != len2)
kono
parents:
diff changeset
612 return false;
kono
parents:
diff changeset
613 return !strncmp (name1, name2, len1);
kono
parents:
diff changeset
614 }
kono
parents:
diff changeset
615
kono
parents:
diff changeset
616 /* Compare two virtual tables, PREVAILING and VTABLE and output ODR
kono
parents:
diff changeset
617 violation warnings. */
kono
parents:
diff changeset
618
kono
parents:
diff changeset
619 void
kono
parents:
diff changeset
620 compare_virtual_tables (varpool_node *prevailing, varpool_node *vtable)
kono
parents:
diff changeset
621 {
kono
parents:
diff changeset
622 int n1, n2;
kono
parents:
diff changeset
623
kono
parents:
diff changeset
624 if (DECL_VIRTUAL_P (prevailing->decl) != DECL_VIRTUAL_P (vtable->decl))
kono
parents:
diff changeset
625 {
kono
parents:
diff changeset
626 odr_violation_reported = true;
kono
parents:
diff changeset
627 if (DECL_VIRTUAL_P (prevailing->decl))
kono
parents:
diff changeset
628 {
kono
parents:
diff changeset
629 varpool_node *tmp = prevailing;
kono
parents:
diff changeset
630 prevailing = vtable;
kono
parents:
diff changeset
631 vtable = tmp;
kono
parents:
diff changeset
632 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
633 auto_diagnostic_group d;
111
kono
parents:
diff changeset
634 if (warning_at (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
635 (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
kono
parents:
diff changeset
636 OPT_Wodr,
kono
parents:
diff changeset
637 "virtual table of type %qD violates one definition rule",
kono
parents:
diff changeset
638 DECL_CONTEXT (vtable->decl)))
kono
parents:
diff changeset
639 inform (DECL_SOURCE_LOCATION (prevailing->decl),
kono
parents:
diff changeset
640 "variable of same assembler name as the virtual table is "
kono
parents:
diff changeset
641 "defined in another translation unit");
kono
parents:
diff changeset
642 return;
kono
parents:
diff changeset
643 }
kono
parents:
diff changeset
644 if (!prevailing->definition || !vtable->definition)
kono
parents:
diff changeset
645 return;
kono
parents:
diff changeset
646
kono
parents:
diff changeset
647 /* If we do not stream ODR type info, do not bother to do useful compare. */
kono
parents:
diff changeset
648 if (!TYPE_BINFO (DECL_CONTEXT (vtable->decl))
kono
parents:
diff changeset
649 || !polymorphic_type_binfo_p (TYPE_BINFO (DECL_CONTEXT (vtable->decl))))
kono
parents:
diff changeset
650 return;
kono
parents:
diff changeset
651
kono
parents:
diff changeset
652 odr_type class_type = get_odr_type (DECL_CONTEXT (vtable->decl), true);
kono
parents:
diff changeset
653
kono
parents:
diff changeset
654 if (class_type->odr_violated)
kono
parents:
diff changeset
655 return;
kono
parents:
diff changeset
656
kono
parents:
diff changeset
657 for (n1 = 0, n2 = 0; true; n1++, n2++)
kono
parents:
diff changeset
658 {
kono
parents:
diff changeset
659 struct ipa_ref *ref1, *ref2;
kono
parents:
diff changeset
660 bool end1, end2;
kono
parents:
diff changeset
661
kono
parents:
diff changeset
662 end1 = !prevailing->iterate_reference (n1, ref1);
kono
parents:
diff changeset
663 end2 = !vtable->iterate_reference (n2, ref2);
kono
parents:
diff changeset
664
kono
parents:
diff changeset
665 /* !DECL_VIRTUAL_P means RTTI entry;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
666 We warn when RTTI is lost because non-RTTI prevails; we silently
111
kono
parents:
diff changeset
667 accept the other case. */
kono
parents:
diff changeset
668 while (!end2
kono
parents:
diff changeset
669 && (end1
kono
parents:
diff changeset
670 || (methods_equal_p (ref1->referred->decl,
kono
parents:
diff changeset
671 ref2->referred->decl)
kono
parents:
diff changeset
672 && TREE_CODE (ref1->referred->decl) == FUNCTION_DECL))
kono
parents:
diff changeset
673 && TREE_CODE (ref2->referred->decl) != FUNCTION_DECL)
kono
parents:
diff changeset
674 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
675 if (!class_type->rtti_broken)
111
kono
parents:
diff changeset
676 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
677 auto_diagnostic_group d;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
678 if (warning_at (DECL_SOURCE_LOCATION
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
679 (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
680 OPT_Wodr,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
681 "virtual table of type %qD contains RTTI "
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
682 "information",
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
683 DECL_CONTEXT (vtable->decl)))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
684 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
685 inform (DECL_SOURCE_LOCATION
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
686 (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
687 "but is prevailed by one without from other"
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
688 " translation unit");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
689 inform (DECL_SOURCE_LOCATION
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
690 (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
691 "RTTI will not work on this type");
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
692 class_type->rtti_broken = true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
693 }
111
kono
parents:
diff changeset
694 }
kono
parents:
diff changeset
695 n2++;
kono
parents:
diff changeset
696 end2 = !vtable->iterate_reference (n2, ref2);
kono
parents:
diff changeset
697 }
kono
parents:
diff changeset
698 while (!end1
kono
parents:
diff changeset
699 && (end2
kono
parents:
diff changeset
700 || (methods_equal_p (ref2->referred->decl, ref1->referred->decl)
kono
parents:
diff changeset
701 && TREE_CODE (ref2->referred->decl) == FUNCTION_DECL))
kono
parents:
diff changeset
702 && TREE_CODE (ref1->referred->decl) != FUNCTION_DECL)
kono
parents:
diff changeset
703 {
kono
parents:
diff changeset
704 n1++;
kono
parents:
diff changeset
705 end1 = !prevailing->iterate_reference (n1, ref1);
kono
parents:
diff changeset
706 }
kono
parents:
diff changeset
707
kono
parents:
diff changeset
708 /* Finished? */
kono
parents:
diff changeset
709 if (end1 && end2)
kono
parents:
diff changeset
710 {
kono
parents:
diff changeset
711 /* Extra paranoia; compare the sizes. We do not have information
kono
parents:
diff changeset
712 about virtual inheritance offsets, so just be sure that these
kono
parents:
diff changeset
713 match.
kono
parents:
diff changeset
714 Do this as very last check so the not very informative error
kono
parents:
diff changeset
715 is not output too often. */
kono
parents:
diff changeset
716 if (DECL_SIZE (prevailing->decl) != DECL_SIZE (vtable->decl))
kono
parents:
diff changeset
717 {
kono
parents:
diff changeset
718 class_type->odr_violated = true;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
719 auto_diagnostic_group d;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
720 tree ctx = TYPE_NAME (DECL_CONTEXT (vtable->decl));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
721 if (warning_at (DECL_SOURCE_LOCATION (ctx), OPT_Wodr,
111
kono
parents:
diff changeset
722 "virtual table of type %qD violates "
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
723 "one definition rule",
111
kono
parents:
diff changeset
724 DECL_CONTEXT (vtable->decl)))
kono
parents:
diff changeset
725 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
726 ctx = TYPE_NAME (DECL_CONTEXT (prevailing->decl));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
727 inform (DECL_SOURCE_LOCATION (ctx),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
728 "the conflicting type defined in another translation"
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
729 " unit has virtual table of different size");
111
kono
parents:
diff changeset
730 }
kono
parents:
diff changeset
731 }
kono
parents:
diff changeset
732 return;
kono
parents:
diff changeset
733 }
kono
parents:
diff changeset
734
kono
parents:
diff changeset
735 if (!end1 && !end2)
kono
parents:
diff changeset
736 {
kono
parents:
diff changeset
737 if (methods_equal_p (ref1->referred->decl, ref2->referred->decl))
kono
parents:
diff changeset
738 continue;
kono
parents:
diff changeset
739
kono
parents:
diff changeset
740 class_type->odr_violated = true;
kono
parents:
diff changeset
741
kono
parents:
diff changeset
742 /* If the loops above stopped on non-virtual pointer, we have
kono
parents:
diff changeset
743 mismatch in RTTI information mangling. */
kono
parents:
diff changeset
744 if (TREE_CODE (ref1->referred->decl) != FUNCTION_DECL
kono
parents:
diff changeset
745 && TREE_CODE (ref2->referred->decl) != FUNCTION_DECL)
kono
parents:
diff changeset
746 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
747 auto_diagnostic_group d;
111
kono
parents:
diff changeset
748 if (warning_at (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
749 (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
kono
parents:
diff changeset
750 OPT_Wodr,
kono
parents:
diff changeset
751 "virtual table of type %qD violates "
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
752 "one definition rule",
111
kono
parents:
diff changeset
753 DECL_CONTEXT (vtable->decl)))
kono
parents:
diff changeset
754 {
kono
parents:
diff changeset
755 inform (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
756 (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
kono
parents:
diff changeset
757 "the conflicting type defined in another translation "
kono
parents:
diff changeset
758 "unit with different RTTI information");
kono
parents:
diff changeset
759 }
kono
parents:
diff changeset
760 return;
kono
parents:
diff changeset
761 }
kono
parents:
diff changeset
762 /* At this point both REF1 and REF2 points either to virtual table
kono
parents:
diff changeset
763 or virtual method. If one points to virtual table and other to
kono
parents:
diff changeset
764 method we can complain the same way as if one table was shorter
kono
parents:
diff changeset
765 than other pointing out the extra method. */
kono
parents:
diff changeset
766 if (TREE_CODE (ref1->referred->decl)
kono
parents:
diff changeset
767 != TREE_CODE (ref2->referred->decl))
kono
parents:
diff changeset
768 {
kono
parents:
diff changeset
769 if (VAR_P (ref1->referred->decl))
kono
parents:
diff changeset
770 end1 = true;
kono
parents:
diff changeset
771 else if (VAR_P (ref2->referred->decl))
kono
parents:
diff changeset
772 end2 = true;
kono
parents:
diff changeset
773 }
kono
parents:
diff changeset
774 }
kono
parents:
diff changeset
775
kono
parents:
diff changeset
776 class_type->odr_violated = true;
kono
parents:
diff changeset
777
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
778 /* Complain about size mismatch. Either we have too many virtual
111
kono
parents:
diff changeset
779 functions or too many virtual table pointers. */
kono
parents:
diff changeset
780 if (end1 || end2)
kono
parents:
diff changeset
781 {
kono
parents:
diff changeset
782 if (end1)
kono
parents:
diff changeset
783 {
kono
parents:
diff changeset
784 varpool_node *tmp = prevailing;
kono
parents:
diff changeset
785 prevailing = vtable;
kono
parents:
diff changeset
786 vtable = tmp;
kono
parents:
diff changeset
787 ref1 = ref2;
kono
parents:
diff changeset
788 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
789 auto_diagnostic_group d;
111
kono
parents:
diff changeset
790 if (warning_at (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
791 (TYPE_NAME (DECL_CONTEXT (vtable->decl))),
kono
parents:
diff changeset
792 OPT_Wodr,
kono
parents:
diff changeset
793 "virtual table of type %qD violates "
kono
parents:
diff changeset
794 "one definition rule",
kono
parents:
diff changeset
795 DECL_CONTEXT (vtable->decl)))
kono
parents:
diff changeset
796 {
kono
parents:
diff changeset
797 if (TREE_CODE (ref1->referring->decl) == FUNCTION_DECL)
kono
parents:
diff changeset
798 {
kono
parents:
diff changeset
799 inform (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
800 (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
kono
parents:
diff changeset
801 "the conflicting type defined in another translation "
kono
parents:
diff changeset
802 "unit");
kono
parents:
diff changeset
803 inform (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
804 (TYPE_NAME (DECL_CONTEXT (ref1->referring->decl))),
kono
parents:
diff changeset
805 "contains additional virtual method %qD",
kono
parents:
diff changeset
806 ref1->referred->decl);
kono
parents:
diff changeset
807 }
kono
parents:
diff changeset
808 else
kono
parents:
diff changeset
809 {
kono
parents:
diff changeset
810 inform (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
811 (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
kono
parents:
diff changeset
812 "the conflicting type defined in another translation "
kono
parents:
diff changeset
813 "unit has virtual table with more entries");
kono
parents:
diff changeset
814 }
kono
parents:
diff changeset
815 }
kono
parents:
diff changeset
816 return;
kono
parents:
diff changeset
817 }
kono
parents:
diff changeset
818
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
819 /* And in the last case we have either mismatch in between two virtual
111
kono
parents:
diff changeset
820 methods or two virtual table pointers. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
821 auto_diagnostic_group d;
111
kono
parents:
diff changeset
822 if (warning_at (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
823 (TYPE_NAME (DECL_CONTEXT (vtable->decl))), OPT_Wodr,
kono
parents:
diff changeset
824 "virtual table of type %qD violates "
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
825 "one definition rule",
111
kono
parents:
diff changeset
826 DECL_CONTEXT (vtable->decl)))
kono
parents:
diff changeset
827 {
kono
parents:
diff changeset
828 if (TREE_CODE (ref1->referred->decl) == FUNCTION_DECL)
kono
parents:
diff changeset
829 {
kono
parents:
diff changeset
830 inform (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
831 (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
kono
parents:
diff changeset
832 "the conflicting type defined in another translation "
kono
parents:
diff changeset
833 "unit");
kono
parents:
diff changeset
834 gcc_assert (TREE_CODE (ref2->referred->decl)
kono
parents:
diff changeset
835 == FUNCTION_DECL);
kono
parents:
diff changeset
836 inform (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
837 (ref1->referred->ultimate_alias_target ()->decl),
kono
parents:
diff changeset
838 "virtual method %qD",
kono
parents:
diff changeset
839 ref1->referred->ultimate_alias_target ()->decl);
kono
parents:
diff changeset
840 inform (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
841 (ref2->referred->ultimate_alias_target ()->decl),
kono
parents:
diff changeset
842 "ought to match virtual method %qD but does not",
kono
parents:
diff changeset
843 ref2->referred->ultimate_alias_target ()->decl);
kono
parents:
diff changeset
844 }
kono
parents:
diff changeset
845 else
kono
parents:
diff changeset
846 inform (DECL_SOURCE_LOCATION
kono
parents:
diff changeset
847 (TYPE_NAME (DECL_CONTEXT (prevailing->decl))),
kono
parents:
diff changeset
848 "the conflicting type defined in another translation "
kono
parents:
diff changeset
849 "unit has virtual table with different contents");
kono
parents:
diff changeset
850 return;
kono
parents:
diff changeset
851 }
kono
parents:
diff changeset
852 }
kono
parents:
diff changeset
853 }
kono
parents:
diff changeset
854
kono
parents:
diff changeset
855 /* Output ODR violation warning about T1 and T2 with REASON.
kono
parents:
diff changeset
856 Display location of ST1 and ST2 if REASON speaks about field or
kono
parents:
diff changeset
857 method of the type.
kono
parents:
diff changeset
858 If WARN is false, do nothing. Set WARNED if warning was indeed
kono
parents:
diff changeset
859 output. */
kono
parents:
diff changeset
860
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
861 static void
111
kono
parents:
diff changeset
862 warn_odr (tree t1, tree t2, tree st1, tree st2,
kono
parents:
diff changeset
863 bool warn, bool *warned, const char *reason)
kono
parents:
diff changeset
864 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
865 tree decl2 = TYPE_NAME (TYPE_MAIN_VARIANT (t2));
111
kono
parents:
diff changeset
866 if (warned)
kono
parents:
diff changeset
867 *warned = false;
kono
parents:
diff changeset
868
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
869 if (!warn || !TYPE_NAME(TYPE_MAIN_VARIANT (t1)))
111
kono
parents:
diff changeset
870 return;
kono
parents:
diff changeset
871
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
872 /* ODR warnings are output during LTO streaming; we must apply location
111
kono
parents:
diff changeset
873 cache for potential warnings to be output correctly. */
kono
parents:
diff changeset
874 if (lto_location_cache::current_cache)
kono
parents:
diff changeset
875 lto_location_cache::current_cache->apply_location_cache ();
kono
parents:
diff changeset
876
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
877 auto_diagnostic_group d;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
878 if (t1 != TYPE_MAIN_VARIANT (t1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
879 && TYPE_NAME (t1) != TYPE_NAME (TYPE_MAIN_VARIANT (t1)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
880 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
881 if (!warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (TYPE_MAIN_VARIANT (t1))),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
882 OPT_Wodr, "type %qT (typedef of %qT) violates the "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
883 "C++ One Definition Rule",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
884 t1, TYPE_MAIN_VARIANT (t1)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
885 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
886 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
887 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
888 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
889 if (!warning_at (DECL_SOURCE_LOCATION (TYPE_NAME (TYPE_MAIN_VARIANT (t1))),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
890 OPT_Wodr, "type %qT violates the C++ One Definition Rule",
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
891 t1))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
892 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
893 }
111
kono
parents:
diff changeset
894 if (!st1 && !st2)
kono
parents:
diff changeset
895 ;
kono
parents:
diff changeset
896 /* For FIELD_DECL support also case where one of fields is
kono
parents:
diff changeset
897 NULL - this is used when the structures have mismatching number of
kono
parents:
diff changeset
898 elements. */
kono
parents:
diff changeset
899 else if (!st1 || TREE_CODE (st1) == FIELD_DECL)
kono
parents:
diff changeset
900 {
kono
parents:
diff changeset
901 inform (DECL_SOURCE_LOCATION (decl2),
kono
parents:
diff changeset
902 "a different type is defined in another translation unit");
kono
parents:
diff changeset
903 if (!st1)
kono
parents:
diff changeset
904 {
kono
parents:
diff changeset
905 st1 = st2;
kono
parents:
diff changeset
906 st2 = NULL;
kono
parents:
diff changeset
907 }
kono
parents:
diff changeset
908 inform (DECL_SOURCE_LOCATION (st1),
kono
parents:
diff changeset
909 "the first difference of corresponding definitions is field %qD",
kono
parents:
diff changeset
910 st1);
kono
parents:
diff changeset
911 if (st2)
kono
parents:
diff changeset
912 decl2 = st2;
kono
parents:
diff changeset
913 }
kono
parents:
diff changeset
914 else if (TREE_CODE (st1) == FUNCTION_DECL)
kono
parents:
diff changeset
915 {
kono
parents:
diff changeset
916 inform (DECL_SOURCE_LOCATION (decl2),
kono
parents:
diff changeset
917 "a different type is defined in another translation unit");
kono
parents:
diff changeset
918 inform (DECL_SOURCE_LOCATION (st1),
kono
parents:
diff changeset
919 "the first difference of corresponding definitions is method %qD",
kono
parents:
diff changeset
920 st1);
kono
parents:
diff changeset
921 decl2 = st2;
kono
parents:
diff changeset
922 }
kono
parents:
diff changeset
923 else
kono
parents:
diff changeset
924 return;
kono
parents:
diff changeset
925 inform (DECL_SOURCE_LOCATION (decl2), reason);
kono
parents:
diff changeset
926
kono
parents:
diff changeset
927 if (warned)
kono
parents:
diff changeset
928 *warned = true;
kono
parents:
diff changeset
929 }
kono
parents:
diff changeset
930
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
931 /* Return true if T1 and T2 are incompatible and we want to recursively
111
kono
parents:
diff changeset
932 dive into them from warn_type_mismatch to give sensible answer. */
kono
parents:
diff changeset
933
kono
parents:
diff changeset
934 static bool
kono
parents:
diff changeset
935 type_mismatch_p (tree t1, tree t2)
kono
parents:
diff changeset
936 {
kono
parents:
diff changeset
937 if (odr_or_derived_type_p (t1) && odr_or_derived_type_p (t2)
kono
parents:
diff changeset
938 && !odr_types_equivalent_p (t1, t2))
kono
parents:
diff changeset
939 return true;
kono
parents:
diff changeset
940 return !types_compatible_p (t1, t2);
kono
parents:
diff changeset
941 }
kono
parents:
diff changeset
942
kono
parents:
diff changeset
943
kono
parents:
diff changeset
944 /* Types T1 and T2 was found to be incompatible in a context they can't
kono
parents:
diff changeset
945 (either used to declare a symbol of same assembler name or unified by
kono
parents:
diff changeset
946 ODR rule). We already output warning about this, but if possible, output
kono
parents:
diff changeset
947 extra information on how the types mismatch.
kono
parents:
diff changeset
948
kono
parents:
diff changeset
949 This is hard to do in general. We basically handle the common cases.
kono
parents:
diff changeset
950
kono
parents:
diff changeset
951 If LOC1 and LOC2 are meaningful locations, use it in the case the types
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
952 themselves do not have one. */
111
kono
parents:
diff changeset
953
kono
parents:
diff changeset
954 void
kono
parents:
diff changeset
955 warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2)
kono
parents:
diff changeset
956 {
kono
parents:
diff changeset
957 /* Location of type is known only if it has TYPE_NAME and the name is
kono
parents:
diff changeset
958 TYPE_DECL. */
kono
parents:
diff changeset
959 location_t loc_t1 = TYPE_NAME (t1) && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL
kono
parents:
diff changeset
960 ? DECL_SOURCE_LOCATION (TYPE_NAME (t1))
kono
parents:
diff changeset
961 : UNKNOWN_LOCATION;
kono
parents:
diff changeset
962 location_t loc_t2 = TYPE_NAME (t2) && TREE_CODE (TYPE_NAME (t2)) == TYPE_DECL
kono
parents:
diff changeset
963 ? DECL_SOURCE_LOCATION (TYPE_NAME (t2))
kono
parents:
diff changeset
964 : UNKNOWN_LOCATION;
kono
parents:
diff changeset
965 bool loc_t2_useful = false;
kono
parents:
diff changeset
966
kono
parents:
diff changeset
967 /* With LTO it is a common case that the location of both types match.
kono
parents:
diff changeset
968 See if T2 has a location that is different from T1. If so, we will
kono
parents:
diff changeset
969 inform user about the location.
kono
parents:
diff changeset
970 Do not consider the location passed to us in LOC1/LOC2 as those are
kono
parents:
diff changeset
971 already output. */
kono
parents:
diff changeset
972 if (loc_t2 > BUILTINS_LOCATION && loc_t2 != loc_t1)
kono
parents:
diff changeset
973 {
kono
parents:
diff changeset
974 if (loc_t1 <= BUILTINS_LOCATION)
kono
parents:
diff changeset
975 loc_t2_useful = true;
kono
parents:
diff changeset
976 else
kono
parents:
diff changeset
977 {
kono
parents:
diff changeset
978 expanded_location xloc1 = expand_location (loc_t1);
kono
parents:
diff changeset
979 expanded_location xloc2 = expand_location (loc_t2);
kono
parents:
diff changeset
980
kono
parents:
diff changeset
981 if (strcmp (xloc1.file, xloc2.file)
kono
parents:
diff changeset
982 || xloc1.line != xloc2.line
kono
parents:
diff changeset
983 || xloc1.column != xloc2.column)
kono
parents:
diff changeset
984 loc_t2_useful = true;
kono
parents:
diff changeset
985 }
kono
parents:
diff changeset
986 }
kono
parents:
diff changeset
987
kono
parents:
diff changeset
988 if (loc_t1 <= BUILTINS_LOCATION)
kono
parents:
diff changeset
989 loc_t1 = loc1;
kono
parents:
diff changeset
990 if (loc_t2 <= BUILTINS_LOCATION)
kono
parents:
diff changeset
991 loc_t2 = loc2;
kono
parents:
diff changeset
992
kono
parents:
diff changeset
993 location_t loc = loc_t1 <= BUILTINS_LOCATION ? loc_t2 : loc_t1;
kono
parents:
diff changeset
994
kono
parents:
diff changeset
995 /* It is a quite common bug to reference anonymous namespace type in
kono
parents:
diff changeset
996 non-anonymous namespace class. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
997 tree mt1 = TYPE_MAIN_VARIANT (t1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
998 tree mt2 = TYPE_MAIN_VARIANT (t2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
999 if ((type_with_linkage_p (mt1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1000 && type_in_anonymous_namespace_p (mt1))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1001 || (type_with_linkage_p (mt2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1002 && type_in_anonymous_namespace_p (mt2)))
111
kono
parents:
diff changeset
1003 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1004 if (!type_with_linkage_p (mt1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1005 || !type_in_anonymous_namespace_p (mt1))
111
kono
parents:
diff changeset
1006 {
kono
parents:
diff changeset
1007 std::swap (t1, t2);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1008 std::swap (mt1, mt2);
111
kono
parents:
diff changeset
1009 std::swap (loc_t1, loc_t2);
kono
parents:
diff changeset
1010 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1011 gcc_assert (TYPE_NAME (mt1)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1012 && TREE_CODE (TYPE_NAME (mt1)) == TYPE_DECL);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1013 tree n1 = TYPE_NAME (mt1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1014 tree n2 = TYPE_NAME (mt2) ? TYPE_NAME (mt2) : NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1015
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1016 if (TREE_CODE (n1) == TYPE_DECL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1017 n1 = DECL_NAME (n1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1018 if (n2 && TREE_CODE (n2) == TYPE_DECL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1019 n2 = DECL_NAME (n2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1020 /* Most of the time, the type names will match, do not be unnecessarily
111
kono
parents:
diff changeset
1021 verbose. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1022 if (n1 != n2)
111
kono
parents:
diff changeset
1023 inform (loc_t1,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1024 "type %qT defined in anonymous namespace cannot match "
111
kono
parents:
diff changeset
1025 "type %qT across the translation unit boundary",
kono
parents:
diff changeset
1026 t1, t2);
kono
parents:
diff changeset
1027 else
kono
parents:
diff changeset
1028 inform (loc_t1,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1029 "type %qT defined in anonymous namespace cannot match "
111
kono
parents:
diff changeset
1030 "across the translation unit boundary",
kono
parents:
diff changeset
1031 t1);
kono
parents:
diff changeset
1032 if (loc_t2_useful)
kono
parents:
diff changeset
1033 inform (loc_t2,
kono
parents:
diff changeset
1034 "the incompatible type defined in another translation unit");
kono
parents:
diff changeset
1035 return;
kono
parents:
diff changeset
1036 }
kono
parents:
diff changeset
1037 /* If types have mangled ODR names and they are different, it is most
kono
parents:
diff changeset
1038 informative to output those.
kono
parents:
diff changeset
1039 This also covers types defined in different namespaces. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1040 const char *odr1 = get_odr_name_for_type (mt1);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1041 const char *odr2 = get_odr_name_for_type (mt2);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1042 if (odr1 != NULL && odr2 != NULL && odr1 != odr2)
111
kono
parents:
diff changeset
1043 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1044 const int opts = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1045 char *name1 = xstrdup (cplus_demangle (odr1, opts));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1046 char *name2 = cplus_demangle (odr2, opts);
111
kono
parents:
diff changeset
1047 if (name1 && name2 && strcmp (name1, name2))
kono
parents:
diff changeset
1048 {
kono
parents:
diff changeset
1049 inform (loc_t1,
kono
parents:
diff changeset
1050 "type name %qs should match type name %qs",
kono
parents:
diff changeset
1051 name1, name2);
kono
parents:
diff changeset
1052 if (loc_t2_useful)
kono
parents:
diff changeset
1053 inform (loc_t2,
kono
parents:
diff changeset
1054 "the incompatible type is defined here");
kono
parents:
diff changeset
1055 free (name1);
kono
parents:
diff changeset
1056 return;
kono
parents:
diff changeset
1057 }
kono
parents:
diff changeset
1058 free (name1);
kono
parents:
diff changeset
1059 }
kono
parents:
diff changeset
1060 /* A tricky case are compound types. Often they appear the same in source
kono
parents:
diff changeset
1061 code and the mismatch is dragged in by type they are build from.
kono
parents:
diff changeset
1062 Look for those differences in subtypes and try to be informative. In other
kono
parents:
diff changeset
1063 cases just output nothing because the source code is probably different
kono
parents:
diff changeset
1064 and in this case we already output a all necessary info. */
kono
parents:
diff changeset
1065 if (!TYPE_NAME (t1) || !TYPE_NAME (t2))
kono
parents:
diff changeset
1066 {
kono
parents:
diff changeset
1067 if (TREE_CODE (t1) == TREE_CODE (t2))
kono
parents:
diff changeset
1068 {
kono
parents:
diff changeset
1069 if (TREE_CODE (t1) == ARRAY_TYPE
kono
parents:
diff changeset
1070 && COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2))
kono
parents:
diff changeset
1071 {
kono
parents:
diff changeset
1072 tree i1 = TYPE_DOMAIN (t1);
kono
parents:
diff changeset
1073 tree i2 = TYPE_DOMAIN (t2);
kono
parents:
diff changeset
1074
kono
parents:
diff changeset
1075 if (i1 && i2
kono
parents:
diff changeset
1076 && TYPE_MAX_VALUE (i1)
kono
parents:
diff changeset
1077 && TYPE_MAX_VALUE (i2)
kono
parents:
diff changeset
1078 && !operand_equal_p (TYPE_MAX_VALUE (i1),
kono
parents:
diff changeset
1079 TYPE_MAX_VALUE (i2), 0))
kono
parents:
diff changeset
1080 {
kono
parents:
diff changeset
1081 inform (loc,
kono
parents:
diff changeset
1082 "array types have different bounds");
kono
parents:
diff changeset
1083 return;
kono
parents:
diff changeset
1084 }
kono
parents:
diff changeset
1085 }
kono
parents:
diff changeset
1086 if ((POINTER_TYPE_P (t1) || TREE_CODE (t1) == ARRAY_TYPE)
kono
parents:
diff changeset
1087 && type_mismatch_p (TREE_TYPE (t1), TREE_TYPE (t2)))
kono
parents:
diff changeset
1088 warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), loc_t1, loc_t2);
kono
parents:
diff changeset
1089 else if (TREE_CODE (t1) == METHOD_TYPE
kono
parents:
diff changeset
1090 || TREE_CODE (t1) == FUNCTION_TYPE)
kono
parents:
diff changeset
1091 {
kono
parents:
diff changeset
1092 tree parms1 = NULL, parms2 = NULL;
kono
parents:
diff changeset
1093 int count = 1;
kono
parents:
diff changeset
1094
kono
parents:
diff changeset
1095 if (type_mismatch_p (TREE_TYPE (t1), TREE_TYPE (t2)))
kono
parents:
diff changeset
1096 {
kono
parents:
diff changeset
1097 inform (loc, "return value type mismatch");
kono
parents:
diff changeset
1098 warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), loc_t1,
kono
parents:
diff changeset
1099 loc_t2);
kono
parents:
diff changeset
1100 return;
kono
parents:
diff changeset
1101 }
kono
parents:
diff changeset
1102 if (prototype_p (t1) && prototype_p (t2))
kono
parents:
diff changeset
1103 for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
kono
parents:
diff changeset
1104 parms1 && parms2;
kono
parents:
diff changeset
1105 parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2),
kono
parents:
diff changeset
1106 count++)
kono
parents:
diff changeset
1107 {
kono
parents:
diff changeset
1108 if (type_mismatch_p (TREE_VALUE (parms1), TREE_VALUE (parms2)))
kono
parents:
diff changeset
1109 {
kono
parents:
diff changeset
1110 if (count == 1 && TREE_CODE (t1) == METHOD_TYPE)
kono
parents:
diff changeset
1111 inform (loc,
kono
parents:
diff changeset
1112 "implicit this pointer type mismatch");
kono
parents:
diff changeset
1113 else
kono
parents:
diff changeset
1114 inform (loc,
kono
parents:
diff changeset
1115 "type mismatch in parameter %i",
kono
parents:
diff changeset
1116 count - (TREE_CODE (t1) == METHOD_TYPE));
kono
parents:
diff changeset
1117 warn_types_mismatch (TREE_VALUE (parms1),
kono
parents:
diff changeset
1118 TREE_VALUE (parms2),
kono
parents:
diff changeset
1119 loc_t1, loc_t2);
kono
parents:
diff changeset
1120 return;
kono
parents:
diff changeset
1121 }
kono
parents:
diff changeset
1122 }
kono
parents:
diff changeset
1123 if (parms1 || parms2)
kono
parents:
diff changeset
1124 {
kono
parents:
diff changeset
1125 inform (loc,
kono
parents:
diff changeset
1126 "types have different parameter counts");
kono
parents:
diff changeset
1127 return;
kono
parents:
diff changeset
1128 }
kono
parents:
diff changeset
1129 }
kono
parents:
diff changeset
1130 }
kono
parents:
diff changeset
1131 return;
kono
parents:
diff changeset
1132 }
kono
parents:
diff changeset
1133
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1134 if (types_odr_comparable (t1, t2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1135 /* We make assign integers mangled names to be able to handle
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1136 signed/unsigned chars. Accepting them here would however lead to
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1137 confusing message like
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1138 "type ‘const int’ itself violates the C++ One Definition Rule" */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1139 && TREE_CODE (t1) != INTEGER_TYPE
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1140 && types_same_for_odr (t1, t2))
111
kono
parents:
diff changeset
1141 inform (loc_t1,
kono
parents:
diff changeset
1142 "type %qT itself violates the C++ One Definition Rule", t1);
kono
parents:
diff changeset
1143 /* Prevent pointless warnings like "struct aa" should match "struct aa". */
kono
parents:
diff changeset
1144 else if (TYPE_NAME (t1) == TYPE_NAME (t2)
kono
parents:
diff changeset
1145 && TREE_CODE (t1) == TREE_CODE (t2) && !loc_t2_useful)
kono
parents:
diff changeset
1146 return;
kono
parents:
diff changeset
1147 else
kono
parents:
diff changeset
1148 inform (loc_t1, "type %qT should match type %qT",
kono
parents:
diff changeset
1149 t1, t2);
kono
parents:
diff changeset
1150 if (loc_t2_useful)
kono
parents:
diff changeset
1151 inform (loc_t2, "the incompatible type is defined here");
kono
parents:
diff changeset
1152 }
kono
parents:
diff changeset
1153
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1154 /* Return true if T should be ignored in TYPE_FIELDS for ODR comparison. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1155
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1156 static bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1157 skip_in_fields_list_p (tree t)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1158 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1159 if (TREE_CODE (t) != FIELD_DECL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1160 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1161 /* C++ FE introduces zero sized fields depending on -std setting, see
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1162 PR89358. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1163 if (DECL_SIZE (t)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1164 && integer_zerop (DECL_SIZE (t))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1165 && DECL_ARTIFICIAL (t)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1166 && DECL_IGNORED_P (t)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1167 && !DECL_NAME (t))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1168 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1169 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1170 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1171
111
kono
parents:
diff changeset
1172 /* Compare T1 and T2, report ODR violations if WARN is true and set
kono
parents:
diff changeset
1173 WARNED to true if anything is reported. Return true if types match.
kono
parents:
diff changeset
1174 If true is returned, the types are also compatible in the sense of
kono
parents:
diff changeset
1175 gimple_canonical_types_compatible_p.
kono
parents:
diff changeset
1176 If LOC1 and LOC2 is not UNKNOWN_LOCATION it may be used to output a warning
kono
parents:
diff changeset
1177 about the type if the type itself do not have location. */
kono
parents:
diff changeset
1178
kono
parents:
diff changeset
1179 static bool
kono
parents:
diff changeset
1180 odr_types_equivalent_p (tree t1, tree t2, bool warn, bool *warned,
kono
parents:
diff changeset
1181 hash_set<type_pair> *visited,
kono
parents:
diff changeset
1182 location_t loc1, location_t loc2)
kono
parents:
diff changeset
1183 {
kono
parents:
diff changeset
1184 /* Check first for the obvious case of pointer identity. */
kono
parents:
diff changeset
1185 if (t1 == t2)
kono
parents:
diff changeset
1186 return true;
kono
parents:
diff changeset
1187
kono
parents:
diff changeset
1188 /* Can't be the same type if the types don't have the same code. */
kono
parents:
diff changeset
1189 if (TREE_CODE (t1) != TREE_CODE (t2))
kono
parents:
diff changeset
1190 {
kono
parents:
diff changeset
1191 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1192 G_("a different type is defined in another translation unit"));
kono
parents:
diff changeset
1193 return false;
kono
parents:
diff changeset
1194 }
kono
parents:
diff changeset
1195
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1196 if ((type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1197 && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1198 || (type_with_linkage_p (TYPE_MAIN_VARIANT (t2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1199 && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t2))))
111
kono
parents:
diff changeset
1200 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1201 /* We cannot trip this when comparing ODR types, only when trying to
111
kono
parents:
diff changeset
1202 match different ODR derivations from different declarations.
kono
parents:
diff changeset
1203 So WARN should be always false. */
kono
parents:
diff changeset
1204 gcc_assert (!warn);
kono
parents:
diff changeset
1205 return false;
kono
parents:
diff changeset
1206 }
kono
parents:
diff changeset
1207
kono
parents:
diff changeset
1208 if (TREE_CODE (t1) == ENUMERAL_TYPE
kono
parents:
diff changeset
1209 && TYPE_VALUES (t1) && TYPE_VALUES (t2))
kono
parents:
diff changeset
1210 {
kono
parents:
diff changeset
1211 tree v1, v2;
kono
parents:
diff changeset
1212 for (v1 = TYPE_VALUES (t1), v2 = TYPE_VALUES (t2);
kono
parents:
diff changeset
1213 v1 && v2 ; v1 = TREE_CHAIN (v1), v2 = TREE_CHAIN (v2))
kono
parents:
diff changeset
1214 {
kono
parents:
diff changeset
1215 if (TREE_PURPOSE (v1) != TREE_PURPOSE (v2))
kono
parents:
diff changeset
1216 {
kono
parents:
diff changeset
1217 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1218 G_("an enum with different value name"
kono
parents:
diff changeset
1219 " is defined in another translation unit"));
kono
parents:
diff changeset
1220 return false;
kono
parents:
diff changeset
1221 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1222 if (!operand_equal_p (TREE_VALUE (v1), TREE_VALUE (v2), 0))
111
kono
parents:
diff changeset
1223 {
kono
parents:
diff changeset
1224 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1225 G_("an enum with different values is defined"
kono
parents:
diff changeset
1226 " in another translation unit"));
kono
parents:
diff changeset
1227 return false;
kono
parents:
diff changeset
1228 }
kono
parents:
diff changeset
1229 }
kono
parents:
diff changeset
1230 if (v1 || v2)
kono
parents:
diff changeset
1231 {
kono
parents:
diff changeset
1232 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1233 G_("an enum with mismatching number of values "
kono
parents:
diff changeset
1234 "is defined in another translation unit"));
kono
parents:
diff changeset
1235 return false;
kono
parents:
diff changeset
1236 }
kono
parents:
diff changeset
1237 }
kono
parents:
diff changeset
1238
kono
parents:
diff changeset
1239 /* Non-aggregate types can be handled cheaply. */
kono
parents:
diff changeset
1240 if (INTEGRAL_TYPE_P (t1)
kono
parents:
diff changeset
1241 || SCALAR_FLOAT_TYPE_P (t1)
kono
parents:
diff changeset
1242 || FIXED_POINT_TYPE_P (t1)
kono
parents:
diff changeset
1243 || TREE_CODE (t1) == VECTOR_TYPE
kono
parents:
diff changeset
1244 || TREE_CODE (t1) == COMPLEX_TYPE
kono
parents:
diff changeset
1245 || TREE_CODE (t1) == OFFSET_TYPE
kono
parents:
diff changeset
1246 || POINTER_TYPE_P (t1))
kono
parents:
diff changeset
1247 {
kono
parents:
diff changeset
1248 if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2))
kono
parents:
diff changeset
1249 {
kono
parents:
diff changeset
1250 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1251 G_("a type with different precision is defined "
kono
parents:
diff changeset
1252 "in another translation unit"));
kono
parents:
diff changeset
1253 return false;
kono
parents:
diff changeset
1254 }
kono
parents:
diff changeset
1255 if (TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
kono
parents:
diff changeset
1256 {
kono
parents:
diff changeset
1257 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1258 G_("a type with different signedness is defined "
kono
parents:
diff changeset
1259 "in another translation unit"));
kono
parents:
diff changeset
1260 return false;
kono
parents:
diff changeset
1261 }
kono
parents:
diff changeset
1262
kono
parents:
diff changeset
1263 if (TREE_CODE (t1) == INTEGER_TYPE
kono
parents:
diff changeset
1264 && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
kono
parents:
diff changeset
1265 {
kono
parents:
diff changeset
1266 /* char WRT uint_8? */
kono
parents:
diff changeset
1267 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1268 G_("a different type is defined in another "
kono
parents:
diff changeset
1269 "translation unit"));
kono
parents:
diff changeset
1270 return false;
kono
parents:
diff changeset
1271 }
kono
parents:
diff changeset
1272
kono
parents:
diff changeset
1273 /* For canonical type comparisons we do not want to build SCCs
kono
parents:
diff changeset
1274 so we cannot compare pointed-to types. But we can, for now,
kono
parents:
diff changeset
1275 require the same pointed-to type kind and match what
kono
parents:
diff changeset
1276 useless_type_conversion_p would do. */
kono
parents:
diff changeset
1277 if (POINTER_TYPE_P (t1))
kono
parents:
diff changeset
1278 {
kono
parents:
diff changeset
1279 if (TYPE_ADDR_SPACE (TREE_TYPE (t1))
kono
parents:
diff changeset
1280 != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
kono
parents:
diff changeset
1281 {
kono
parents:
diff changeset
1282 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1283 G_("it is defined as a pointer in different address "
kono
parents:
diff changeset
1284 "space in another translation unit"));
kono
parents:
diff changeset
1285 return false;
kono
parents:
diff changeset
1286 }
kono
parents:
diff changeset
1287
kono
parents:
diff changeset
1288 if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2),
kono
parents:
diff changeset
1289 visited, loc1, loc2))
kono
parents:
diff changeset
1290 {
kono
parents:
diff changeset
1291 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1292 G_("it is defined as a pointer to different type "
kono
parents:
diff changeset
1293 "in another translation unit"));
kono
parents:
diff changeset
1294 if (warn && warned)
kono
parents:
diff changeset
1295 warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2),
kono
parents:
diff changeset
1296 loc1, loc2);
kono
parents:
diff changeset
1297 return false;
kono
parents:
diff changeset
1298 }
kono
parents:
diff changeset
1299 }
kono
parents:
diff changeset
1300
kono
parents:
diff changeset
1301 if ((TREE_CODE (t1) == VECTOR_TYPE || TREE_CODE (t1) == COMPLEX_TYPE)
kono
parents:
diff changeset
1302 && !odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2),
kono
parents:
diff changeset
1303 visited, loc1, loc2))
kono
parents:
diff changeset
1304 {
kono
parents:
diff changeset
1305 /* Probably specific enough. */
kono
parents:
diff changeset
1306 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1307 G_("a different type is defined "
kono
parents:
diff changeset
1308 "in another translation unit"));
kono
parents:
diff changeset
1309 if (warn && warned)
kono
parents:
diff changeset
1310 warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), loc1, loc2);
kono
parents:
diff changeset
1311 return false;
kono
parents:
diff changeset
1312 }
kono
parents:
diff changeset
1313 }
kono
parents:
diff changeset
1314 /* Do type-specific comparisons. */
kono
parents:
diff changeset
1315 else switch (TREE_CODE (t1))
kono
parents:
diff changeset
1316 {
kono
parents:
diff changeset
1317 case ARRAY_TYPE:
kono
parents:
diff changeset
1318 {
kono
parents:
diff changeset
1319 /* Array types are the same if the element types are the same and
kono
parents:
diff changeset
1320 the number of elements are the same. */
kono
parents:
diff changeset
1321 if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2),
kono
parents:
diff changeset
1322 visited, loc1, loc2))
kono
parents:
diff changeset
1323 {
kono
parents:
diff changeset
1324 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1325 G_("a different type is defined in another "
kono
parents:
diff changeset
1326 "translation unit"));
kono
parents:
diff changeset
1327 if (warn && warned)
kono
parents:
diff changeset
1328 warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), loc1, loc2);
kono
parents:
diff changeset
1329 }
kono
parents:
diff changeset
1330 gcc_assert (TYPE_STRING_FLAG (t1) == TYPE_STRING_FLAG (t2));
kono
parents:
diff changeset
1331 gcc_assert (TYPE_NONALIASED_COMPONENT (t1)
kono
parents:
diff changeset
1332 == TYPE_NONALIASED_COMPONENT (t2));
kono
parents:
diff changeset
1333
kono
parents:
diff changeset
1334 tree i1 = TYPE_DOMAIN (t1);
kono
parents:
diff changeset
1335 tree i2 = TYPE_DOMAIN (t2);
kono
parents:
diff changeset
1336
kono
parents:
diff changeset
1337 /* For an incomplete external array, the type domain can be
kono
parents:
diff changeset
1338 NULL_TREE. Check this condition also. */
kono
parents:
diff changeset
1339 if (i1 == NULL_TREE || i2 == NULL_TREE)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1340 return type_variants_equivalent_p (t1, t2);
111
kono
parents:
diff changeset
1341
kono
parents:
diff changeset
1342 tree min1 = TYPE_MIN_VALUE (i1);
kono
parents:
diff changeset
1343 tree min2 = TYPE_MIN_VALUE (i2);
kono
parents:
diff changeset
1344 tree max1 = TYPE_MAX_VALUE (i1);
kono
parents:
diff changeset
1345 tree max2 = TYPE_MAX_VALUE (i2);
kono
parents:
diff changeset
1346
kono
parents:
diff changeset
1347 /* In C++, minimums should be always 0. */
kono
parents:
diff changeset
1348 gcc_assert (min1 == min2);
kono
parents:
diff changeset
1349 if (!operand_equal_p (max1, max2, 0))
kono
parents:
diff changeset
1350 {
kono
parents:
diff changeset
1351 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1352 G_("an array of different size is defined "
kono
parents:
diff changeset
1353 "in another translation unit"));
kono
parents:
diff changeset
1354 return false;
kono
parents:
diff changeset
1355 }
kono
parents:
diff changeset
1356 }
kono
parents:
diff changeset
1357 break;
kono
parents:
diff changeset
1358
kono
parents:
diff changeset
1359 case METHOD_TYPE:
kono
parents:
diff changeset
1360 case FUNCTION_TYPE:
kono
parents:
diff changeset
1361 /* Function types are the same if the return type and arguments types
kono
parents:
diff changeset
1362 are the same. */
kono
parents:
diff changeset
1363 if (!odr_subtypes_equivalent_p (TREE_TYPE (t1), TREE_TYPE (t2),
kono
parents:
diff changeset
1364 visited, loc1, loc2))
kono
parents:
diff changeset
1365 {
kono
parents:
diff changeset
1366 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1367 G_("has different return value "
kono
parents:
diff changeset
1368 "in another translation unit"));
kono
parents:
diff changeset
1369 if (warn && warned)
kono
parents:
diff changeset
1370 warn_types_mismatch (TREE_TYPE (t1), TREE_TYPE (t2), loc1, loc2);
kono
parents:
diff changeset
1371 return false;
kono
parents:
diff changeset
1372 }
kono
parents:
diff changeset
1373
kono
parents:
diff changeset
1374 if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2)
kono
parents:
diff changeset
1375 || !prototype_p (t1) || !prototype_p (t2))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1376 return type_variants_equivalent_p (t1, t2);
111
kono
parents:
diff changeset
1377 else
kono
parents:
diff changeset
1378 {
kono
parents:
diff changeset
1379 tree parms1, parms2;
kono
parents:
diff changeset
1380
kono
parents:
diff changeset
1381 for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
kono
parents:
diff changeset
1382 parms1 && parms2;
kono
parents:
diff changeset
1383 parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
kono
parents:
diff changeset
1384 {
kono
parents:
diff changeset
1385 if (!odr_subtypes_equivalent_p
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1386 (TREE_VALUE (parms1), TREE_VALUE (parms2),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1387 visited, loc1, loc2))
111
kono
parents:
diff changeset
1388 {
kono
parents:
diff changeset
1389 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1390 G_("has different parameters in another "
kono
parents:
diff changeset
1391 "translation unit"));
kono
parents:
diff changeset
1392 if (warn && warned)
kono
parents:
diff changeset
1393 warn_types_mismatch (TREE_VALUE (parms1),
kono
parents:
diff changeset
1394 TREE_VALUE (parms2), loc1, loc2);
kono
parents:
diff changeset
1395 return false;
kono
parents:
diff changeset
1396 }
kono
parents:
diff changeset
1397 }
kono
parents:
diff changeset
1398
kono
parents:
diff changeset
1399 if (parms1 || parms2)
kono
parents:
diff changeset
1400 {
kono
parents:
diff changeset
1401 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1402 G_("has different parameters "
kono
parents:
diff changeset
1403 "in another translation unit"));
kono
parents:
diff changeset
1404 return false;
kono
parents:
diff changeset
1405 }
kono
parents:
diff changeset
1406
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1407 return type_variants_equivalent_p (t1, t2);
111
kono
parents:
diff changeset
1408 }
kono
parents:
diff changeset
1409
kono
parents:
diff changeset
1410 case RECORD_TYPE:
kono
parents:
diff changeset
1411 case UNION_TYPE:
kono
parents:
diff changeset
1412 case QUAL_UNION_TYPE:
kono
parents:
diff changeset
1413 {
kono
parents:
diff changeset
1414 tree f1, f2;
kono
parents:
diff changeset
1415
kono
parents:
diff changeset
1416 /* For aggregate types, all the fields must be the same. */
kono
parents:
diff changeset
1417 if (COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2))
kono
parents:
diff changeset
1418 {
kono
parents:
diff changeset
1419 if (TYPE_BINFO (t1) && TYPE_BINFO (t2)
kono
parents:
diff changeset
1420 && polymorphic_type_binfo_p (TYPE_BINFO (t1))
kono
parents:
diff changeset
1421 != polymorphic_type_binfo_p (TYPE_BINFO (t2)))
kono
parents:
diff changeset
1422 {
kono
parents:
diff changeset
1423 if (polymorphic_type_binfo_p (TYPE_BINFO (t1)))
kono
parents:
diff changeset
1424 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1425 G_("a type defined in another translation unit "
kono
parents:
diff changeset
1426 "is not polymorphic"));
kono
parents:
diff changeset
1427 else
kono
parents:
diff changeset
1428 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1429 G_("a type defined in another translation unit "
kono
parents:
diff changeset
1430 "is polymorphic"));
kono
parents:
diff changeset
1431 return false;
kono
parents:
diff changeset
1432 }
kono
parents:
diff changeset
1433 for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
kono
parents:
diff changeset
1434 f1 || f2;
kono
parents:
diff changeset
1435 f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
kono
parents:
diff changeset
1436 {
kono
parents:
diff changeset
1437 /* Skip non-fields. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1438 while (f1 && skip_in_fields_list_p (f1))
111
kono
parents:
diff changeset
1439 f1 = TREE_CHAIN (f1);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1440 while (f2 && skip_in_fields_list_p (f2))
111
kono
parents:
diff changeset
1441 f2 = TREE_CHAIN (f2);
kono
parents:
diff changeset
1442 if (!f1 || !f2)
kono
parents:
diff changeset
1443 break;
kono
parents:
diff changeset
1444 if (DECL_VIRTUAL_P (f1) != DECL_VIRTUAL_P (f2))
kono
parents:
diff changeset
1445 {
kono
parents:
diff changeset
1446 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1447 G_("a type with different virtual table pointers"
kono
parents:
diff changeset
1448 " is defined in another translation unit"));
kono
parents:
diff changeset
1449 return false;
kono
parents:
diff changeset
1450 }
kono
parents:
diff changeset
1451 if (DECL_ARTIFICIAL (f1) != DECL_ARTIFICIAL (f2))
kono
parents:
diff changeset
1452 {
kono
parents:
diff changeset
1453 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1454 G_("a type with different bases is defined "
kono
parents:
diff changeset
1455 "in another translation unit"));
kono
parents:
diff changeset
1456 return false;
kono
parents:
diff changeset
1457 }
kono
parents:
diff changeset
1458 if (DECL_NAME (f1) != DECL_NAME (f2)
kono
parents:
diff changeset
1459 && !DECL_ARTIFICIAL (f1))
kono
parents:
diff changeset
1460 {
kono
parents:
diff changeset
1461 warn_odr (t1, t2, f1, f2, warn, warned,
kono
parents:
diff changeset
1462 G_("a field with different name is defined "
kono
parents:
diff changeset
1463 "in another translation unit"));
kono
parents:
diff changeset
1464 return false;
kono
parents:
diff changeset
1465 }
kono
parents:
diff changeset
1466 if (!odr_subtypes_equivalent_p (TREE_TYPE (f1),
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1467 TREE_TYPE (f2),
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1468 visited, loc1, loc2))
111
kono
parents:
diff changeset
1469 {
kono
parents:
diff changeset
1470 /* Do not warn about artificial fields and just go into
kono
parents:
diff changeset
1471 generic field mismatch warning. */
kono
parents:
diff changeset
1472 if (DECL_ARTIFICIAL (f1))
kono
parents:
diff changeset
1473 break;
kono
parents:
diff changeset
1474
kono
parents:
diff changeset
1475 warn_odr (t1, t2, f1, f2, warn, warned,
kono
parents:
diff changeset
1476 G_("a field of same name but different type "
kono
parents:
diff changeset
1477 "is defined in another translation unit"));
kono
parents:
diff changeset
1478 if (warn && warned)
kono
parents:
diff changeset
1479 warn_types_mismatch (TREE_TYPE (f1), TREE_TYPE (f2), loc1, loc2);
kono
parents:
diff changeset
1480 return false;
kono
parents:
diff changeset
1481 }
kono
parents:
diff changeset
1482 if (!gimple_compare_field_offset (f1, f2))
kono
parents:
diff changeset
1483 {
kono
parents:
diff changeset
1484 /* Do not warn about artificial fields and just go into
kono
parents:
diff changeset
1485 generic field mismatch warning. */
kono
parents:
diff changeset
1486 if (DECL_ARTIFICIAL (f1))
kono
parents:
diff changeset
1487 break;
kono
parents:
diff changeset
1488 warn_odr (t1, t2, f1, f2, warn, warned,
kono
parents:
diff changeset
1489 G_("fields have different layout "
kono
parents:
diff changeset
1490 "in another translation unit"));
kono
parents:
diff changeset
1491 return false;
kono
parents:
diff changeset
1492 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1493 if (DECL_BIT_FIELD (f1) != DECL_BIT_FIELD (f2))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1494 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1495 warn_odr (t1, t2, f1, f2, warn, warned,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1496 G_("one field is a bitfield while the other "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1497 "is not"));
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1498 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1499 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1500 else
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1501 gcc_assert (DECL_NONADDRESSABLE_P (f1)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1502 == DECL_NONADDRESSABLE_P (f2));
111
kono
parents:
diff changeset
1503 }
kono
parents:
diff changeset
1504
kono
parents:
diff changeset
1505 /* If one aggregate has more fields than the other, they
kono
parents:
diff changeset
1506 are not the same. */
kono
parents:
diff changeset
1507 if (f1 || f2)
kono
parents:
diff changeset
1508 {
kono
parents:
diff changeset
1509 if ((f1 && DECL_VIRTUAL_P (f1)) || (f2 && DECL_VIRTUAL_P (f2)))
kono
parents:
diff changeset
1510 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1511 G_("a type with different virtual table pointers"
kono
parents:
diff changeset
1512 " is defined in another translation unit"));
kono
parents:
diff changeset
1513 else if ((f1 && DECL_ARTIFICIAL (f1))
kono
parents:
diff changeset
1514 || (f2 && DECL_ARTIFICIAL (f2)))
kono
parents:
diff changeset
1515 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1516 G_("a type with different bases is defined "
kono
parents:
diff changeset
1517 "in another translation unit"));
kono
parents:
diff changeset
1518 else
kono
parents:
diff changeset
1519 warn_odr (t1, t2, f1, f2, warn, warned,
kono
parents:
diff changeset
1520 G_("a type with different number of fields "
kono
parents:
diff changeset
1521 "is defined in another translation unit"));
kono
parents:
diff changeset
1522
kono
parents:
diff changeset
1523 return false;
kono
parents:
diff changeset
1524 }
kono
parents:
diff changeset
1525 }
kono
parents:
diff changeset
1526 break;
kono
parents:
diff changeset
1527 }
kono
parents:
diff changeset
1528 case VOID_TYPE:
kono
parents:
diff changeset
1529 case NULLPTR_TYPE:
kono
parents:
diff changeset
1530 break;
kono
parents:
diff changeset
1531
kono
parents:
diff changeset
1532 default:
kono
parents:
diff changeset
1533 debug_tree (t1);
kono
parents:
diff changeset
1534 gcc_unreachable ();
kono
parents:
diff changeset
1535 }
kono
parents:
diff changeset
1536
kono
parents:
diff changeset
1537 /* Those are better to come last as they are utterly uninformative. */
kono
parents:
diff changeset
1538 if (TYPE_SIZE (t1) && TYPE_SIZE (t2)
kono
parents:
diff changeset
1539 && !operand_equal_p (TYPE_SIZE (t1), TYPE_SIZE (t2), 0))
kono
parents:
diff changeset
1540 {
kono
parents:
diff changeset
1541 warn_odr (t1, t2, NULL, NULL, warn, warned,
kono
parents:
diff changeset
1542 G_("a type with different size "
kono
parents:
diff changeset
1543 "is defined in another translation unit"));
kono
parents:
diff changeset
1544 return false;
kono
parents:
diff changeset
1545 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1546
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1547 if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1548 && COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2))
111
kono
parents:
diff changeset
1549 {
kono
parents:
diff changeset
1550 warn_odr (t1, t2, NULL, NULL, warn, warned,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1551 G_("one type needs to be constructed while other not"));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1552 gcc_checking_assert (RECORD_OR_UNION_TYPE_P (t1));
111
kono
parents:
diff changeset
1553 return false;
kono
parents:
diff changeset
1554 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1555 /* There is no really good user facing warning for this.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1556 Either the original reason for modes being different is lost during
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1557 streaming or we should catch earlier warnings. We however must detect
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1558 the mismatch to avoid type verifier from cmplaining on mismatched
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1559 types between type and canonical type. See PR91576. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1560 if (TYPE_MODE (t1) != TYPE_MODE (t2)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1561 && COMPLETE_TYPE_P (t1) && COMPLETE_TYPE_P (t2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1562 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1563 warn_odr (t1, t2, NULL, NULL, warn, warned,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1564 G_("memory layout mismatch"));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1565 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1566 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1567
111
kono
parents:
diff changeset
1568 gcc_assert (!TYPE_SIZE_UNIT (t1) || !TYPE_SIZE_UNIT (t2)
kono
parents:
diff changeset
1569 || operand_equal_p (TYPE_SIZE_UNIT (t1),
kono
parents:
diff changeset
1570 TYPE_SIZE_UNIT (t2), 0));
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1571 return type_variants_equivalent_p (t1, t2);
111
kono
parents:
diff changeset
1572 }
kono
parents:
diff changeset
1573
kono
parents:
diff changeset
1574 /* Return true if TYPE1 and TYPE2 are equivalent for One Definition Rule. */
kono
parents:
diff changeset
1575
kono
parents:
diff changeset
1576 bool
kono
parents:
diff changeset
1577 odr_types_equivalent_p (tree type1, tree type2)
kono
parents:
diff changeset
1578 {
kono
parents:
diff changeset
1579 gcc_checking_assert (odr_or_derived_type_p (type1)
kono
parents:
diff changeset
1580 && odr_or_derived_type_p (type2));
kono
parents:
diff changeset
1581
kono
parents:
diff changeset
1582 hash_set<type_pair> visited;
kono
parents:
diff changeset
1583 return odr_types_equivalent_p (type1, type2, false, NULL,
kono
parents:
diff changeset
1584 &visited, UNKNOWN_LOCATION, UNKNOWN_LOCATION);
kono
parents:
diff changeset
1585 }
kono
parents:
diff changeset
1586
kono
parents:
diff changeset
1587 /* TYPE is equivalent to VAL by ODR, but its tree representation differs
kono
parents:
diff changeset
1588 from VAL->type. This may happen in LTO where tree merging did not merge
kono
parents:
diff changeset
1589 all variants of the same type or due to ODR violation.
kono
parents:
diff changeset
1590
kono
parents:
diff changeset
1591 Analyze and report ODR violations and add type to duplicate list.
kono
parents:
diff changeset
1592 If TYPE is more specified than VAL->type, prevail VAL->type. Also if
kono
parents:
diff changeset
1593 this is first time we see definition of a class return true so the
kono
parents:
diff changeset
1594 base types are analyzed. */
kono
parents:
diff changeset
1595
kono
parents:
diff changeset
1596 static bool
kono
parents:
diff changeset
1597 add_type_duplicate (odr_type val, tree type)
kono
parents:
diff changeset
1598 {
kono
parents:
diff changeset
1599 bool build_bases = false;
kono
parents:
diff changeset
1600 bool prevail = false;
kono
parents:
diff changeset
1601 bool odr_must_violate = false;
kono
parents:
diff changeset
1602
kono
parents:
diff changeset
1603 if (!val->types_set)
kono
parents:
diff changeset
1604 val->types_set = new hash_set<tree>;
kono
parents:
diff changeset
1605
kono
parents:
diff changeset
1606 /* Chose polymorphic type as leader (this happens only in case of ODR
kono
parents:
diff changeset
1607 violations. */
kono
parents:
diff changeset
1608 if ((TREE_CODE (type) == RECORD_TYPE && TYPE_BINFO (type)
kono
parents:
diff changeset
1609 && polymorphic_type_binfo_p (TYPE_BINFO (type)))
kono
parents:
diff changeset
1610 && (TREE_CODE (val->type) != RECORD_TYPE || !TYPE_BINFO (val->type)
kono
parents:
diff changeset
1611 || !polymorphic_type_binfo_p (TYPE_BINFO (val->type))))
kono
parents:
diff changeset
1612 {
kono
parents:
diff changeset
1613 prevail = true;
kono
parents:
diff changeset
1614 build_bases = true;
kono
parents:
diff changeset
1615 }
kono
parents:
diff changeset
1616 /* Always prefer complete type to be the leader. */
kono
parents:
diff changeset
1617 else if (!COMPLETE_TYPE_P (val->type) && COMPLETE_TYPE_P (type))
kono
parents:
diff changeset
1618 {
kono
parents:
diff changeset
1619 prevail = true;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1620 if (TREE_CODE (type) == RECORD_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1621 build_bases = TYPE_BINFO (type);
111
kono
parents:
diff changeset
1622 }
kono
parents:
diff changeset
1623 else if (COMPLETE_TYPE_P (val->type) && !COMPLETE_TYPE_P (type))
kono
parents:
diff changeset
1624 ;
kono
parents:
diff changeset
1625 else if (TREE_CODE (val->type) == ENUMERAL_TYPE
kono
parents:
diff changeset
1626 && TREE_CODE (type) == ENUMERAL_TYPE
kono
parents:
diff changeset
1627 && !TYPE_VALUES (val->type) && TYPE_VALUES (type))
kono
parents:
diff changeset
1628 prevail = true;
kono
parents:
diff changeset
1629 else if (TREE_CODE (val->type) == RECORD_TYPE
kono
parents:
diff changeset
1630 && TREE_CODE (type) == RECORD_TYPE
kono
parents:
diff changeset
1631 && TYPE_BINFO (type) && !TYPE_BINFO (val->type))
kono
parents:
diff changeset
1632 {
kono
parents:
diff changeset
1633 gcc_assert (!val->bases.length ());
kono
parents:
diff changeset
1634 build_bases = true;
kono
parents:
diff changeset
1635 prevail = true;
kono
parents:
diff changeset
1636 }
kono
parents:
diff changeset
1637
kono
parents:
diff changeset
1638 if (prevail)
kono
parents:
diff changeset
1639 std::swap (val->type, type);
kono
parents:
diff changeset
1640
kono
parents:
diff changeset
1641 val->types_set->add (type);
kono
parents:
diff changeset
1642
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1643 if (!odr_hash)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1644 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1645
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1646 gcc_checking_assert (can_be_name_hashed_p (type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1647 && can_be_name_hashed_p (val->type));
111
kono
parents:
diff changeset
1648
kono
parents:
diff changeset
1649 bool merge = true;
kono
parents:
diff changeset
1650 bool base_mismatch = false;
kono
parents:
diff changeset
1651 unsigned int i;
kono
parents:
diff changeset
1652 bool warned = false;
kono
parents:
diff changeset
1653 hash_set<type_pair> visited;
kono
parents:
diff changeset
1654
kono
parents:
diff changeset
1655 gcc_assert (in_lto_p);
kono
parents:
diff changeset
1656 vec_safe_push (val->types, type);
kono
parents:
diff changeset
1657
kono
parents:
diff changeset
1658 /* If both are class types, compare the bases. */
kono
parents:
diff changeset
1659 if (COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (val->type)
kono
parents:
diff changeset
1660 && TREE_CODE (val->type) == RECORD_TYPE
kono
parents:
diff changeset
1661 && TREE_CODE (type) == RECORD_TYPE
kono
parents:
diff changeset
1662 && TYPE_BINFO (val->type) && TYPE_BINFO (type))
kono
parents:
diff changeset
1663 {
kono
parents:
diff changeset
1664 if (BINFO_N_BASE_BINFOS (TYPE_BINFO (type))
kono
parents:
diff changeset
1665 != BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type)))
kono
parents:
diff changeset
1666 {
kono
parents:
diff changeset
1667 if (!flag_ltrans && !warned && !val->odr_violated)
kono
parents:
diff changeset
1668 {
kono
parents:
diff changeset
1669 tree extra_base;
kono
parents:
diff changeset
1670 warn_odr (type, val->type, NULL, NULL, !warned, &warned,
kono
parents:
diff changeset
1671 "a type with the same name but different "
kono
parents:
diff changeset
1672 "number of polymorphic bases is "
kono
parents:
diff changeset
1673 "defined in another translation unit");
kono
parents:
diff changeset
1674 if (warned)
kono
parents:
diff changeset
1675 {
kono
parents:
diff changeset
1676 if (BINFO_N_BASE_BINFOS (TYPE_BINFO (type))
kono
parents:
diff changeset
1677 > BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type)))
kono
parents:
diff changeset
1678 extra_base = BINFO_BASE_BINFO
kono
parents:
diff changeset
1679 (TYPE_BINFO (type),
kono
parents:
diff changeset
1680 BINFO_N_BASE_BINFOS (TYPE_BINFO (val->type)));
kono
parents:
diff changeset
1681 else
kono
parents:
diff changeset
1682 extra_base = BINFO_BASE_BINFO
kono
parents:
diff changeset
1683 (TYPE_BINFO (val->type),
kono
parents:
diff changeset
1684 BINFO_N_BASE_BINFOS (TYPE_BINFO (type)));
kono
parents:
diff changeset
1685 tree extra_base_type = BINFO_TYPE (extra_base);
kono
parents:
diff changeset
1686 inform (DECL_SOURCE_LOCATION (TYPE_NAME (extra_base_type)),
kono
parents:
diff changeset
1687 "the extra base is defined here");
kono
parents:
diff changeset
1688 }
kono
parents:
diff changeset
1689 }
kono
parents:
diff changeset
1690 base_mismatch = true;
kono
parents:
diff changeset
1691 }
kono
parents:
diff changeset
1692 else
kono
parents:
diff changeset
1693 for (i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++)
kono
parents:
diff changeset
1694 {
kono
parents:
diff changeset
1695 tree base1 = BINFO_BASE_BINFO (TYPE_BINFO (type), i);
kono
parents:
diff changeset
1696 tree base2 = BINFO_BASE_BINFO (TYPE_BINFO (val->type), i);
kono
parents:
diff changeset
1697 tree type1 = BINFO_TYPE (base1);
kono
parents:
diff changeset
1698 tree type2 = BINFO_TYPE (base2);
kono
parents:
diff changeset
1699
kono
parents:
diff changeset
1700 if (types_odr_comparable (type1, type2))
kono
parents:
diff changeset
1701 {
kono
parents:
diff changeset
1702 if (!types_same_for_odr (type1, type2))
kono
parents:
diff changeset
1703 base_mismatch = true;
kono
parents:
diff changeset
1704 }
kono
parents:
diff changeset
1705 else
kono
parents:
diff changeset
1706 if (!odr_types_equivalent_p (type1, type2))
kono
parents:
diff changeset
1707 base_mismatch = true;
kono
parents:
diff changeset
1708 if (base_mismatch)
kono
parents:
diff changeset
1709 {
kono
parents:
diff changeset
1710 if (!warned && !val->odr_violated)
kono
parents:
diff changeset
1711 {
kono
parents:
diff changeset
1712 warn_odr (type, val->type, NULL, NULL,
kono
parents:
diff changeset
1713 !warned, &warned,
kono
parents:
diff changeset
1714 "a type with the same name but different base "
kono
parents:
diff changeset
1715 "type is defined in another translation unit");
kono
parents:
diff changeset
1716 if (warned)
kono
parents:
diff changeset
1717 warn_types_mismatch (type1, type2,
kono
parents:
diff changeset
1718 UNKNOWN_LOCATION, UNKNOWN_LOCATION);
kono
parents:
diff changeset
1719 }
kono
parents:
diff changeset
1720 break;
kono
parents:
diff changeset
1721 }
kono
parents:
diff changeset
1722 if (BINFO_OFFSET (base1) != BINFO_OFFSET (base2))
kono
parents:
diff changeset
1723 {
kono
parents:
diff changeset
1724 base_mismatch = true;
kono
parents:
diff changeset
1725 if (!warned && !val->odr_violated)
kono
parents:
diff changeset
1726 warn_odr (type, val->type, NULL, NULL,
kono
parents:
diff changeset
1727 !warned, &warned,
kono
parents:
diff changeset
1728 "a type with the same name but different base "
kono
parents:
diff changeset
1729 "layout is defined in another translation unit");
kono
parents:
diff changeset
1730 break;
kono
parents:
diff changeset
1731 }
kono
parents:
diff changeset
1732 /* One of bases is not of complete type. */
kono
parents:
diff changeset
1733 if (!TYPE_BINFO (type1) != !TYPE_BINFO (type2))
kono
parents:
diff changeset
1734 {
kono
parents:
diff changeset
1735 /* If we have a polymorphic type info specified for TYPE1
kono
parents:
diff changeset
1736 but not for TYPE2 we possibly missed a base when recording
kono
parents:
diff changeset
1737 VAL->type earlier.
kono
parents:
diff changeset
1738 Be sure this does not happen. */
kono
parents:
diff changeset
1739 if (TYPE_BINFO (type1)
kono
parents:
diff changeset
1740 && polymorphic_type_binfo_p (TYPE_BINFO (type1))
kono
parents:
diff changeset
1741 && !build_bases)
kono
parents:
diff changeset
1742 odr_must_violate = true;
kono
parents:
diff changeset
1743 break;
kono
parents:
diff changeset
1744 }
kono
parents:
diff changeset
1745 /* One base is polymorphic and the other not.
kono
parents:
diff changeset
1746 This ought to be diagnosed earlier, but do not ICE in the
kono
parents:
diff changeset
1747 checking bellow. */
kono
parents:
diff changeset
1748 else if (TYPE_BINFO (type1)
kono
parents:
diff changeset
1749 && polymorphic_type_binfo_p (TYPE_BINFO (type1))
kono
parents:
diff changeset
1750 != polymorphic_type_binfo_p (TYPE_BINFO (type2)))
kono
parents:
diff changeset
1751 {
kono
parents:
diff changeset
1752 if (!warned && !val->odr_violated)
kono
parents:
diff changeset
1753 warn_odr (type, val->type, NULL, NULL,
kono
parents:
diff changeset
1754 !warned, &warned,
kono
parents:
diff changeset
1755 "a base of the type is polymorphic only in one "
kono
parents:
diff changeset
1756 "translation unit");
kono
parents:
diff changeset
1757 base_mismatch = true;
kono
parents:
diff changeset
1758 break;
kono
parents:
diff changeset
1759 }
kono
parents:
diff changeset
1760 }
kono
parents:
diff changeset
1761 if (base_mismatch)
kono
parents:
diff changeset
1762 {
kono
parents:
diff changeset
1763 merge = false;
kono
parents:
diff changeset
1764 odr_violation_reported = true;
kono
parents:
diff changeset
1765 val->odr_violated = true;
kono
parents:
diff changeset
1766
kono
parents:
diff changeset
1767 if (symtab->dump_file)
kono
parents:
diff changeset
1768 {
kono
parents:
diff changeset
1769 fprintf (symtab->dump_file, "ODR base violation\n");
kono
parents:
diff changeset
1770
kono
parents:
diff changeset
1771 print_node (symtab->dump_file, "", val->type, 0);
kono
parents:
diff changeset
1772 putc ('\n',symtab->dump_file);
kono
parents:
diff changeset
1773 print_node (symtab->dump_file, "", type, 0);
kono
parents:
diff changeset
1774 putc ('\n',symtab->dump_file);
kono
parents:
diff changeset
1775 }
kono
parents:
diff changeset
1776 }
kono
parents:
diff changeset
1777 }
kono
parents:
diff changeset
1778
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1779 /* Next compare memory layout.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1780 The DECL_SOURCE_LOCATIONs in this invocation came from LTO streaming.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1781 We must apply the location cache to ensure that they are valid
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1782 before we can pass them to odr_types_equivalent_p (PR lto/83121). */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1783 if (lto_location_cache::current_cache)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1784 lto_location_cache::current_cache->apply_location_cache ();
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1785 /* As a special case we stream mangles names of integer types so we can see
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1786 if they are believed to be same even though they have different
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1787 representation. Avoid bogus warning on mismatches in these. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1788 if (TREE_CODE (type) != INTEGER_TYPE
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1789 && TREE_CODE (val->type) != INTEGER_TYPE
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1790 && !odr_types_equivalent_p (val->type, type,
111
kono
parents:
diff changeset
1791 !flag_ltrans && !val->odr_violated && !warned,
kono
parents:
diff changeset
1792 &warned, &visited,
kono
parents:
diff changeset
1793 DECL_SOURCE_LOCATION (TYPE_NAME (val->type)),
kono
parents:
diff changeset
1794 DECL_SOURCE_LOCATION (TYPE_NAME (type))))
kono
parents:
diff changeset
1795 {
kono
parents:
diff changeset
1796 merge = false;
kono
parents:
diff changeset
1797 odr_violation_reported = true;
kono
parents:
diff changeset
1798 val->odr_violated = true;
kono
parents:
diff changeset
1799 }
kono
parents:
diff changeset
1800 gcc_assert (val->odr_violated || !odr_must_violate);
kono
parents:
diff changeset
1801 /* Sanity check that all bases will be build same way again. */
kono
parents:
diff changeset
1802 if (flag_checking
kono
parents:
diff changeset
1803 && COMPLETE_TYPE_P (type) && COMPLETE_TYPE_P (val->type)
kono
parents:
diff changeset
1804 && TREE_CODE (val->type) == RECORD_TYPE
kono
parents:
diff changeset
1805 && TREE_CODE (type) == RECORD_TYPE
kono
parents:
diff changeset
1806 && TYPE_BINFO (val->type) && TYPE_BINFO (type)
kono
parents:
diff changeset
1807 && !val->odr_violated
kono
parents:
diff changeset
1808 && !base_mismatch && val->bases.length ())
kono
parents:
diff changeset
1809 {
kono
parents:
diff changeset
1810 unsigned int num_poly_bases = 0;
kono
parents:
diff changeset
1811 unsigned int j;
kono
parents:
diff changeset
1812
kono
parents:
diff changeset
1813 for (i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++)
kono
parents:
diff changeset
1814 if (polymorphic_type_binfo_p (BINFO_BASE_BINFO
kono
parents:
diff changeset
1815 (TYPE_BINFO (type), i)))
kono
parents:
diff changeset
1816 num_poly_bases++;
kono
parents:
diff changeset
1817 gcc_assert (num_poly_bases == val->bases.length ());
kono
parents:
diff changeset
1818 for (j = 0, i = 0; i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type));
kono
parents:
diff changeset
1819 i++)
kono
parents:
diff changeset
1820 if (polymorphic_type_binfo_p (BINFO_BASE_BINFO
kono
parents:
diff changeset
1821 (TYPE_BINFO (type), i)))
kono
parents:
diff changeset
1822 {
kono
parents:
diff changeset
1823 odr_type base = get_odr_type
kono
parents:
diff changeset
1824 (BINFO_TYPE
kono
parents:
diff changeset
1825 (BINFO_BASE_BINFO (TYPE_BINFO (type),
kono
parents:
diff changeset
1826 i)),
kono
parents:
diff changeset
1827 true);
kono
parents:
diff changeset
1828 gcc_assert (val->bases[j] == base);
kono
parents:
diff changeset
1829 j++;
kono
parents:
diff changeset
1830 }
kono
parents:
diff changeset
1831 }
kono
parents:
diff changeset
1832
kono
parents:
diff changeset
1833
kono
parents:
diff changeset
1834 /* Regularize things a little. During LTO same types may come with
kono
parents:
diff changeset
1835 different BINFOs. Either because their virtual table was
kono
parents:
diff changeset
1836 not merged by tree merging and only later at decl merging or
kono
parents:
diff changeset
1837 because one type comes with external vtable, while other
kono
parents:
diff changeset
1838 with internal. We want to merge equivalent binfos to conserve
kono
parents:
diff changeset
1839 memory and streaming overhead.
kono
parents:
diff changeset
1840
kono
parents:
diff changeset
1841 The external vtables are more harmful: they contain references
kono
parents:
diff changeset
1842 to external declarations of methods that may be defined in the
kono
parents:
diff changeset
1843 merged LTO unit. For this reason we absolutely need to remove
kono
parents:
diff changeset
1844 them and replace by internal variants. Not doing so will lead
kono
parents:
diff changeset
1845 to incomplete answers from possible_polymorphic_call_targets.
kono
parents:
diff changeset
1846
kono
parents:
diff changeset
1847 FIXME: disable for now; because ODR types are now build during
kono
parents:
diff changeset
1848 streaming in, the variants do not need to be linked to the type,
kono
parents:
diff changeset
1849 yet. We need to do the merging in cleanup pass to be implemented
kono
parents:
diff changeset
1850 soon. */
kono
parents:
diff changeset
1851 if (!flag_ltrans && merge
kono
parents:
diff changeset
1852 && 0
kono
parents:
diff changeset
1853 && TREE_CODE (val->type) == RECORD_TYPE
kono
parents:
diff changeset
1854 && TREE_CODE (type) == RECORD_TYPE
kono
parents:
diff changeset
1855 && TYPE_BINFO (val->type) && TYPE_BINFO (type)
kono
parents:
diff changeset
1856 && TYPE_MAIN_VARIANT (type) == type
kono
parents:
diff changeset
1857 && TYPE_MAIN_VARIANT (val->type) == val->type
kono
parents:
diff changeset
1858 && BINFO_VTABLE (TYPE_BINFO (val->type))
kono
parents:
diff changeset
1859 && BINFO_VTABLE (TYPE_BINFO (type)))
kono
parents:
diff changeset
1860 {
kono
parents:
diff changeset
1861 tree master_binfo = TYPE_BINFO (val->type);
kono
parents:
diff changeset
1862 tree v1 = BINFO_VTABLE (master_binfo);
kono
parents:
diff changeset
1863 tree v2 = BINFO_VTABLE (TYPE_BINFO (type));
kono
parents:
diff changeset
1864
kono
parents:
diff changeset
1865 if (TREE_CODE (v1) == POINTER_PLUS_EXPR)
kono
parents:
diff changeset
1866 {
kono
parents:
diff changeset
1867 gcc_assert (TREE_CODE (v2) == POINTER_PLUS_EXPR
kono
parents:
diff changeset
1868 && operand_equal_p (TREE_OPERAND (v1, 1),
kono
parents:
diff changeset
1869 TREE_OPERAND (v2, 1), 0));
kono
parents:
diff changeset
1870 v1 = TREE_OPERAND (TREE_OPERAND (v1, 0), 0);
kono
parents:
diff changeset
1871 v2 = TREE_OPERAND (TREE_OPERAND (v2, 0), 0);
kono
parents:
diff changeset
1872 }
kono
parents:
diff changeset
1873 gcc_assert (DECL_ASSEMBLER_NAME (v1)
kono
parents:
diff changeset
1874 == DECL_ASSEMBLER_NAME (v2));
kono
parents:
diff changeset
1875
kono
parents:
diff changeset
1876 if (DECL_EXTERNAL (v1) && !DECL_EXTERNAL (v2))
kono
parents:
diff changeset
1877 {
kono
parents:
diff changeset
1878 unsigned int i;
kono
parents:
diff changeset
1879
kono
parents:
diff changeset
1880 set_type_binfo (val->type, TYPE_BINFO (type));
kono
parents:
diff changeset
1881 for (i = 0; i < val->types->length (); i++)
kono
parents:
diff changeset
1882 {
kono
parents:
diff changeset
1883 if (TYPE_BINFO ((*val->types)[i])
kono
parents:
diff changeset
1884 == master_binfo)
kono
parents:
diff changeset
1885 set_type_binfo ((*val->types)[i], TYPE_BINFO (type));
kono
parents:
diff changeset
1886 }
kono
parents:
diff changeset
1887 BINFO_TYPE (TYPE_BINFO (type)) = val->type;
kono
parents:
diff changeset
1888 }
kono
parents:
diff changeset
1889 else
kono
parents:
diff changeset
1890 set_type_binfo (type, master_binfo);
kono
parents:
diff changeset
1891 }
kono
parents:
diff changeset
1892 return build_bases;
kono
parents:
diff changeset
1893 }
kono
parents:
diff changeset
1894
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1895 /* REF is OBJ_TYPE_REF, return the class the ref corresponds to. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1896
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1897 tree
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1898 obj_type_ref_class (const_tree ref)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1899 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1900 gcc_checking_assert (TREE_CODE (ref) == OBJ_TYPE_REF);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1901 ref = TREE_TYPE (ref);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1902 gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1903 ref = TREE_TYPE (ref);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1904 /* We look for type THIS points to. ObjC also builds
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1905 OBJ_TYPE_REF with non-method calls, Their first parameter
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1906 ID however also corresponds to class type. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1907 gcc_checking_assert (TREE_CODE (ref) == METHOD_TYPE
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1908 || TREE_CODE (ref) == FUNCTION_TYPE);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1909 ref = TREE_VALUE (TYPE_ARG_TYPES (ref));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1910 gcc_checking_assert (TREE_CODE (ref) == POINTER_TYPE);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1911 tree ret = TREE_TYPE (ref);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1912 if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (ret))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1913 ret = TYPE_CANONICAL (ret);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1914 else
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1915 ret = get_odr_type (ret)->type;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1916 return ret;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1917 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1918
111
kono
parents:
diff changeset
1919 /* Get ODR type hash entry for TYPE. If INSERT is true, create
kono
parents:
diff changeset
1920 possibly new entry. */
kono
parents:
diff changeset
1921
kono
parents:
diff changeset
1922 odr_type
kono
parents:
diff changeset
1923 get_odr_type (tree type, bool insert)
kono
parents:
diff changeset
1924 {
kono
parents:
diff changeset
1925 odr_type_d **slot = NULL;
kono
parents:
diff changeset
1926 odr_type val = NULL;
kono
parents:
diff changeset
1927 hashval_t hash;
kono
parents:
diff changeset
1928 bool build_bases = false;
kono
parents:
diff changeset
1929 bool insert_to_odr_array = false;
kono
parents:
diff changeset
1930 int base_id = -1;
kono
parents:
diff changeset
1931
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1932 type = TYPE_MAIN_VARIANT (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1933 if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1934 type = TYPE_CANONICAL (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1935
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1936 gcc_checking_assert (can_be_name_hashed_p (type));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1937
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1938 hash = hash_odr_name (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1939 slot = odr_hash->find_slot_with_hash (type, hash,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1940 insert ? INSERT : NO_INSERT);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1941
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1942 if (!slot)
111
kono
parents:
diff changeset
1943 return NULL;
kono
parents:
diff changeset
1944
kono
parents:
diff changeset
1945 /* See if we already have entry for type. */
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1946 if (*slot)
111
kono
parents:
diff changeset
1947 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1948 val = *slot;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1949
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1950 if (val->type != type && insert
111
kono
parents:
diff changeset
1951 && (!val->types_set || !val->types_set->add (type)))
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1952 build_bases = add_type_duplicate (val, type);
111
kono
parents:
diff changeset
1953 }
kono
parents:
diff changeset
1954 else
kono
parents:
diff changeset
1955 {
kono
parents:
diff changeset
1956 val = ggc_cleared_alloc<odr_type_d> ();
kono
parents:
diff changeset
1957 val->type = type;
kono
parents:
diff changeset
1958 val->bases = vNULL;
kono
parents:
diff changeset
1959 val->derived_types = vNULL;
kono
parents:
diff changeset
1960 if (type_with_linkage_p (type))
kono
parents:
diff changeset
1961 val->anonymous_namespace = type_in_anonymous_namespace_p (type);
kono
parents:
diff changeset
1962 else
kono
parents:
diff changeset
1963 val->anonymous_namespace = 0;
kono
parents:
diff changeset
1964 build_bases = COMPLETE_TYPE_P (val->type);
kono
parents:
diff changeset
1965 insert_to_odr_array = true;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1966 *slot = val;
111
kono
parents:
diff changeset
1967 }
kono
parents:
diff changeset
1968
kono
parents:
diff changeset
1969 if (build_bases && TREE_CODE (type) == RECORD_TYPE && TYPE_BINFO (type)
kono
parents:
diff changeset
1970 && type_with_linkage_p (type)
kono
parents:
diff changeset
1971 && type == TYPE_MAIN_VARIANT (type))
kono
parents:
diff changeset
1972 {
kono
parents:
diff changeset
1973 tree binfo = TYPE_BINFO (type);
kono
parents:
diff changeset
1974 unsigned int i;
kono
parents:
diff changeset
1975
kono
parents:
diff changeset
1976 gcc_assert (BINFO_TYPE (TYPE_BINFO (val->type)) == type);
kono
parents:
diff changeset
1977
kono
parents:
diff changeset
1978 val->all_derivations_known = type_all_derivations_known_p (type);
kono
parents:
diff changeset
1979 for (i = 0; i < BINFO_N_BASE_BINFOS (binfo); i++)
kono
parents:
diff changeset
1980 /* For now record only polymorphic types. other are
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
1981 pointless for devirtualization and we cannot precisely
111
kono
parents:
diff changeset
1982 determine ODR equivalency of these during LTO. */
kono
parents:
diff changeset
1983 if (polymorphic_type_binfo_p (BINFO_BASE_BINFO (binfo, i)))
kono
parents:
diff changeset
1984 {
kono
parents:
diff changeset
1985 tree base_type= BINFO_TYPE (BINFO_BASE_BINFO (binfo, i));
kono
parents:
diff changeset
1986 odr_type base = get_odr_type (base_type, true);
kono
parents:
diff changeset
1987 gcc_assert (TYPE_MAIN_VARIANT (base_type) == base_type);
kono
parents:
diff changeset
1988 base->derived_types.safe_push (val);
kono
parents:
diff changeset
1989 val->bases.safe_push (base);
kono
parents:
diff changeset
1990 if (base->id > base_id)
kono
parents:
diff changeset
1991 base_id = base->id;
kono
parents:
diff changeset
1992 }
kono
parents:
diff changeset
1993 }
kono
parents:
diff changeset
1994 /* Ensure that type always appears after bases. */
kono
parents:
diff changeset
1995 if (insert_to_odr_array)
kono
parents:
diff changeset
1996 {
kono
parents:
diff changeset
1997 if (odr_types_ptr)
kono
parents:
diff changeset
1998 val->id = odr_types.length ();
kono
parents:
diff changeset
1999 vec_safe_push (odr_types_ptr, val);
kono
parents:
diff changeset
2000 }
kono
parents:
diff changeset
2001 else if (base_id > val->id)
kono
parents:
diff changeset
2002 {
kono
parents:
diff changeset
2003 odr_types[val->id] = 0;
kono
parents:
diff changeset
2004 /* Be sure we did not recorded any derived types; these may need
kono
parents:
diff changeset
2005 renumbering too. */
kono
parents:
diff changeset
2006 gcc_assert (val->derived_types.length() == 0);
kono
parents:
diff changeset
2007 val->id = odr_types.length ();
kono
parents:
diff changeset
2008 vec_safe_push (odr_types_ptr, val);
kono
parents:
diff changeset
2009 }
kono
parents:
diff changeset
2010 return val;
kono
parents:
diff changeset
2011 }
kono
parents:
diff changeset
2012
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2013 /* Return type that in ODR type hash prevailed TYPE. Be careful and punt
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2014 on ODR violations. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2015
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2016 tree
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2017 prevailing_odr_type (tree type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2018 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2019 odr_type t = get_odr_type (type, false);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2020 if (!t || t->odr_violated)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2021 return type;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2022 return t->type;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2023 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2024
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2025 /* Set tbaa_enabled flag for TYPE. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2026
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2027 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2028 enable_odr_based_tbaa (tree type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2029 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2030 odr_type t = get_odr_type (type, true);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2031 t->tbaa_enabled = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2032 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2033
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2034 /* True if canonical type of TYPE is determined using ODR name. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2035
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2036 bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2037 odr_based_tbaa_p (const_tree type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2038 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2039 if (!RECORD_OR_UNION_TYPE_P (type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2040 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2041 odr_type t = get_odr_type (const_cast <tree> (type), false);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2042 if (!t || !t->tbaa_enabled)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2043 return false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2044 return true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2045 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2046
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2047 /* Set TYPE_CANONICAL of type and all its variants and duplicates
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2048 to CANONICAL. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2049
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2050 void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2051 set_type_canonical_for_odr_type (tree type, tree canonical)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2052 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2053 odr_type t = get_odr_type (type, false);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2054 unsigned int i;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2055 tree tt;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2056
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2057 for (tree t2 = t->type; t2; t2 = TYPE_NEXT_VARIANT (t2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2058 TYPE_CANONICAL (t2) = canonical;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2059 if (t->types)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2060 FOR_EACH_VEC_ELT (*t->types, i, tt)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2061 for (tree t2 = tt; t2; t2 = TYPE_NEXT_VARIANT (t2))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2062 TYPE_CANONICAL (t2) = canonical;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2063 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2064
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2065 /* Return true if we reported some ODR violation on TYPE. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2066
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2067 bool
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2068 odr_type_violation_reported_p (tree type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2069 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2070 return get_odr_type (type, false)->odr_violated;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2071 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2072
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2073 /* Add TYPE of ODR type hash. */
111
kono
parents:
diff changeset
2074
kono
parents:
diff changeset
2075 void
kono
parents:
diff changeset
2076 register_odr_type (tree type)
kono
parents:
diff changeset
2077 {
kono
parents:
diff changeset
2078 if (!odr_hash)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2079 odr_hash = new odr_hash_type (23);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2080 if (type == TYPE_MAIN_VARIANT (type))
111
kono
parents:
diff changeset
2081 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2082 /* To get ODR warnings right, first register all sub-types. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2083 if (RECORD_OR_UNION_TYPE_P (type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2084 && COMPLETE_TYPE_P (type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2085 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2086 /* Limit recursion on types which are already registered. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2087 odr_type ot = get_odr_type (type, false);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2088 if (ot
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2089 && (ot->type == type
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2090 || (ot->types_set
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2091 && ot->types_set->contains (type))))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2092 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2093 for (tree f = TYPE_FIELDS (type); f; f = TREE_CHAIN (f))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2094 if (TREE_CODE (f) == FIELD_DECL)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2095 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2096 tree subtype = TREE_TYPE (f);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2097
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2098 while (TREE_CODE (subtype) == ARRAY_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2099 subtype = TREE_TYPE (subtype);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2100 if (type_with_linkage_p (TYPE_MAIN_VARIANT (subtype)))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2101 register_odr_type (TYPE_MAIN_VARIANT (subtype));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2102 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2103 if (TYPE_BINFO (type))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2104 for (unsigned int i = 0;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2105 i < BINFO_N_BASE_BINFOS (TYPE_BINFO (type)); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2106 register_odr_type (BINFO_TYPE (BINFO_BASE_BINFO
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2107 (TYPE_BINFO (type), i)));
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2108 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2109 get_odr_type (type, true);
111
kono
parents:
diff changeset
2110 }
kono
parents:
diff changeset
2111 }
kono
parents:
diff changeset
2112
kono
parents:
diff changeset
2113 /* Return true if type is known to have no derivations. */
kono
parents:
diff changeset
2114
kono
parents:
diff changeset
2115 bool
kono
parents:
diff changeset
2116 type_known_to_have_no_derivations_p (tree t)
kono
parents:
diff changeset
2117 {
kono
parents:
diff changeset
2118 return (type_all_derivations_known_p (t)
kono
parents:
diff changeset
2119 && (TYPE_FINAL_P (t)
kono
parents:
diff changeset
2120 || (odr_hash
kono
parents:
diff changeset
2121 && !get_odr_type (t, true)->derived_types.length())));
kono
parents:
diff changeset
2122 }
kono
parents:
diff changeset
2123
kono
parents:
diff changeset
2124 /* Dump ODR type T and all its derived types. INDENT specifies indentation for
kono
parents:
diff changeset
2125 recursive printing. */
kono
parents:
diff changeset
2126
kono
parents:
diff changeset
2127 static void
kono
parents:
diff changeset
2128 dump_odr_type (FILE *f, odr_type t, int indent=0)
kono
parents:
diff changeset
2129 {
kono
parents:
diff changeset
2130 unsigned int i;
kono
parents:
diff changeset
2131 fprintf (f, "%*s type %i: ", indent * 2, "", t->id);
kono
parents:
diff changeset
2132 print_generic_expr (f, t->type, TDF_SLIM);
kono
parents:
diff changeset
2133 fprintf (f, "%s", t->anonymous_namespace ? " (anonymous namespace)":"");
kono
parents:
diff changeset
2134 fprintf (f, "%s\n", t->all_derivations_known ? " (derivations known)":"");
kono
parents:
diff changeset
2135 if (TYPE_NAME (t->type))
kono
parents:
diff changeset
2136 {
kono
parents:
diff changeset
2137 if (DECL_ASSEMBLER_NAME_SET_P (TYPE_NAME (t->type)))
kono
parents:
diff changeset
2138 fprintf (f, "%*s mangled name: %s\n", indent * 2, "",
kono
parents:
diff changeset
2139 IDENTIFIER_POINTER
kono
parents:
diff changeset
2140 (DECL_ASSEMBLER_NAME (TYPE_NAME (t->type))));
kono
parents:
diff changeset
2141 }
kono
parents:
diff changeset
2142 if (t->bases.length ())
kono
parents:
diff changeset
2143 {
kono
parents:
diff changeset
2144 fprintf (f, "%*s base odr type ids: ", indent * 2, "");
kono
parents:
diff changeset
2145 for (i = 0; i < t->bases.length (); i++)
kono
parents:
diff changeset
2146 fprintf (f, " %i", t->bases[i]->id);
kono
parents:
diff changeset
2147 fprintf (f, "\n");
kono
parents:
diff changeset
2148 }
kono
parents:
diff changeset
2149 if (t->derived_types.length ())
kono
parents:
diff changeset
2150 {
kono
parents:
diff changeset
2151 fprintf (f, "%*s derived types:\n", indent * 2, "");
kono
parents:
diff changeset
2152 for (i = 0; i < t->derived_types.length (); i++)
kono
parents:
diff changeset
2153 dump_odr_type (f, t->derived_types[i], indent + 1);
kono
parents:
diff changeset
2154 }
kono
parents:
diff changeset
2155 fprintf (f, "\n");
kono
parents:
diff changeset
2156 }
kono
parents:
diff changeset
2157
kono
parents:
diff changeset
2158 /* Dump the type inheritance graph. */
kono
parents:
diff changeset
2159
kono
parents:
diff changeset
2160 static void
kono
parents:
diff changeset
2161 dump_type_inheritance_graph (FILE *f)
kono
parents:
diff changeset
2162 {
kono
parents:
diff changeset
2163 unsigned int i;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2164 unsigned int num_all_types = 0, num_types = 0, num_duplicates = 0;
111
kono
parents:
diff changeset
2165 if (!odr_types_ptr)
kono
parents:
diff changeset
2166 return;
kono
parents:
diff changeset
2167 fprintf (f, "\n\nType inheritance graph:\n");
kono
parents:
diff changeset
2168 for (i = 0; i < odr_types.length (); i++)
kono
parents:
diff changeset
2169 {
kono
parents:
diff changeset
2170 if (odr_types[i] && odr_types[i]->bases.length () == 0)
kono
parents:
diff changeset
2171 dump_odr_type (f, odr_types[i]);
kono
parents:
diff changeset
2172 }
kono
parents:
diff changeset
2173 for (i = 0; i < odr_types.length (); i++)
kono
parents:
diff changeset
2174 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2175 if (!odr_types[i])
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2176 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2177
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2178 num_all_types++;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2179 if (!odr_types[i]->types || !odr_types[i]->types->length ())
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2180 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2181
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2182 /* To aid ODR warnings we also mangle integer constants but do
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2183 not consider duplicates there. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2184 if (TREE_CODE (odr_types[i]->type) == INTEGER_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2185 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2186
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2187 /* It is normal to have one duplicate and one normal variant. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2188 if (odr_types[i]->types->length () == 1
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2189 && COMPLETE_TYPE_P (odr_types[i]->type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2190 && !COMPLETE_TYPE_P ((*odr_types[i]->types)[0]))
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2191 continue;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2192
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2193 num_types ++;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2194
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2195 unsigned int j;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2196 fprintf (f, "Duplicate tree types for odr type %i\n", i);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2197 print_node (f, "", odr_types[i]->type, 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2198 print_node (f, "", TYPE_NAME (odr_types[i]->type), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2199 putc ('\n',f);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2200 for (j = 0; j < odr_types[i]->types->length (); j++)
111
kono
parents:
diff changeset
2201 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2202 tree t;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2203 num_duplicates ++;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2204 fprintf (f, "duplicate #%i\n", j);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2205 print_node (f, "", (*odr_types[i]->types)[j], 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2206 t = (*odr_types[i]->types)[j];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2207 while (TYPE_P (t) && TYPE_CONTEXT (t))
111
kono
parents:
diff changeset
2208 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2209 t = TYPE_CONTEXT (t);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2210 print_node (f, "", t, 0);
111
kono
parents:
diff changeset
2211 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2212 print_node (f, "", TYPE_NAME ((*odr_types[i]->types)[j]), 0);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2213 putc ('\n',f);
111
kono
parents:
diff changeset
2214 }
kono
parents:
diff changeset
2215 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2216 fprintf (f, "Out of %i types there are %i types with duplicates; "
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2217 "%i duplicates overall\n", num_all_types, num_types, num_duplicates);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2218 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2219
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2220 /* Save some WPA->ltrans streaming by freeing stuff needed only for good
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2221 ODR warnings.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2222 We free TYPE_VALUES of enums and also make TYPE_DECLs to not point back
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2223 to the type (which is needed to keep them in the same SCC and preserve
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2224 location information to output warnings) and subsequently we make all
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2225 TYPE_DECLS of same assembler name equivalent. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2226
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2227 static void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2228 free_odr_warning_data ()
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2229 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2230 static bool odr_data_freed = false;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2231
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2232 if (odr_data_freed || !flag_wpa || !odr_types_ptr)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2233 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2234
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2235 odr_data_freed = true;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2236
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2237 for (unsigned int i = 0; i < odr_types.length (); i++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2238 if (odr_types[i])
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2239 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2240 tree t = odr_types[i]->type;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2241
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2242 if (TREE_CODE (t) == ENUMERAL_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2243 TYPE_VALUES (t) = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2244 TREE_TYPE (TYPE_NAME (t)) = void_type_node;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2245
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2246 if (odr_types[i]->types)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2247 for (unsigned int j = 0; j < odr_types[i]->types->length (); j++)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2248 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2249 tree td = (*odr_types[i]->types)[j];
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2250
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2251 if (TREE_CODE (td) == ENUMERAL_TYPE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2252 TYPE_VALUES (td) = NULL;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2253 TYPE_NAME (td) = TYPE_NAME (t);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2254 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2255 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2256 odr_data_freed = true;
111
kono
parents:
diff changeset
2257 }
kono
parents:
diff changeset
2258
kono
parents:
diff changeset
2259 /* Initialize IPA devirt and build inheritance tree graph. */
kono
parents:
diff changeset
2260
kono
parents:
diff changeset
2261 void
kono
parents:
diff changeset
2262 build_type_inheritance_graph (void)
kono
parents:
diff changeset
2263 {
kono
parents:
diff changeset
2264 struct symtab_node *n;
kono
parents:
diff changeset
2265 FILE *inheritance_dump_file;
kono
parents:
diff changeset
2266 dump_flags_t flags;
kono
parents:
diff changeset
2267
kono
parents:
diff changeset
2268 if (odr_hash)
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2269 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2270 free_odr_warning_data ();
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2271 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2272 }
111
kono
parents:
diff changeset
2273 timevar_push (TV_IPA_INHERITANCE);
kono
parents:
diff changeset
2274 inheritance_dump_file = dump_begin (TDI_inheritance, &flags);
kono
parents:
diff changeset
2275 odr_hash = new odr_hash_type (23);
kono
parents:
diff changeset
2276
kono
parents:
diff changeset
2277 /* We reconstruct the graph starting of types of all methods seen in the
kono
parents:
diff changeset
2278 unit. */
kono
parents:
diff changeset
2279 FOR_EACH_SYMBOL (n)
kono
parents:
diff changeset
2280 if (is_a <cgraph_node *> (n)
kono
parents:
diff changeset
2281 && DECL_VIRTUAL_P (n->decl)
kono
parents:
diff changeset
2282 && n->real_symbol_p ())
kono
parents:
diff changeset
2283 get_odr_type (TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl)), true);
kono
parents:
diff changeset
2284
kono
parents:
diff changeset
2285 /* Look also for virtual tables of types that do not define any methods.
kono
parents:
diff changeset
2286
kono
parents:
diff changeset
2287 We need it in a case where class B has virtual base of class A
kono
parents:
diff changeset
2288 re-defining its virtual method and there is class C with no virtual
kono
parents:
diff changeset
2289 methods with B as virtual base.
kono
parents:
diff changeset
2290
kono
parents:
diff changeset
2291 Here we output B's virtual method in two variant - for non-virtual
kono
parents:
diff changeset
2292 and virtual inheritance. B's virtual table has non-virtual version,
kono
parents:
diff changeset
2293 while C's has virtual.
kono
parents:
diff changeset
2294
kono
parents:
diff changeset
2295 For this reason we need to know about C in order to include both
kono
parents:
diff changeset
2296 variants of B. More correctly, record_target_from_binfo should
kono
parents:
diff changeset
2297 add both variants of the method when walking B, but we have no
kono
parents:
diff changeset
2298 link in between them.
kono
parents:
diff changeset
2299
kono
parents:
diff changeset
2300 We rely on fact that either the method is exported and thus we
kono
parents:
diff changeset
2301 assume it is called externally or C is in anonymous namespace and
kono
parents:
diff changeset
2302 thus we will see the vtable. */
kono
parents:
diff changeset
2303
kono
parents:
diff changeset
2304 else if (is_a <varpool_node *> (n)
kono
parents:
diff changeset
2305 && DECL_VIRTUAL_P (n->decl)
kono
parents:
diff changeset
2306 && TREE_CODE (DECL_CONTEXT (n->decl)) == RECORD_TYPE
kono
parents:
diff changeset
2307 && TYPE_BINFO (DECL_CONTEXT (n->decl))
kono
parents:
diff changeset
2308 && polymorphic_type_binfo_p (TYPE_BINFO (DECL_CONTEXT (n->decl))))
kono
parents:
diff changeset
2309 get_odr_type (TYPE_MAIN_VARIANT (DECL_CONTEXT (n->decl)), true);
kono
parents:
diff changeset
2310 if (inheritance_dump_file)
kono
parents:
diff changeset
2311 {
kono
parents:
diff changeset
2312 dump_type_inheritance_graph (inheritance_dump_file);
kono
parents:
diff changeset
2313 dump_end (TDI_inheritance, inheritance_dump_file);
kono
parents:
diff changeset
2314 }
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2315 free_odr_warning_data ();
111
kono
parents:
diff changeset
2316 timevar_pop (TV_IPA_INHERITANCE);
kono
parents:
diff changeset
2317 }
kono
parents:
diff changeset
2318
kono
parents:
diff changeset
2319 /* Return true if N has reference from live virtual table
kono
parents:
diff changeset
2320 (and thus can be a destination of polymorphic call).
kono
parents:
diff changeset
2321 Be conservatively correct when callgraph is not built or
kono
parents:
diff changeset
2322 if the method may be referred externally. */
kono
parents:
diff changeset
2323
kono
parents:
diff changeset
2324 static bool
kono
parents:
diff changeset
2325 referenced_from_vtable_p (struct cgraph_node *node)
kono
parents:
diff changeset
2326 {
kono
parents:
diff changeset
2327 int i;
kono
parents:
diff changeset
2328 struct ipa_ref *ref;
kono
parents:
diff changeset
2329 bool found = false;
kono
parents:
diff changeset
2330
kono
parents:
diff changeset
2331 if (node->externally_visible
kono
parents:
diff changeset
2332 || DECL_EXTERNAL (node->decl)
kono
parents:
diff changeset
2333 || node->used_from_other_partition)
kono
parents:
diff changeset
2334 return true;
kono
parents:
diff changeset
2335
kono
parents:
diff changeset
2336 /* Keep this test constant time.
kono
parents:
diff changeset
2337 It is unlikely this can happen except for the case where speculative
kono
parents:
diff changeset
2338 devirtualization introduced many speculative edges to this node.
kono
parents:
diff changeset
2339 In this case the target is very likely alive anyway. */
kono
parents:
diff changeset
2340 if (node->ref_list.referring.length () > 100)
kono
parents:
diff changeset
2341 return true;
kono
parents:
diff changeset
2342
kono
parents:
diff changeset
2343 /* We need references built. */
kono
parents:
diff changeset
2344 if (symtab->state <= CONSTRUCTION)
kono
parents:
diff changeset
2345 return true;
kono
parents:
diff changeset
2346
kono
parents:
diff changeset
2347 for (i = 0; node->iterate_referring (i, ref); i++)
kono
parents:
diff changeset
2348 if ((ref->use == IPA_REF_ALIAS
kono
parents:
diff changeset
2349 && referenced_from_vtable_p (dyn_cast<cgraph_node *> (ref->referring)))
kono
parents:
diff changeset
2350 || (ref->use == IPA_REF_ADDR
kono
parents:
diff changeset
2351 && VAR_P (ref->referring->decl)
kono
parents:
diff changeset
2352 && DECL_VIRTUAL_P (ref->referring->decl)))
kono
parents:
diff changeset
2353 {
kono
parents:
diff changeset
2354 found = true;
kono
parents:
diff changeset
2355 break;
kono
parents:
diff changeset
2356 }
kono
parents:
diff changeset
2357 return found;
kono
parents:
diff changeset
2358 }
kono
parents:
diff changeset
2359
kono
parents:
diff changeset
2360 /* Return if TARGET is cxa_pure_virtual. */
kono
parents:
diff changeset
2361
kono
parents:
diff changeset
2362 static bool
kono
parents:
diff changeset
2363 is_cxa_pure_virtual_p (tree target)
kono
parents:
diff changeset
2364 {
kono
parents:
diff changeset
2365 return target && TREE_CODE (TREE_TYPE (target)) != METHOD_TYPE
kono
parents:
diff changeset
2366 && DECL_NAME (target)
kono
parents:
diff changeset
2367 && id_equal (DECL_NAME (target),
kono
parents:
diff changeset
2368 "__cxa_pure_virtual");
kono
parents:
diff changeset
2369 }
kono
parents:
diff changeset
2370
kono
parents:
diff changeset
2371 /* If TARGET has associated node, record it in the NODES array.
kono
parents:
diff changeset
2372 CAN_REFER specify if program can refer to the target directly.
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2373 if TARGET is unknown (NULL) or it cannot be inserted (for example because
111
kono
parents:
diff changeset
2374 its body was already removed and there is no way to refer to it), clear
kono
parents:
diff changeset
2375 COMPLETEP. */
kono
parents:
diff changeset
2376
kono
parents:
diff changeset
2377 static void
kono
parents:
diff changeset
2378 maybe_record_node (vec <cgraph_node *> &nodes,
kono
parents:
diff changeset
2379 tree target, hash_set<tree> *inserted,
kono
parents:
diff changeset
2380 bool can_refer,
kono
parents:
diff changeset
2381 bool *completep)
kono
parents:
diff changeset
2382 {
kono
parents:
diff changeset
2383 struct cgraph_node *target_node, *alias_target;
kono
parents:
diff changeset
2384 enum availability avail;
kono
parents:
diff changeset
2385 bool pure_virtual = is_cxa_pure_virtual_p (target);
kono
parents:
diff changeset
2386
kono
parents:
diff changeset
2387 /* __builtin_unreachable do not need to be added into
kono
parents:
diff changeset
2388 list of targets; the runtime effect of calling them is undefined.
kono
parents:
diff changeset
2389 Only "real" virtual methods should be accounted. */
kono
parents:
diff changeset
2390 if (target && TREE_CODE (TREE_TYPE (target)) != METHOD_TYPE && !pure_virtual)
kono
parents:
diff changeset
2391 return;
kono
parents:
diff changeset
2392
kono
parents:
diff changeset
2393 if (!can_refer)
kono
parents:
diff changeset
2394 {
kono
parents:
diff changeset
2395 /* The only case when method of anonymous namespace becomes unreferable
kono
parents:
diff changeset
2396 is when we completely optimized it out. */
kono
parents:
diff changeset
2397 if (flag_ltrans
kono
parents:
diff changeset
2398 || !target
kono
parents:
diff changeset
2399 || !type_in_anonymous_namespace_p (DECL_CONTEXT (target)))
kono
parents:
diff changeset
2400 *completep = false;
kono
parents:
diff changeset
2401 return;
kono
parents:
diff changeset
2402 }
kono
parents:
diff changeset
2403
kono
parents:
diff changeset
2404 if (!target)
kono
parents:
diff changeset
2405 return;
kono
parents:
diff changeset
2406
kono
parents:
diff changeset
2407 target_node = cgraph_node::get (target);
kono
parents:
diff changeset
2408
kono
parents:
diff changeset
2409 /* Prefer alias target over aliases, so we do not get confused by
kono
parents:
diff changeset
2410 fake duplicates. */
kono
parents:
diff changeset
2411 if (target_node)
kono
parents:
diff changeset
2412 {
kono
parents:
diff changeset
2413 alias_target = target_node->ultimate_alias_target (&avail);
kono
parents:
diff changeset
2414 if (target_node != alias_target
kono
parents:
diff changeset
2415 && avail >= AVAIL_AVAILABLE
kono
parents:
diff changeset
2416 && target_node->get_availability ())
kono
parents:
diff changeset
2417 target_node = alias_target;
kono
parents:
diff changeset
2418 }
kono
parents:
diff changeset
2419
kono
parents:
diff changeset
2420 /* Method can only be called by polymorphic call if any
kono
parents:
diff changeset
2421 of vtables referring to it are alive.
kono
parents:
diff changeset
2422
kono
parents:
diff changeset
2423 While this holds for non-anonymous functions, too, there are
kono
parents:
diff changeset
2424 cases where we want to keep them in the list; for example
kono
parents:
diff changeset
2425 inline functions with -fno-weak are static, but we still
kono
parents:
diff changeset
2426 may devirtualize them when instance comes from other unit.
kono
parents:
diff changeset
2427 The same holds for LTO.
kono
parents:
diff changeset
2428
kono
parents:
diff changeset
2429 Currently we ignore these functions in speculative devirtualization.
kono
parents:
diff changeset
2430 ??? Maybe it would make sense to be more aggressive for LTO even
kono
parents:
diff changeset
2431 elsewhere. */
kono
parents:
diff changeset
2432 if (!flag_ltrans
kono
parents:
diff changeset
2433 && !pure_virtual
kono
parents:
diff changeset
2434 && type_in_anonymous_namespace_p (DECL_CONTEXT (target))
kono
parents:
diff changeset
2435 && (!target_node
kono
parents:
diff changeset
2436 || !referenced_from_vtable_p (target_node)))
kono
parents:
diff changeset
2437 ;
kono
parents:
diff changeset
2438 /* See if TARGET is useful function we can deal with. */
kono
parents:
diff changeset
2439 else if (target_node != NULL
kono
parents:
diff changeset
2440 && (TREE_PUBLIC (target)
kono
parents:
diff changeset
2441 || DECL_EXTERNAL (target)
kono
parents:
diff changeset
2442 || target_node->definition)
kono
parents:
diff changeset
2443 && target_node->real_symbol_p ())
kono
parents:
diff changeset
2444 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2445 gcc_assert (!target_node->inlined_to);
111
kono
parents:
diff changeset
2446 gcc_assert (target_node->real_symbol_p ());
kono
parents:
diff changeset
2447 /* When sanitizing, do not assume that __cxa_pure_virtual is not called
kono
parents:
diff changeset
2448 by valid program. */
kono
parents:
diff changeset
2449 if (flag_sanitize & SANITIZE_UNREACHABLE)
kono
parents:
diff changeset
2450 ;
kono
parents:
diff changeset
2451 /* Only add pure virtual if it is the only possible target. This way
kono
parents:
diff changeset
2452 we will preserve the diagnostics about pure virtual called in many
kono
parents:
diff changeset
2453 cases without disabling optimization in other. */
kono
parents:
diff changeset
2454 else if (pure_virtual)
kono
parents:
diff changeset
2455 {
kono
parents:
diff changeset
2456 if (nodes.length ())
kono
parents:
diff changeset
2457 return;
kono
parents:
diff changeset
2458 }
kono
parents:
diff changeset
2459 /* If we found a real target, take away cxa_pure_virtual. */
kono
parents:
diff changeset
2460 else if (!pure_virtual && nodes.length () == 1
kono
parents:
diff changeset
2461 && is_cxa_pure_virtual_p (nodes[0]->decl))
kono
parents:
diff changeset
2462 nodes.pop ();
kono
parents:
diff changeset
2463 if (pure_virtual && nodes.length ())
kono
parents:
diff changeset
2464 return;
kono
parents:
diff changeset
2465 if (!inserted->add (target))
kono
parents:
diff changeset
2466 {
kono
parents:
diff changeset
2467 cached_polymorphic_call_targets->add (target_node);
kono
parents:
diff changeset
2468 nodes.safe_push (target_node);
kono
parents:
diff changeset
2469 }
kono
parents:
diff changeset
2470 }
kono
parents:
diff changeset
2471 else if (!completep)
kono
parents:
diff changeset
2472 ;
kono
parents:
diff changeset
2473 /* We have definition of __cxa_pure_virtual that is not accessible (it is
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2474 optimized out or partitioned to other unit) so we cannot add it. When
111
kono
parents:
diff changeset
2475 not sanitizing, there is nothing to do.
kono
parents:
diff changeset
2476 Otherwise declare the list incomplete. */
kono
parents:
diff changeset
2477 else if (pure_virtual)
kono
parents:
diff changeset
2478 {
kono
parents:
diff changeset
2479 if (flag_sanitize & SANITIZE_UNREACHABLE)
kono
parents:
diff changeset
2480 *completep = false;
kono
parents:
diff changeset
2481 }
kono
parents:
diff changeset
2482 else if (flag_ltrans
kono
parents:
diff changeset
2483 || !type_in_anonymous_namespace_p (DECL_CONTEXT (target)))
kono
parents:
diff changeset
2484 *completep = false;
kono
parents:
diff changeset
2485 }
kono
parents:
diff changeset
2486
kono
parents:
diff changeset
2487 /* See if BINFO's type matches OUTER_TYPE. If so, look up
kono
parents:
diff changeset
2488 BINFO of subtype of OTR_TYPE at OFFSET and in that BINFO find
kono
parents:
diff changeset
2489 method in vtable and insert method to NODES array
kono
parents:
diff changeset
2490 or BASES_TO_CONSIDER if this array is non-NULL.
kono
parents:
diff changeset
2491 Otherwise recurse to base BINFOs.
kono
parents:
diff changeset
2492 This matches what get_binfo_at_offset does, but with offset
kono
parents:
diff changeset
2493 being unknown.
kono
parents:
diff changeset
2494
kono
parents:
diff changeset
2495 TYPE_BINFOS is a stack of BINFOS of types with defined
kono
parents:
diff changeset
2496 virtual table seen on way from class type to BINFO.
kono
parents:
diff changeset
2497
kono
parents:
diff changeset
2498 MATCHED_VTABLES tracks virtual tables we already did lookup
kono
parents:
diff changeset
2499 for virtual function in. INSERTED tracks nodes we already
kono
parents:
diff changeset
2500 inserted.
kono
parents:
diff changeset
2501
kono
parents:
diff changeset
2502 ANONYMOUS is true if BINFO is part of anonymous namespace.
kono
parents:
diff changeset
2503
kono
parents:
diff changeset
2504 Clear COMPLETEP when we hit unreferable target.
kono
parents:
diff changeset
2505 */
kono
parents:
diff changeset
2506
kono
parents:
diff changeset
2507 static void
kono
parents:
diff changeset
2508 record_target_from_binfo (vec <cgraph_node *> &nodes,
kono
parents:
diff changeset
2509 vec <tree> *bases_to_consider,
kono
parents:
diff changeset
2510 tree binfo,
kono
parents:
diff changeset
2511 tree otr_type,
kono
parents:
diff changeset
2512 vec <tree> &type_binfos,
kono
parents:
diff changeset
2513 HOST_WIDE_INT otr_token,
kono
parents:
diff changeset
2514 tree outer_type,
kono
parents:
diff changeset
2515 HOST_WIDE_INT offset,
kono
parents:
diff changeset
2516 hash_set<tree> *inserted,
kono
parents:
diff changeset
2517 hash_set<tree> *matched_vtables,
kono
parents:
diff changeset
2518 bool anonymous,
kono
parents:
diff changeset
2519 bool *completep)
kono
parents:
diff changeset
2520 {
kono
parents:
diff changeset
2521 tree type = BINFO_TYPE (binfo);
kono
parents:
diff changeset
2522 int i;
kono
parents:
diff changeset
2523 tree base_binfo;
kono
parents:
diff changeset
2524
kono
parents:
diff changeset
2525
kono
parents:
diff changeset
2526 if (BINFO_VTABLE (binfo))
kono
parents:
diff changeset
2527 type_binfos.safe_push (binfo);
kono
parents:
diff changeset
2528 if (types_same_for_odr (type, outer_type))
kono
parents:
diff changeset
2529 {
kono
parents:
diff changeset
2530 int i;
kono
parents:
diff changeset
2531 tree type_binfo = NULL;
kono
parents:
diff changeset
2532
kono
parents:
diff changeset
2533 /* Look up BINFO with virtual table. For normal types it is always last
kono
parents:
diff changeset
2534 binfo on stack. */
kono
parents:
diff changeset
2535 for (i = type_binfos.length () - 1; i >= 0; i--)
kono
parents:
diff changeset
2536 if (BINFO_OFFSET (type_binfos[i]) == BINFO_OFFSET (binfo))
kono
parents:
diff changeset
2537 {
kono
parents:
diff changeset
2538 type_binfo = type_binfos[i];
kono
parents:
diff changeset
2539 break;
kono
parents:
diff changeset
2540 }
kono
parents:
diff changeset
2541 if (BINFO_VTABLE (binfo))
kono
parents:
diff changeset
2542 type_binfos.pop ();
kono
parents:
diff changeset
2543 /* If this is duplicated BINFO for base shared by virtual inheritance,
kono
parents:
diff changeset
2544 we may not have its associated vtable. This is not a problem, since
kono
parents:
diff changeset
2545 we will walk it on the other path. */
kono
parents:
diff changeset
2546 if (!type_binfo)
kono
parents:
diff changeset
2547 return;
kono
parents:
diff changeset
2548 tree inner_binfo = get_binfo_at_offset (type_binfo,
kono
parents:
diff changeset
2549 offset, otr_type);
kono
parents:
diff changeset
2550 if (!inner_binfo)
kono
parents:
diff changeset
2551 {
kono
parents:
diff changeset
2552 gcc_assert (odr_violation_reported);
kono
parents:
diff changeset
2553 return;
kono
parents:
diff changeset
2554 }
kono
parents:
diff changeset
2555 /* For types in anonymous namespace first check if the respective vtable
kono
parents:
diff changeset
2556 is alive. If not, we know the type can't be called. */
kono
parents:
diff changeset
2557 if (!flag_ltrans && anonymous)
kono
parents:
diff changeset
2558 {
kono
parents:
diff changeset
2559 tree vtable = BINFO_VTABLE (inner_binfo);
kono
parents:
diff changeset
2560 varpool_node *vnode;
kono
parents:
diff changeset
2561
kono
parents:
diff changeset
2562 if (TREE_CODE (vtable) == POINTER_PLUS_EXPR)
kono
parents:
diff changeset
2563 vtable = TREE_OPERAND (TREE_OPERAND (vtable, 0), 0);
kono
parents:
diff changeset
2564 vnode = varpool_node::get (vtable);
kono
parents:
diff changeset
2565 if (!vnode || !vnode->definition)
kono
parents:
diff changeset
2566 return;
kono
parents:
diff changeset
2567 }
kono
parents:
diff changeset
2568 gcc_assert (inner_binfo);
kono
parents:
diff changeset
2569 if (bases_to_consider
kono
parents:
diff changeset
2570 ? !matched_vtables->contains (BINFO_VTABLE (inner_binfo))
kono
parents:
diff changeset
2571 : !matched_vtables->add (BINFO_VTABLE (inner_binfo)))
kono
parents:
diff changeset
2572 {
kono
parents:
diff changeset
2573 bool can_refer;
kono
parents:
diff changeset
2574 tree target = gimple_get_virt_method_for_binfo (otr_token,
kono
parents:
diff changeset
2575 inner_binfo,
kono
parents:
diff changeset
2576 &can_refer);
kono
parents:
diff changeset
2577 if (!bases_to_consider)
kono
parents:
diff changeset
2578 maybe_record_node (nodes, target, inserted, can_refer, completep);
kono
parents:
diff changeset
2579 /* Destructors are never called via construction vtables. */
kono
parents:
diff changeset
2580 else if (!target || !DECL_CXX_DESTRUCTOR_P (target))
kono
parents:
diff changeset
2581 bases_to_consider->safe_push (target);
kono
parents:
diff changeset
2582 }
kono
parents:
diff changeset
2583 return;
kono
parents:
diff changeset
2584 }
kono
parents:
diff changeset
2585
kono
parents:
diff changeset
2586 /* Walk bases. */
kono
parents:
diff changeset
2587 for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
kono
parents:
diff changeset
2588 /* Walking bases that have no virtual method is pointless exercise. */
kono
parents:
diff changeset
2589 if (polymorphic_type_binfo_p (base_binfo))
kono
parents:
diff changeset
2590 record_target_from_binfo (nodes, bases_to_consider, base_binfo, otr_type,
kono
parents:
diff changeset
2591 type_binfos,
kono
parents:
diff changeset
2592 otr_token, outer_type, offset, inserted,
kono
parents:
diff changeset
2593 matched_vtables, anonymous, completep);
kono
parents:
diff changeset
2594 if (BINFO_VTABLE (binfo))
kono
parents:
diff changeset
2595 type_binfos.pop ();
kono
parents:
diff changeset
2596 }
kono
parents:
diff changeset
2597
kono
parents:
diff changeset
2598 /* Look up virtual methods matching OTR_TYPE (with OFFSET and OTR_TOKEN)
kono
parents:
diff changeset
2599 of TYPE, insert them to NODES, recurse into derived nodes.
kono
parents:
diff changeset
2600 INSERTED is used to avoid duplicate insertions of methods into NODES.
kono
parents:
diff changeset
2601 MATCHED_VTABLES are used to avoid duplicate walking vtables.
kono
parents:
diff changeset
2602 Clear COMPLETEP if unreferable target is found.
kono
parents:
diff changeset
2603
kono
parents:
diff changeset
2604 If CONSIDER_CONSTRUCTION is true, record to BASES_TO_CONSIDER
kono
parents:
diff changeset
2605 all cases where BASE_SKIPPED is true (because the base is abstract
kono
parents:
diff changeset
2606 class). */
kono
parents:
diff changeset
2607
kono
parents:
diff changeset
2608 static void
kono
parents:
diff changeset
2609 possible_polymorphic_call_targets_1 (vec <cgraph_node *> &nodes,
kono
parents:
diff changeset
2610 hash_set<tree> *inserted,
kono
parents:
diff changeset
2611 hash_set<tree> *matched_vtables,
kono
parents:
diff changeset
2612 tree otr_type,
kono
parents:
diff changeset
2613 odr_type type,
kono
parents:
diff changeset
2614 HOST_WIDE_INT otr_token,
kono
parents:
diff changeset
2615 tree outer_type,
kono
parents:
diff changeset
2616 HOST_WIDE_INT offset,
kono
parents:
diff changeset
2617 bool *completep,
kono
parents:
diff changeset
2618 vec <tree> &bases_to_consider,
kono
parents:
diff changeset
2619 bool consider_construction)
kono
parents:
diff changeset
2620 {
kono
parents:
diff changeset
2621 tree binfo = TYPE_BINFO (type->type);
kono
parents:
diff changeset
2622 unsigned int i;
kono
parents:
diff changeset
2623 auto_vec <tree, 8> type_binfos;
kono
parents:
diff changeset
2624 bool possibly_instantiated = type_possibly_instantiated_p (type->type);
kono
parents:
diff changeset
2625
kono
parents:
diff changeset
2626 /* We may need to consider types w/o instances because of possible derived
kono
parents:
diff changeset
2627 types using their methods either directly or via construction vtables.
kono
parents:
diff changeset
2628 We are safe to skip them when all derivations are known, since we will
kono
parents:
diff changeset
2629 handle them later.
kono
parents:
diff changeset
2630 This is done by recording them to BASES_TO_CONSIDER array. */
kono
parents:
diff changeset
2631 if (possibly_instantiated || consider_construction)
kono
parents:
diff changeset
2632 {
kono
parents:
diff changeset
2633 record_target_from_binfo (nodes,
kono
parents:
diff changeset
2634 (!possibly_instantiated
kono
parents:
diff changeset
2635 && type_all_derivations_known_p (type->type))
kono
parents:
diff changeset
2636 ? &bases_to_consider : NULL,
kono
parents:
diff changeset
2637 binfo, otr_type, type_binfos, otr_token,
kono
parents:
diff changeset
2638 outer_type, offset,
kono
parents:
diff changeset
2639 inserted, matched_vtables,
kono
parents:
diff changeset
2640 type->anonymous_namespace, completep);
kono
parents:
diff changeset
2641 }
kono
parents:
diff changeset
2642 for (i = 0; i < type->derived_types.length (); i++)
kono
parents:
diff changeset
2643 possible_polymorphic_call_targets_1 (nodes, inserted,
kono
parents:
diff changeset
2644 matched_vtables,
kono
parents:
diff changeset
2645 otr_type,
kono
parents:
diff changeset
2646 type->derived_types[i],
kono
parents:
diff changeset
2647 otr_token, outer_type, offset, completep,
kono
parents:
diff changeset
2648 bases_to_consider, consider_construction);
kono
parents:
diff changeset
2649 }
kono
parents:
diff changeset
2650
kono
parents:
diff changeset
2651 /* Cache of queries for polymorphic call targets.
kono
parents:
diff changeset
2652
kono
parents:
diff changeset
2653 Enumerating all call targets may get expensive when there are many
kono
parents:
diff changeset
2654 polymorphic calls in the program, so we memoize all the previous
kono
parents:
diff changeset
2655 queries and avoid duplicated work. */
kono
parents:
diff changeset
2656
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2657 class polymorphic_call_target_d
111
kono
parents:
diff changeset
2658 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2659 public:
111
kono
parents:
diff changeset
2660 HOST_WIDE_INT otr_token;
kono
parents:
diff changeset
2661 ipa_polymorphic_call_context context;
kono
parents:
diff changeset
2662 odr_type type;
kono
parents:
diff changeset
2663 vec <cgraph_node *> targets;
kono
parents:
diff changeset
2664 tree decl_warning;
kono
parents:
diff changeset
2665 int type_warning;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2666 unsigned int n_odr_types;
111
kono
parents:
diff changeset
2667 bool complete;
kono
parents:
diff changeset
2668 bool speculative;
kono
parents:
diff changeset
2669 };
kono
parents:
diff changeset
2670
kono
parents:
diff changeset
2671 /* Polymorphic call target cache helpers. */
kono
parents:
diff changeset
2672
kono
parents:
diff changeset
2673 struct polymorphic_call_target_hasher
kono
parents:
diff changeset
2674 : pointer_hash <polymorphic_call_target_d>
kono
parents:
diff changeset
2675 {
kono
parents:
diff changeset
2676 static inline hashval_t hash (const polymorphic_call_target_d *);
kono
parents:
diff changeset
2677 static inline bool equal (const polymorphic_call_target_d *,
kono
parents:
diff changeset
2678 const polymorphic_call_target_d *);
kono
parents:
diff changeset
2679 static inline void remove (polymorphic_call_target_d *);
kono
parents:
diff changeset
2680 };
kono
parents:
diff changeset
2681
kono
parents:
diff changeset
2682 /* Return the computed hashcode for ODR_QUERY. */
kono
parents:
diff changeset
2683
kono
parents:
diff changeset
2684 inline hashval_t
kono
parents:
diff changeset
2685 polymorphic_call_target_hasher::hash (const polymorphic_call_target_d *odr_query)
kono
parents:
diff changeset
2686 {
kono
parents:
diff changeset
2687 inchash::hash hstate (odr_query->otr_token);
kono
parents:
diff changeset
2688
kono
parents:
diff changeset
2689 hstate.add_hwi (odr_query->type->id);
kono
parents:
diff changeset
2690 hstate.merge_hash (TYPE_UID (odr_query->context.outer_type));
kono
parents:
diff changeset
2691 hstate.add_hwi (odr_query->context.offset);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2692 hstate.add_hwi (odr_query->n_odr_types);
111
kono
parents:
diff changeset
2693
kono
parents:
diff changeset
2694 if (odr_query->context.speculative_outer_type)
kono
parents:
diff changeset
2695 {
kono
parents:
diff changeset
2696 hstate.merge_hash (TYPE_UID (odr_query->context.speculative_outer_type));
kono
parents:
diff changeset
2697 hstate.add_hwi (odr_query->context.speculative_offset);
kono
parents:
diff changeset
2698 }
kono
parents:
diff changeset
2699 hstate.add_flag (odr_query->speculative);
kono
parents:
diff changeset
2700 hstate.add_flag (odr_query->context.maybe_in_construction);
kono
parents:
diff changeset
2701 hstate.add_flag (odr_query->context.maybe_derived_type);
kono
parents:
diff changeset
2702 hstate.add_flag (odr_query->context.speculative_maybe_derived_type);
kono
parents:
diff changeset
2703 hstate.commit_flag ();
kono
parents:
diff changeset
2704 return hstate.end ();
kono
parents:
diff changeset
2705 }
kono
parents:
diff changeset
2706
kono
parents:
diff changeset
2707 /* Compare cache entries T1 and T2. */
kono
parents:
diff changeset
2708
kono
parents:
diff changeset
2709 inline bool
kono
parents:
diff changeset
2710 polymorphic_call_target_hasher::equal (const polymorphic_call_target_d *t1,
kono
parents:
diff changeset
2711 const polymorphic_call_target_d *t2)
kono
parents:
diff changeset
2712 {
kono
parents:
diff changeset
2713 return (t1->type == t2->type && t1->otr_token == t2->otr_token
kono
parents:
diff changeset
2714 && t1->speculative == t2->speculative
kono
parents:
diff changeset
2715 && t1->context.offset == t2->context.offset
kono
parents:
diff changeset
2716 && t1->context.speculative_offset == t2->context.speculative_offset
kono
parents:
diff changeset
2717 && t1->context.outer_type == t2->context.outer_type
kono
parents:
diff changeset
2718 && t1->context.speculative_outer_type == t2->context.speculative_outer_type
kono
parents:
diff changeset
2719 && t1->context.maybe_in_construction
kono
parents:
diff changeset
2720 == t2->context.maybe_in_construction
kono
parents:
diff changeset
2721 && t1->context.maybe_derived_type == t2->context.maybe_derived_type
kono
parents:
diff changeset
2722 && (t1->context.speculative_maybe_derived_type
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2723 == t2->context.speculative_maybe_derived_type)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2724 /* Adding new type may affect outcome of target search. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2725 && t1->n_odr_types == t2->n_odr_types);
111
kono
parents:
diff changeset
2726 }
kono
parents:
diff changeset
2727
kono
parents:
diff changeset
2728 /* Remove entry in polymorphic call target cache hash. */
kono
parents:
diff changeset
2729
kono
parents:
diff changeset
2730 inline void
kono
parents:
diff changeset
2731 polymorphic_call_target_hasher::remove (polymorphic_call_target_d *v)
kono
parents:
diff changeset
2732 {
kono
parents:
diff changeset
2733 v->targets.release ();
kono
parents:
diff changeset
2734 free (v);
kono
parents:
diff changeset
2735 }
kono
parents:
diff changeset
2736
kono
parents:
diff changeset
2737 /* Polymorphic call target query cache. */
kono
parents:
diff changeset
2738
kono
parents:
diff changeset
2739 typedef hash_table<polymorphic_call_target_hasher>
kono
parents:
diff changeset
2740 polymorphic_call_target_hash_type;
kono
parents:
diff changeset
2741 static polymorphic_call_target_hash_type *polymorphic_call_target_hash;
kono
parents:
diff changeset
2742
kono
parents:
diff changeset
2743 /* Destroy polymorphic call target query cache. */
kono
parents:
diff changeset
2744
kono
parents:
diff changeset
2745 static void
kono
parents:
diff changeset
2746 free_polymorphic_call_targets_hash ()
kono
parents:
diff changeset
2747 {
kono
parents:
diff changeset
2748 if (cached_polymorphic_call_targets)
kono
parents:
diff changeset
2749 {
kono
parents:
diff changeset
2750 delete polymorphic_call_target_hash;
kono
parents:
diff changeset
2751 polymorphic_call_target_hash = NULL;
kono
parents:
diff changeset
2752 delete cached_polymorphic_call_targets;
kono
parents:
diff changeset
2753 cached_polymorphic_call_targets = NULL;
kono
parents:
diff changeset
2754 }
kono
parents:
diff changeset
2755 }
kono
parents:
diff changeset
2756
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2757 /* Force rebuilding type inheritance graph from scratch.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2758 This is use to make sure that we do not keep references to types
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2759 which was not visible to free_lang_data. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2760
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2761 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2762 rebuild_type_inheritance_graph ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2763 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2764 if (!odr_hash)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2765 return;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2766 delete odr_hash;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2767 odr_hash = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2768 odr_types_ptr = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2769 free_polymorphic_call_targets_hash ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2770 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2771
111
kono
parents:
diff changeset
2772 /* When virtual function is removed, we may need to flush the cache. */
kono
parents:
diff changeset
2773
kono
parents:
diff changeset
2774 static void
kono
parents:
diff changeset
2775 devirt_node_removal_hook (struct cgraph_node *n, void *d ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2776 {
kono
parents:
diff changeset
2777 if (cached_polymorphic_call_targets
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2778 && !thunk_expansion
111
kono
parents:
diff changeset
2779 && cached_polymorphic_call_targets->contains (n))
kono
parents:
diff changeset
2780 free_polymorphic_call_targets_hash ();
kono
parents:
diff changeset
2781 }
kono
parents:
diff changeset
2782
kono
parents:
diff changeset
2783 /* Look up base of BINFO that has virtual table VTABLE with OFFSET. */
kono
parents:
diff changeset
2784
kono
parents:
diff changeset
2785 tree
kono
parents:
diff changeset
2786 subbinfo_with_vtable_at_offset (tree binfo, unsigned HOST_WIDE_INT offset,
kono
parents:
diff changeset
2787 tree vtable)
kono
parents:
diff changeset
2788 {
kono
parents:
diff changeset
2789 tree v = BINFO_VTABLE (binfo);
kono
parents:
diff changeset
2790 int i;
kono
parents:
diff changeset
2791 tree base_binfo;
kono
parents:
diff changeset
2792 unsigned HOST_WIDE_INT this_offset;
kono
parents:
diff changeset
2793
kono
parents:
diff changeset
2794 if (v)
kono
parents:
diff changeset
2795 {
kono
parents:
diff changeset
2796 if (!vtable_pointer_value_to_vtable (v, &v, &this_offset))
kono
parents:
diff changeset
2797 gcc_unreachable ();
kono
parents:
diff changeset
2798
kono
parents:
diff changeset
2799 if (offset == this_offset
kono
parents:
diff changeset
2800 && DECL_ASSEMBLER_NAME (v) == DECL_ASSEMBLER_NAME (vtable))
kono
parents:
diff changeset
2801 return binfo;
kono
parents:
diff changeset
2802 }
kono
parents:
diff changeset
2803
kono
parents:
diff changeset
2804 for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
kono
parents:
diff changeset
2805 if (polymorphic_type_binfo_p (base_binfo))
kono
parents:
diff changeset
2806 {
kono
parents:
diff changeset
2807 base_binfo = subbinfo_with_vtable_at_offset (base_binfo, offset, vtable);
kono
parents:
diff changeset
2808 if (base_binfo)
kono
parents:
diff changeset
2809 return base_binfo;
kono
parents:
diff changeset
2810 }
kono
parents:
diff changeset
2811 return NULL;
kono
parents:
diff changeset
2812 }
kono
parents:
diff changeset
2813
kono
parents:
diff changeset
2814 /* T is known constant value of virtual table pointer.
kono
parents:
diff changeset
2815 Store virtual table to V and its offset to OFFSET.
kono
parents:
diff changeset
2816 Return false if T does not look like virtual table reference. */
kono
parents:
diff changeset
2817
kono
parents:
diff changeset
2818 bool
kono
parents:
diff changeset
2819 vtable_pointer_value_to_vtable (const_tree t, tree *v,
kono
parents:
diff changeset
2820 unsigned HOST_WIDE_INT *offset)
kono
parents:
diff changeset
2821 {
kono
parents:
diff changeset
2822 /* We expect &MEM[(void *)&virtual_table + 16B].
kono
parents:
diff changeset
2823 We obtain object's BINFO from the context of the virtual table.
kono
parents:
diff changeset
2824 This one contains pointer to virtual table represented via
kono
parents:
diff changeset
2825 POINTER_PLUS_EXPR. Verify that this pointer matches what
kono
parents:
diff changeset
2826 we propagated through.
kono
parents:
diff changeset
2827
kono
parents:
diff changeset
2828 In the case of virtual inheritance, the virtual tables may
kono
parents:
diff changeset
2829 be nested, i.e. the offset may be different from 16 and we may
kono
parents:
diff changeset
2830 need to dive into the type representation. */
kono
parents:
diff changeset
2831 if (TREE_CODE (t) == ADDR_EXPR
kono
parents:
diff changeset
2832 && TREE_CODE (TREE_OPERAND (t, 0)) == MEM_REF
kono
parents:
diff changeset
2833 && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 0)) == ADDR_EXPR
kono
parents:
diff changeset
2834 && TREE_CODE (TREE_OPERAND (TREE_OPERAND (t, 0), 1)) == INTEGER_CST
kono
parents:
diff changeset
2835 && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 0), 0), 0))
kono
parents:
diff changeset
2836 == VAR_DECL)
kono
parents:
diff changeset
2837 && DECL_VIRTUAL_P (TREE_OPERAND (TREE_OPERAND
kono
parents:
diff changeset
2838 (TREE_OPERAND (t, 0), 0), 0)))
kono
parents:
diff changeset
2839 {
kono
parents:
diff changeset
2840 *v = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 0), 0), 0);
kono
parents:
diff changeset
2841 *offset = tree_to_uhwi (TREE_OPERAND (TREE_OPERAND (t, 0), 1));
kono
parents:
diff changeset
2842 return true;
kono
parents:
diff changeset
2843 }
kono
parents:
diff changeset
2844
kono
parents:
diff changeset
2845 /* Alternative representation, used by C++ frontend is POINTER_PLUS_EXPR.
kono
parents:
diff changeset
2846 We need to handle it when T comes from static variable initializer or
kono
parents:
diff changeset
2847 BINFO. */
kono
parents:
diff changeset
2848 if (TREE_CODE (t) == POINTER_PLUS_EXPR)
kono
parents:
diff changeset
2849 {
kono
parents:
diff changeset
2850 *offset = tree_to_uhwi (TREE_OPERAND (t, 1));
kono
parents:
diff changeset
2851 t = TREE_OPERAND (t, 0);
kono
parents:
diff changeset
2852 }
kono
parents:
diff changeset
2853 else
kono
parents:
diff changeset
2854 *offset = 0;
kono
parents:
diff changeset
2855
kono
parents:
diff changeset
2856 if (TREE_CODE (t) != ADDR_EXPR)
kono
parents:
diff changeset
2857 return false;
kono
parents:
diff changeset
2858 *v = TREE_OPERAND (t, 0);
kono
parents:
diff changeset
2859 return true;
kono
parents:
diff changeset
2860 }
kono
parents:
diff changeset
2861
kono
parents:
diff changeset
2862 /* T is known constant value of virtual table pointer. Return BINFO of the
kono
parents:
diff changeset
2863 instance type. */
kono
parents:
diff changeset
2864
kono
parents:
diff changeset
2865 tree
kono
parents:
diff changeset
2866 vtable_pointer_value_to_binfo (const_tree t)
kono
parents:
diff changeset
2867 {
kono
parents:
diff changeset
2868 tree vtable;
kono
parents:
diff changeset
2869 unsigned HOST_WIDE_INT offset;
kono
parents:
diff changeset
2870
kono
parents:
diff changeset
2871 if (!vtable_pointer_value_to_vtable (t, &vtable, &offset))
kono
parents:
diff changeset
2872 return NULL_TREE;
kono
parents:
diff changeset
2873
kono
parents:
diff changeset
2874 /* FIXME: for stores of construction vtables we return NULL,
kono
parents:
diff changeset
2875 because we do not have BINFO for those. Eventually we should fix
kono
parents:
diff changeset
2876 our representation to allow this case to be handled, too.
kono
parents:
diff changeset
2877 In the case we see store of BINFO we however may assume
kono
parents:
diff changeset
2878 that standard folding will be able to cope with it. */
kono
parents:
diff changeset
2879 return subbinfo_with_vtable_at_offset (TYPE_BINFO (DECL_CONTEXT (vtable)),
kono
parents:
diff changeset
2880 offset, vtable);
kono
parents:
diff changeset
2881 }
kono
parents:
diff changeset
2882
kono
parents:
diff changeset
2883 /* Walk bases of OUTER_TYPE that contain OTR_TYPE at OFFSET.
kono
parents:
diff changeset
2884 Look up their respective virtual methods for OTR_TOKEN and OTR_TYPE
kono
parents:
diff changeset
2885 and insert them in NODES.
kono
parents:
diff changeset
2886
kono
parents:
diff changeset
2887 MATCHED_VTABLES and INSERTED is used to avoid duplicated work. */
kono
parents:
diff changeset
2888
kono
parents:
diff changeset
2889 static void
kono
parents:
diff changeset
2890 record_targets_from_bases (tree otr_type,
kono
parents:
diff changeset
2891 HOST_WIDE_INT otr_token,
kono
parents:
diff changeset
2892 tree outer_type,
kono
parents:
diff changeset
2893 HOST_WIDE_INT offset,
kono
parents:
diff changeset
2894 vec <cgraph_node *> &nodes,
kono
parents:
diff changeset
2895 hash_set<tree> *inserted,
kono
parents:
diff changeset
2896 hash_set<tree> *matched_vtables,
kono
parents:
diff changeset
2897 bool *completep)
kono
parents:
diff changeset
2898 {
kono
parents:
diff changeset
2899 while (true)
kono
parents:
diff changeset
2900 {
kono
parents:
diff changeset
2901 HOST_WIDE_INT pos, size;
kono
parents:
diff changeset
2902 tree base_binfo;
kono
parents:
diff changeset
2903 tree fld;
kono
parents:
diff changeset
2904
kono
parents:
diff changeset
2905 if (types_same_for_odr (outer_type, otr_type))
kono
parents:
diff changeset
2906 return;
kono
parents:
diff changeset
2907
kono
parents:
diff changeset
2908 for (fld = TYPE_FIELDS (outer_type); fld; fld = DECL_CHAIN (fld))
kono
parents:
diff changeset
2909 {
kono
parents:
diff changeset
2910 if (TREE_CODE (fld) != FIELD_DECL)
kono
parents:
diff changeset
2911 continue;
kono
parents:
diff changeset
2912
kono
parents:
diff changeset
2913 pos = int_bit_position (fld);
kono
parents:
diff changeset
2914 size = tree_to_shwi (DECL_SIZE (fld));
kono
parents:
diff changeset
2915 if (pos <= offset && (pos + size) > offset
kono
parents:
diff changeset
2916 /* Do not get confused by zero sized bases. */
kono
parents:
diff changeset
2917 && polymorphic_type_binfo_p (TYPE_BINFO (TREE_TYPE (fld))))
kono
parents:
diff changeset
2918 break;
kono
parents:
diff changeset
2919 }
kono
parents:
diff changeset
2920 /* Within a class type we should always find corresponding fields. */
kono
parents:
diff changeset
2921 gcc_assert (fld && TREE_CODE (TREE_TYPE (fld)) == RECORD_TYPE);
kono
parents:
diff changeset
2922
kono
parents:
diff changeset
2923 /* Nonbase types should have been stripped by outer_class_type. */
kono
parents:
diff changeset
2924 gcc_assert (DECL_ARTIFICIAL (fld));
kono
parents:
diff changeset
2925
kono
parents:
diff changeset
2926 outer_type = TREE_TYPE (fld);
kono
parents:
diff changeset
2927 offset -= pos;
kono
parents:
diff changeset
2928
kono
parents:
diff changeset
2929 base_binfo = get_binfo_at_offset (TYPE_BINFO (outer_type),
kono
parents:
diff changeset
2930 offset, otr_type);
kono
parents:
diff changeset
2931 if (!base_binfo)
kono
parents:
diff changeset
2932 {
kono
parents:
diff changeset
2933 gcc_assert (odr_violation_reported);
kono
parents:
diff changeset
2934 return;
kono
parents:
diff changeset
2935 }
kono
parents:
diff changeset
2936 gcc_assert (base_binfo);
kono
parents:
diff changeset
2937 if (!matched_vtables->add (BINFO_VTABLE (base_binfo)))
kono
parents:
diff changeset
2938 {
kono
parents:
diff changeset
2939 bool can_refer;
kono
parents:
diff changeset
2940 tree target = gimple_get_virt_method_for_binfo (otr_token,
kono
parents:
diff changeset
2941 base_binfo,
kono
parents:
diff changeset
2942 &can_refer);
kono
parents:
diff changeset
2943 if (!target || ! DECL_CXX_DESTRUCTOR_P (target))
kono
parents:
diff changeset
2944 maybe_record_node (nodes, target, inserted, can_refer, completep);
kono
parents:
diff changeset
2945 matched_vtables->add (BINFO_VTABLE (base_binfo));
kono
parents:
diff changeset
2946 }
kono
parents:
diff changeset
2947 }
kono
parents:
diff changeset
2948 }
kono
parents:
diff changeset
2949
kono
parents:
diff changeset
2950 /* When virtual table is removed, we may need to flush the cache. */
kono
parents:
diff changeset
2951
kono
parents:
diff changeset
2952 static void
kono
parents:
diff changeset
2953 devirt_variable_node_removal_hook (varpool_node *n,
kono
parents:
diff changeset
2954 void *d ATTRIBUTE_UNUSED)
kono
parents:
diff changeset
2955 {
kono
parents:
diff changeset
2956 if (cached_polymorphic_call_targets
kono
parents:
diff changeset
2957 && DECL_VIRTUAL_P (n->decl)
kono
parents:
diff changeset
2958 && type_in_anonymous_namespace_p (DECL_CONTEXT (n->decl)))
kono
parents:
diff changeset
2959 free_polymorphic_call_targets_hash ();
kono
parents:
diff changeset
2960 }
kono
parents:
diff changeset
2961
kono
parents:
diff changeset
2962 /* Record about how many calls would benefit from given type to be final. */
kono
parents:
diff changeset
2963
kono
parents:
diff changeset
2964 struct odr_type_warn_count
kono
parents:
diff changeset
2965 {
kono
parents:
diff changeset
2966 tree type;
kono
parents:
diff changeset
2967 int count;
kono
parents:
diff changeset
2968 profile_count dyn_count;
kono
parents:
diff changeset
2969 };
kono
parents:
diff changeset
2970
kono
parents:
diff changeset
2971 /* Record about how many calls would benefit from given method to be final. */
kono
parents:
diff changeset
2972
kono
parents:
diff changeset
2973 struct decl_warn_count
kono
parents:
diff changeset
2974 {
kono
parents:
diff changeset
2975 tree decl;
kono
parents:
diff changeset
2976 int count;
kono
parents:
diff changeset
2977 profile_count dyn_count;
kono
parents:
diff changeset
2978 };
kono
parents:
diff changeset
2979
kono
parents:
diff changeset
2980 /* Information about type and decl warnings. */
kono
parents:
diff changeset
2981
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2982 class final_warning_record
111
kono
parents:
diff changeset
2983 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
2984 public:
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2985 /* If needed grow type_warnings vector and initialize new decl_warn_count
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2986 to have dyn_count set to profile_count::zero (). */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2987 void grow_type_warnings (unsigned newlen);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2988
111
kono
parents:
diff changeset
2989 profile_count dyn_count;
kono
parents:
diff changeset
2990 auto_vec<odr_type_warn_count> type_warnings;
kono
parents:
diff changeset
2991 hash_map<tree, decl_warn_count> decl_warnings;
kono
parents:
diff changeset
2992 };
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2993
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2994 void
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2995 final_warning_record::grow_type_warnings (unsigned newlen)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2996 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2997 unsigned len = type_warnings.length ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2998 if (newlen > len)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2999 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3000 type_warnings.safe_grow_cleared (newlen);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3001 for (unsigned i = len; i < newlen; i++)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3002 type_warnings[i].dyn_count = profile_count::zero ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3003 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3004 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3005
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3006 class final_warning_record *final_warning_records;
111
kono
parents:
diff changeset
3007
kono
parents:
diff changeset
3008 /* Return vector containing possible targets of polymorphic call of type
kono
parents:
diff changeset
3009 OTR_TYPE calling method OTR_TOKEN within type of OTR_OUTER_TYPE and OFFSET.
kono
parents:
diff changeset
3010 If INCLUDE_BASES is true, walk also base types of OUTER_TYPES containing
kono
parents:
diff changeset
3011 OTR_TYPE and include their virtual method. This is useful for types
kono
parents:
diff changeset
3012 possibly in construction or destruction where the virtual table may
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3013 temporarily change to one of base types. INCLUDE_DERIVED_TYPES make
111
kono
parents:
diff changeset
3014 us to walk the inheritance graph for all derivations.
kono
parents:
diff changeset
3015
kono
parents:
diff changeset
3016 If COMPLETEP is non-NULL, store true if the list is complete.
kono
parents:
diff changeset
3017 CACHE_TOKEN (if non-NULL) will get stored to an unique ID of entry
kono
parents:
diff changeset
3018 in the target cache. If user needs to visit every target list
kono
parents:
diff changeset
3019 just once, it can memoize them.
kono
parents:
diff changeset
3020
kono
parents:
diff changeset
3021 If SPECULATIVE is set, the list will not contain targets that
kono
parents:
diff changeset
3022 are not speculatively taken.
kono
parents:
diff changeset
3023
kono
parents:
diff changeset
3024 Returned vector is placed into cache. It is NOT caller's responsibility
kono
parents:
diff changeset
3025 to free it. The vector can be freed on cgraph_remove_node call if
kono
parents:
diff changeset
3026 the particular node is a virtual function present in the cache. */
kono
parents:
diff changeset
3027
kono
parents:
diff changeset
3028 vec <cgraph_node *>
kono
parents:
diff changeset
3029 possible_polymorphic_call_targets (tree otr_type,
kono
parents:
diff changeset
3030 HOST_WIDE_INT otr_token,
kono
parents:
diff changeset
3031 ipa_polymorphic_call_context context,
kono
parents:
diff changeset
3032 bool *completep,
kono
parents:
diff changeset
3033 void **cache_token,
kono
parents:
diff changeset
3034 bool speculative)
kono
parents:
diff changeset
3035 {
kono
parents:
diff changeset
3036 static struct cgraph_node_hook_list *node_removal_hook_holder;
kono
parents:
diff changeset
3037 vec <cgraph_node *> nodes = vNULL;
kono
parents:
diff changeset
3038 auto_vec <tree, 8> bases_to_consider;
kono
parents:
diff changeset
3039 odr_type type, outer_type;
kono
parents:
diff changeset
3040 polymorphic_call_target_d key;
kono
parents:
diff changeset
3041 polymorphic_call_target_d **slot;
kono
parents:
diff changeset
3042 unsigned int i;
kono
parents:
diff changeset
3043 tree binfo, target;
kono
parents:
diff changeset
3044 bool complete;
kono
parents:
diff changeset
3045 bool can_refer = false;
kono
parents:
diff changeset
3046 bool skipped = false;
kono
parents:
diff changeset
3047
kono
parents:
diff changeset
3048 otr_type = TYPE_MAIN_VARIANT (otr_type);
kono
parents:
diff changeset
3049
kono
parents:
diff changeset
3050 /* If ODR is not initialized or the context is invalid, return empty
kono
parents:
diff changeset
3051 incomplete list. */
kono
parents:
diff changeset
3052 if (!odr_hash || context.invalid || !TYPE_BINFO (otr_type))
kono
parents:
diff changeset
3053 {
kono
parents:
diff changeset
3054 if (completep)
kono
parents:
diff changeset
3055 *completep = context.invalid;
kono
parents:
diff changeset
3056 if (cache_token)
kono
parents:
diff changeset
3057 *cache_token = NULL;
kono
parents:
diff changeset
3058 return nodes;
kono
parents:
diff changeset
3059 }
kono
parents:
diff changeset
3060
kono
parents:
diff changeset
3061 /* Do not bother to compute speculative info when user do not asks for it. */
kono
parents:
diff changeset
3062 if (!speculative || !context.speculative_outer_type)
kono
parents:
diff changeset
3063 context.clear_speculation ();
kono
parents:
diff changeset
3064
kono
parents:
diff changeset
3065 type = get_odr_type (otr_type, true);
kono
parents:
diff changeset
3066
kono
parents:
diff changeset
3067 /* Recording type variants would waste results cache. */
kono
parents:
diff changeset
3068 gcc_assert (!context.outer_type
kono
parents:
diff changeset
3069 || TYPE_MAIN_VARIANT (context.outer_type) == context.outer_type);
kono
parents:
diff changeset
3070
kono
parents:
diff changeset
3071 /* Look up the outer class type we want to walk.
kono
parents:
diff changeset
3072 If we fail to do so, the context is invalid. */
kono
parents:
diff changeset
3073 if ((context.outer_type || context.speculative_outer_type)
kono
parents:
diff changeset
3074 && !context.restrict_to_inner_class (otr_type))
kono
parents:
diff changeset
3075 {
kono
parents:
diff changeset
3076 if (completep)
kono
parents:
diff changeset
3077 *completep = true;
kono
parents:
diff changeset
3078 if (cache_token)
kono
parents:
diff changeset
3079 *cache_token = NULL;
kono
parents:
diff changeset
3080 return nodes;
kono
parents:
diff changeset
3081 }
kono
parents:
diff changeset
3082 gcc_assert (!context.invalid);
kono
parents:
diff changeset
3083
kono
parents:
diff changeset
3084 /* Check that restrict_to_inner_class kept the main variant. */
kono
parents:
diff changeset
3085 gcc_assert (!context.outer_type
kono
parents:
diff changeset
3086 || TYPE_MAIN_VARIANT (context.outer_type) == context.outer_type);
kono
parents:
diff changeset
3087
kono
parents:
diff changeset
3088 /* We canonicalize our query, so we do not need extra hashtable entries. */
kono
parents:
diff changeset
3089
kono
parents:
diff changeset
3090 /* Without outer type, we have no use for offset. Just do the
kono
parents:
diff changeset
3091 basic search from inner type. */
kono
parents:
diff changeset
3092 if (!context.outer_type)
kono
parents:
diff changeset
3093 context.clear_outer_type (otr_type);
kono
parents:
diff changeset
3094 /* We need to update our hierarchy if the type does not exist. */
kono
parents:
diff changeset
3095 outer_type = get_odr_type (context.outer_type, true);
kono
parents:
diff changeset
3096 /* If the type is complete, there are no derivations. */
kono
parents:
diff changeset
3097 if (TYPE_FINAL_P (outer_type->type))
kono
parents:
diff changeset
3098 context.maybe_derived_type = false;
kono
parents:
diff changeset
3099
kono
parents:
diff changeset
3100 /* Initialize query cache. */
kono
parents:
diff changeset
3101 if (!cached_polymorphic_call_targets)
kono
parents:
diff changeset
3102 {
kono
parents:
diff changeset
3103 cached_polymorphic_call_targets = new hash_set<cgraph_node *>;
kono
parents:
diff changeset
3104 polymorphic_call_target_hash
kono
parents:
diff changeset
3105 = new polymorphic_call_target_hash_type (23);
kono
parents:
diff changeset
3106 if (!node_removal_hook_holder)
kono
parents:
diff changeset
3107 {
kono
parents:
diff changeset
3108 node_removal_hook_holder =
kono
parents:
diff changeset
3109 symtab->add_cgraph_removal_hook (&devirt_node_removal_hook, NULL);
kono
parents:
diff changeset
3110 symtab->add_varpool_removal_hook (&devirt_variable_node_removal_hook,
kono
parents:
diff changeset
3111 NULL);
kono
parents:
diff changeset
3112 }
kono
parents:
diff changeset
3113 }
kono
parents:
diff changeset
3114
kono
parents:
diff changeset
3115 if (in_lto_p)
kono
parents:
diff changeset
3116 {
kono
parents:
diff changeset
3117 if (context.outer_type != otr_type)
kono
parents:
diff changeset
3118 context.outer_type
kono
parents:
diff changeset
3119 = get_odr_type (context.outer_type, true)->type;
kono
parents:
diff changeset
3120 if (context.speculative_outer_type)
kono
parents:
diff changeset
3121 context.speculative_outer_type
kono
parents:
diff changeset
3122 = get_odr_type (context.speculative_outer_type, true)->type;
kono
parents:
diff changeset
3123 }
kono
parents:
diff changeset
3124
kono
parents:
diff changeset
3125 /* Look up cached answer. */
kono
parents:
diff changeset
3126 key.type = type;
kono
parents:
diff changeset
3127 key.otr_token = otr_token;
kono
parents:
diff changeset
3128 key.speculative = speculative;
kono
parents:
diff changeset
3129 key.context = context;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3130 key.n_odr_types = odr_types.length ();
111
kono
parents:
diff changeset
3131 slot = polymorphic_call_target_hash->find_slot (&key, INSERT);
kono
parents:
diff changeset
3132 if (cache_token)
kono
parents:
diff changeset
3133 *cache_token = (void *)*slot;
kono
parents:
diff changeset
3134 if (*slot)
kono
parents:
diff changeset
3135 {
kono
parents:
diff changeset
3136 if (completep)
kono
parents:
diff changeset
3137 *completep = (*slot)->complete;
kono
parents:
diff changeset
3138 if ((*slot)->type_warning && final_warning_records)
kono
parents:
diff changeset
3139 {
kono
parents:
diff changeset
3140 final_warning_records->type_warnings[(*slot)->type_warning - 1].count++;
kono
parents:
diff changeset
3141 if (!final_warning_records->type_warnings
kono
parents:
diff changeset
3142 [(*slot)->type_warning - 1].dyn_count.initialized_p ())
kono
parents:
diff changeset
3143 final_warning_records->type_warnings
kono
parents:
diff changeset
3144 [(*slot)->type_warning - 1].dyn_count = profile_count::zero ();
kono
parents:
diff changeset
3145 if (final_warning_records->dyn_count > 0)
kono
parents:
diff changeset
3146 final_warning_records->type_warnings[(*slot)->type_warning - 1].dyn_count
kono
parents:
diff changeset
3147 = final_warning_records->type_warnings[(*slot)->type_warning - 1].dyn_count
kono
parents:
diff changeset
3148 + final_warning_records->dyn_count;
kono
parents:
diff changeset
3149 }
kono
parents:
diff changeset
3150 if (!speculative && (*slot)->decl_warning && final_warning_records)
kono
parents:
diff changeset
3151 {
kono
parents:
diff changeset
3152 struct decl_warn_count *c =
kono
parents:
diff changeset
3153 final_warning_records->decl_warnings.get ((*slot)->decl_warning);
kono
parents:
diff changeset
3154 c->count++;
kono
parents:
diff changeset
3155 if (final_warning_records->dyn_count > 0)
kono
parents:
diff changeset
3156 c->dyn_count += final_warning_records->dyn_count;
kono
parents:
diff changeset
3157 }
kono
parents:
diff changeset
3158 return (*slot)->targets;
kono
parents:
diff changeset
3159 }
kono
parents:
diff changeset
3160
kono
parents:
diff changeset
3161 complete = true;
kono
parents:
diff changeset
3162
kono
parents:
diff changeset
3163 /* Do actual search. */
kono
parents:
diff changeset
3164 timevar_push (TV_IPA_VIRTUAL_CALL);
kono
parents:
diff changeset
3165 *slot = XCNEW (polymorphic_call_target_d);
kono
parents:
diff changeset
3166 if (cache_token)
kono
parents:
diff changeset
3167 *cache_token = (void *)*slot;
kono
parents:
diff changeset
3168 (*slot)->type = type;
kono
parents:
diff changeset
3169 (*slot)->otr_token = otr_token;
kono
parents:
diff changeset
3170 (*slot)->context = context;
kono
parents:
diff changeset
3171 (*slot)->speculative = speculative;
kono
parents:
diff changeset
3172
kono
parents:
diff changeset
3173 hash_set<tree> inserted;
kono
parents:
diff changeset
3174 hash_set<tree> matched_vtables;
kono
parents:
diff changeset
3175
kono
parents:
diff changeset
3176 /* First insert targets we speculatively identified as likely. */
kono
parents:
diff changeset
3177 if (context.speculative_outer_type)
kono
parents:
diff changeset
3178 {
kono
parents:
diff changeset
3179 odr_type speculative_outer_type;
kono
parents:
diff changeset
3180 bool speculation_complete = true;
kono
parents:
diff changeset
3181
kono
parents:
diff changeset
3182 /* First insert target from type itself and check if it may have
kono
parents:
diff changeset
3183 derived types. */
kono
parents:
diff changeset
3184 speculative_outer_type = get_odr_type (context.speculative_outer_type, true);
kono
parents:
diff changeset
3185 if (TYPE_FINAL_P (speculative_outer_type->type))
kono
parents:
diff changeset
3186 context.speculative_maybe_derived_type = false;
kono
parents:
diff changeset
3187 binfo = get_binfo_at_offset (TYPE_BINFO (speculative_outer_type->type),
kono
parents:
diff changeset
3188 context.speculative_offset, otr_type);
kono
parents:
diff changeset
3189 if (binfo)
kono
parents:
diff changeset
3190 target = gimple_get_virt_method_for_binfo (otr_token, binfo,
kono
parents:
diff changeset
3191 &can_refer);
kono
parents:
diff changeset
3192 else
kono
parents:
diff changeset
3193 target = NULL;
kono
parents:
diff changeset
3194
kono
parents:
diff changeset
3195 /* In the case we get complete method, we don't need
kono
parents:
diff changeset
3196 to walk derivations. */
kono
parents:
diff changeset
3197 if (target && DECL_FINAL_P (target))
kono
parents:
diff changeset
3198 context.speculative_maybe_derived_type = false;
kono
parents:
diff changeset
3199 if (type_possibly_instantiated_p (speculative_outer_type->type))
kono
parents:
diff changeset
3200 maybe_record_node (nodes, target, &inserted, can_refer, &speculation_complete);
kono
parents:
diff changeset
3201 if (binfo)
kono
parents:
diff changeset
3202 matched_vtables.add (BINFO_VTABLE (binfo));
kono
parents:
diff changeset
3203
kono
parents:
diff changeset
3204
kono
parents:
diff changeset
3205 /* Next walk recursively all derived types. */
kono
parents:
diff changeset
3206 if (context.speculative_maybe_derived_type)
kono
parents:
diff changeset
3207 for (i = 0; i < speculative_outer_type->derived_types.length(); i++)
kono
parents:
diff changeset
3208 possible_polymorphic_call_targets_1 (nodes, &inserted,
kono
parents:
diff changeset
3209 &matched_vtables,
kono
parents:
diff changeset
3210 otr_type,
kono
parents:
diff changeset
3211 speculative_outer_type->derived_types[i],
kono
parents:
diff changeset
3212 otr_token, speculative_outer_type->type,
kono
parents:
diff changeset
3213 context.speculative_offset,
kono
parents:
diff changeset
3214 &speculation_complete,
kono
parents:
diff changeset
3215 bases_to_consider,
kono
parents:
diff changeset
3216 false);
kono
parents:
diff changeset
3217 }
kono
parents:
diff changeset
3218
kono
parents:
diff changeset
3219 if (!speculative || !nodes.length ())
kono
parents:
diff changeset
3220 {
kono
parents:
diff changeset
3221 /* First see virtual method of type itself. */
kono
parents:
diff changeset
3222 binfo = get_binfo_at_offset (TYPE_BINFO (outer_type->type),
kono
parents:
diff changeset
3223 context.offset, otr_type);
kono
parents:
diff changeset
3224 if (binfo)
kono
parents:
diff changeset
3225 target = gimple_get_virt_method_for_binfo (otr_token, binfo,
kono
parents:
diff changeset
3226 &can_refer);
kono
parents:
diff changeset
3227 else
kono
parents:
diff changeset
3228 {
kono
parents:
diff changeset
3229 gcc_assert (odr_violation_reported);
kono
parents:
diff changeset
3230 target = NULL;
kono
parents:
diff changeset
3231 }
kono
parents:
diff changeset
3232
kono
parents:
diff changeset
3233 /* Destructors are never called through construction virtual tables,
kono
parents:
diff changeset
3234 because the type is always known. */
kono
parents:
diff changeset
3235 if (target && DECL_CXX_DESTRUCTOR_P (target))
kono
parents:
diff changeset
3236 context.maybe_in_construction = false;
kono
parents:
diff changeset
3237
kono
parents:
diff changeset
3238 if (target)
kono
parents:
diff changeset
3239 {
kono
parents:
diff changeset
3240 /* In the case we get complete method, we don't need
kono
parents:
diff changeset
3241 to walk derivations. */
kono
parents:
diff changeset
3242 if (DECL_FINAL_P (target))
kono
parents:
diff changeset
3243 context.maybe_derived_type = false;
kono
parents:
diff changeset
3244 }
kono
parents:
diff changeset
3245
kono
parents:
diff changeset
3246 /* If OUTER_TYPE is abstract, we know we are not seeing its instance. */
kono
parents:
diff changeset
3247 if (type_possibly_instantiated_p (outer_type->type))
kono
parents:
diff changeset
3248 maybe_record_node (nodes, target, &inserted, can_refer, &complete);
kono
parents:
diff changeset
3249 else
kono
parents:
diff changeset
3250 skipped = true;
kono
parents:
diff changeset
3251
kono
parents:
diff changeset
3252 if (binfo)
kono
parents:
diff changeset
3253 matched_vtables.add (BINFO_VTABLE (binfo));
kono
parents:
diff changeset
3254
kono
parents:
diff changeset
3255 /* Next walk recursively all derived types. */
kono
parents:
diff changeset
3256 if (context.maybe_derived_type)
kono
parents:
diff changeset
3257 {
kono
parents:
diff changeset
3258 for (i = 0; i < outer_type->derived_types.length(); i++)
kono
parents:
diff changeset
3259 possible_polymorphic_call_targets_1 (nodes, &inserted,
kono
parents:
diff changeset
3260 &matched_vtables,
kono
parents:
diff changeset
3261 otr_type,
kono
parents:
diff changeset
3262 outer_type->derived_types[i],
kono
parents:
diff changeset
3263 otr_token, outer_type->type,
kono
parents:
diff changeset
3264 context.offset, &complete,
kono
parents:
diff changeset
3265 bases_to_consider,
kono
parents:
diff changeset
3266 context.maybe_in_construction);
kono
parents:
diff changeset
3267
kono
parents:
diff changeset
3268 if (!outer_type->all_derivations_known)
kono
parents:
diff changeset
3269 {
kono
parents:
diff changeset
3270 if (!speculative && final_warning_records
kono
parents:
diff changeset
3271 && nodes.length () == 1
kono
parents:
diff changeset
3272 && TREE_CODE (TREE_TYPE (nodes[0]->decl)) == METHOD_TYPE)
kono
parents:
diff changeset
3273 {
kono
parents:
diff changeset
3274 if (complete
kono
parents:
diff changeset
3275 && warn_suggest_final_types
kono
parents:
diff changeset
3276 && !outer_type->derived_types.length ())
kono
parents:
diff changeset
3277 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3278 final_warning_records->grow_type_warnings
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3279 (outer_type->id);
111
kono
parents:
diff changeset
3280 final_warning_records->type_warnings[outer_type->id].count++;
kono
parents:
diff changeset
3281 if (!final_warning_records->type_warnings
kono
parents:
diff changeset
3282 [outer_type->id].dyn_count.initialized_p ())
kono
parents:
diff changeset
3283 final_warning_records->type_warnings
kono
parents:
diff changeset
3284 [outer_type->id].dyn_count = profile_count::zero ();
kono
parents:
diff changeset
3285 final_warning_records->type_warnings[outer_type->id].dyn_count
kono
parents:
diff changeset
3286 += final_warning_records->dyn_count;
kono
parents:
diff changeset
3287 final_warning_records->type_warnings[outer_type->id].type
kono
parents:
diff changeset
3288 = outer_type->type;
kono
parents:
diff changeset
3289 (*slot)->type_warning = outer_type->id + 1;
kono
parents:
diff changeset
3290 }
kono
parents:
diff changeset
3291 if (complete
kono
parents:
diff changeset
3292 && warn_suggest_final_methods
kono
parents:
diff changeset
3293 && types_same_for_odr (DECL_CONTEXT (nodes[0]->decl),
kono
parents:
diff changeset
3294 outer_type->type))
kono
parents:
diff changeset
3295 {
kono
parents:
diff changeset
3296 bool existed;
kono
parents:
diff changeset
3297 struct decl_warn_count &c =
kono
parents:
diff changeset
3298 final_warning_records->decl_warnings.get_or_insert
kono
parents:
diff changeset
3299 (nodes[0]->decl, &existed);
kono
parents:
diff changeset
3300
kono
parents:
diff changeset
3301 if (existed)
kono
parents:
diff changeset
3302 {
kono
parents:
diff changeset
3303 c.count++;
kono
parents:
diff changeset
3304 c.dyn_count += final_warning_records->dyn_count;
kono
parents:
diff changeset
3305 }
kono
parents:
diff changeset
3306 else
kono
parents:
diff changeset
3307 {
kono
parents:
diff changeset
3308 c.count = 1;
kono
parents:
diff changeset
3309 c.dyn_count = final_warning_records->dyn_count;
kono
parents:
diff changeset
3310 c.decl = nodes[0]->decl;
kono
parents:
diff changeset
3311 }
kono
parents:
diff changeset
3312 (*slot)->decl_warning = nodes[0]->decl;
kono
parents:
diff changeset
3313 }
kono
parents:
diff changeset
3314 }
kono
parents:
diff changeset
3315 complete = false;
kono
parents:
diff changeset
3316 }
kono
parents:
diff changeset
3317 }
kono
parents:
diff changeset
3318
kono
parents:
diff changeset
3319 if (!speculative)
kono
parents:
diff changeset
3320 {
kono
parents:
diff changeset
3321 /* Destructors are never called through construction virtual tables,
kono
parents:
diff changeset
3322 because the type is always known. One of entries may be
kono
parents:
diff changeset
3323 cxa_pure_virtual so look to at least two of them. */
kono
parents:
diff changeset
3324 if (context.maybe_in_construction)
kono
parents:
diff changeset
3325 for (i =0 ; i < MIN (nodes.length (), 2); i++)
kono
parents:
diff changeset
3326 if (DECL_CXX_DESTRUCTOR_P (nodes[i]->decl))
kono
parents:
diff changeset
3327 context.maybe_in_construction = false;
kono
parents:
diff changeset
3328 if (context.maybe_in_construction)
kono
parents:
diff changeset
3329 {
kono
parents:
diff changeset
3330 if (type != outer_type
kono
parents:
diff changeset
3331 && (!skipped
kono
parents:
diff changeset
3332 || (context.maybe_derived_type
kono
parents:
diff changeset
3333 && !type_all_derivations_known_p (outer_type->type))))
kono
parents:
diff changeset
3334 record_targets_from_bases (otr_type, otr_token, outer_type->type,
kono
parents:
diff changeset
3335 context.offset, nodes, &inserted,
kono
parents:
diff changeset
3336 &matched_vtables, &complete);
kono
parents:
diff changeset
3337 if (skipped)
kono
parents:
diff changeset
3338 maybe_record_node (nodes, target, &inserted, can_refer, &complete);
kono
parents:
diff changeset
3339 for (i = 0; i < bases_to_consider.length(); i++)
kono
parents:
diff changeset
3340 maybe_record_node (nodes, bases_to_consider[i], &inserted, can_refer, &complete);
kono
parents:
diff changeset
3341 }
kono
parents:
diff changeset
3342 }
kono
parents:
diff changeset
3343 }
kono
parents:
diff changeset
3344
kono
parents:
diff changeset
3345 (*slot)->targets = nodes;
kono
parents:
diff changeset
3346 (*slot)->complete = complete;
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3347 (*slot)->n_odr_types = odr_types.length ();
111
kono
parents:
diff changeset
3348 if (completep)
kono
parents:
diff changeset
3349 *completep = complete;
kono
parents:
diff changeset
3350
kono
parents:
diff changeset
3351 timevar_pop (TV_IPA_VIRTUAL_CALL);
kono
parents:
diff changeset
3352 return nodes;
kono
parents:
diff changeset
3353 }
kono
parents:
diff changeset
3354
kono
parents:
diff changeset
3355 bool
kono
parents:
diff changeset
3356 add_decl_warning (const tree &key ATTRIBUTE_UNUSED, const decl_warn_count &value,
kono
parents:
diff changeset
3357 vec<const decl_warn_count*> *vec)
kono
parents:
diff changeset
3358 {
kono
parents:
diff changeset
3359 vec->safe_push (&value);
kono
parents:
diff changeset
3360 return true;
kono
parents:
diff changeset
3361 }
kono
parents:
diff changeset
3362
kono
parents:
diff changeset
3363 /* Dump target list TARGETS into FILE. */
kono
parents:
diff changeset
3364
kono
parents:
diff changeset
3365 static void
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3366 dump_targets (FILE *f, vec <cgraph_node *> targets, bool verbose)
111
kono
parents:
diff changeset
3367 {
kono
parents:
diff changeset
3368 unsigned int i;
kono
parents:
diff changeset
3369
kono
parents:
diff changeset
3370 for (i = 0; i < targets.length (); i++)
kono
parents:
diff changeset
3371 {
kono
parents:
diff changeset
3372 char *name = NULL;
kono
parents:
diff changeset
3373 if (in_lto_p)
kono
parents:
diff changeset
3374 name = cplus_demangle_v3 (targets[i]->asm_name (), 0);
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3375 fprintf (f, " %s", name ? name : targets[i]->dump_name ());
111
kono
parents:
diff changeset
3376 if (in_lto_p)
kono
parents:
diff changeset
3377 free (name);
kono
parents:
diff changeset
3378 if (!targets[i]->definition)
kono
parents:
diff changeset
3379 fprintf (f, " (no definition%s)",
kono
parents:
diff changeset
3380 DECL_DECLARED_INLINE_P (targets[i]->decl)
kono
parents:
diff changeset
3381 ? " inline" : "");
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3382 /* With many targets for every call polymorphic dumps are going to
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3383 be quadratic in size. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3384 if (i > 10 && !verbose)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3385 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3386 fprintf (f, " ... and %i more targets\n", targets.length () - i);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3387 return;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3388 }
111
kono
parents:
diff changeset
3389 }
kono
parents:
diff changeset
3390 fprintf (f, "\n");
kono
parents:
diff changeset
3391 }
kono
parents:
diff changeset
3392
kono
parents:
diff changeset
3393 /* Dump all possible targets of a polymorphic call. */
kono
parents:
diff changeset
3394
kono
parents:
diff changeset
3395 void
kono
parents:
diff changeset
3396 dump_possible_polymorphic_call_targets (FILE *f,
kono
parents:
diff changeset
3397 tree otr_type,
kono
parents:
diff changeset
3398 HOST_WIDE_INT otr_token,
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3399 const ipa_polymorphic_call_context &ctx,
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3400 bool verbose)
111
kono
parents:
diff changeset
3401 {
kono
parents:
diff changeset
3402 vec <cgraph_node *> targets;
kono
parents:
diff changeset
3403 bool final;
kono
parents:
diff changeset
3404 odr_type type = get_odr_type (TYPE_MAIN_VARIANT (otr_type), false);
kono
parents:
diff changeset
3405 unsigned int len;
kono
parents:
diff changeset
3406
kono
parents:
diff changeset
3407 if (!type)
kono
parents:
diff changeset
3408 return;
kono
parents:
diff changeset
3409 targets = possible_polymorphic_call_targets (otr_type, otr_token,
kono
parents:
diff changeset
3410 ctx,
kono
parents:
diff changeset
3411 &final, NULL, false);
kono
parents:
diff changeset
3412 fprintf (f, " Targets of polymorphic call of type %i:", type->id);
kono
parents:
diff changeset
3413 print_generic_expr (f, type->type, TDF_SLIM);
kono
parents:
diff changeset
3414 fprintf (f, " token %i\n", (int)otr_token);
kono
parents:
diff changeset
3415
kono
parents:
diff changeset
3416 ctx.dump (f);
kono
parents:
diff changeset
3417
kono
parents:
diff changeset
3418 fprintf (f, " %s%s%s%s\n ",
kono
parents:
diff changeset
3419 final ? "This is a complete list." :
kono
parents:
diff changeset
3420 "This is partial list; extra targets may be defined in other units.",
kono
parents:
diff changeset
3421 ctx.maybe_in_construction ? " (base types included)" : "",
kono
parents:
diff changeset
3422 ctx.maybe_derived_type ? " (derived types included)" : "",
kono
parents:
diff changeset
3423 ctx.speculative_maybe_derived_type ? " (speculative derived types included)" : "");
kono
parents:
diff changeset
3424 len = targets.length ();
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3425 dump_targets (f, targets, verbose);
111
kono
parents:
diff changeset
3426
kono
parents:
diff changeset
3427 targets = possible_polymorphic_call_targets (otr_type, otr_token,
kono
parents:
diff changeset
3428 ctx,
kono
parents:
diff changeset
3429 &final, NULL, true);
kono
parents:
diff changeset
3430 if (targets.length () != len)
kono
parents:
diff changeset
3431 {
kono
parents:
diff changeset
3432 fprintf (f, " Speculative targets:");
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3433 dump_targets (f, targets, verbose);
111
kono
parents:
diff changeset
3434 }
kono
parents:
diff changeset
3435 /* Ugly: during callgraph construction the target cache may get populated
kono
parents:
diff changeset
3436 before all targets are found. While this is harmless (because all local
kono
parents:
diff changeset
3437 types are discovered and only in those case we devirtualize fully and we
kono
parents:
diff changeset
3438 don't do speculative devirtualization before IPA stage) it triggers
kono
parents:
diff changeset
3439 assert here when dumping at that stage also populates the case with
kono
parents:
diff changeset
3440 speculative targets. Quietly ignore this. */
kono
parents:
diff changeset
3441 gcc_assert (symtab->state < IPA_SSA || targets.length () <= len);
kono
parents:
diff changeset
3442 fprintf (f, "\n");
kono
parents:
diff changeset
3443 }
kono
parents:
diff changeset
3444
kono
parents:
diff changeset
3445
kono
parents:
diff changeset
3446 /* Return true if N can be possibly target of a polymorphic call of
kono
parents:
diff changeset
3447 OTR_TYPE/OTR_TOKEN. */
kono
parents:
diff changeset
3448
kono
parents:
diff changeset
3449 bool
kono
parents:
diff changeset
3450 possible_polymorphic_call_target_p (tree otr_type,
kono
parents:
diff changeset
3451 HOST_WIDE_INT otr_token,
kono
parents:
diff changeset
3452 const ipa_polymorphic_call_context &ctx,
kono
parents:
diff changeset
3453 struct cgraph_node *n)
kono
parents:
diff changeset
3454 {
kono
parents:
diff changeset
3455 vec <cgraph_node *> targets;
kono
parents:
diff changeset
3456 unsigned int i;
kono
parents:
diff changeset
3457 bool final;
kono
parents:
diff changeset
3458
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3459 if (fndecl_built_in_p (n->decl, BUILT_IN_UNREACHABLE)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3460 || fndecl_built_in_p (n->decl, BUILT_IN_TRAP))
111
kono
parents:
diff changeset
3461 return true;
kono
parents:
diff changeset
3462
kono
parents:
diff changeset
3463 if (is_cxa_pure_virtual_p (n->decl))
kono
parents:
diff changeset
3464 return true;
kono
parents:
diff changeset
3465
kono
parents:
diff changeset
3466 if (!odr_hash)
kono
parents:
diff changeset
3467 return true;
kono
parents:
diff changeset
3468 targets = possible_polymorphic_call_targets (otr_type, otr_token, ctx, &final);
kono
parents:
diff changeset
3469 for (i = 0; i < targets.length (); i++)
kono
parents:
diff changeset
3470 if (n->semantically_equivalent_p (targets[i]))
kono
parents:
diff changeset
3471 return true;
kono
parents:
diff changeset
3472
kono
parents:
diff changeset
3473 /* At a moment we allow middle end to dig out new external declarations
kono
parents:
diff changeset
3474 as a targets of polymorphic calls. */
kono
parents:
diff changeset
3475 if (!final && !n->definition)
kono
parents:
diff changeset
3476 return true;
kono
parents:
diff changeset
3477 return false;
kono
parents:
diff changeset
3478 }
kono
parents:
diff changeset
3479
kono
parents:
diff changeset
3480
kono
parents:
diff changeset
3481
kono
parents:
diff changeset
3482 /* Return true if N can be possibly target of a polymorphic call of
kono
parents:
diff changeset
3483 OBJ_TYPE_REF expression REF in STMT. */
kono
parents:
diff changeset
3484
kono
parents:
diff changeset
3485 bool
kono
parents:
diff changeset
3486 possible_polymorphic_call_target_p (tree ref,
kono
parents:
diff changeset
3487 gimple *stmt,
kono
parents:
diff changeset
3488 struct cgraph_node *n)
kono
parents:
diff changeset
3489 {
kono
parents:
diff changeset
3490 ipa_polymorphic_call_context context (current_function_decl, ref, stmt);
kono
parents:
diff changeset
3491 tree call_fn = gimple_call_fn (stmt);
kono
parents:
diff changeset
3492
kono
parents:
diff changeset
3493 return possible_polymorphic_call_target_p (obj_type_ref_class (call_fn),
kono
parents:
diff changeset
3494 tree_to_uhwi
kono
parents:
diff changeset
3495 (OBJ_TYPE_REF_TOKEN (call_fn)),
kono
parents:
diff changeset
3496 context,
kono
parents:
diff changeset
3497 n);
kono
parents:
diff changeset
3498 }
kono
parents:
diff changeset
3499
kono
parents:
diff changeset
3500
kono
parents:
diff changeset
3501 /* After callgraph construction new external nodes may appear.
kono
parents:
diff changeset
3502 Add them into the graph. */
kono
parents:
diff changeset
3503
kono
parents:
diff changeset
3504 void
kono
parents:
diff changeset
3505 update_type_inheritance_graph (void)
kono
parents:
diff changeset
3506 {
kono
parents:
diff changeset
3507 struct cgraph_node *n;
kono
parents:
diff changeset
3508
kono
parents:
diff changeset
3509 if (!odr_hash)
kono
parents:
diff changeset
3510 return;
kono
parents:
diff changeset
3511 free_polymorphic_call_targets_hash ();
kono
parents:
diff changeset
3512 timevar_push (TV_IPA_INHERITANCE);
kono
parents:
diff changeset
3513 /* We reconstruct the graph starting from types of all methods seen in the
kono
parents:
diff changeset
3514 unit. */
kono
parents:
diff changeset
3515 FOR_EACH_FUNCTION (n)
kono
parents:
diff changeset
3516 if (DECL_VIRTUAL_P (n->decl)
kono
parents:
diff changeset
3517 && !n->definition
kono
parents:
diff changeset
3518 && n->real_symbol_p ())
kono
parents:
diff changeset
3519 get_odr_type (TYPE_METHOD_BASETYPE (TREE_TYPE (n->decl)), true);
kono
parents:
diff changeset
3520 timevar_pop (TV_IPA_INHERITANCE);
kono
parents:
diff changeset
3521 }
kono
parents:
diff changeset
3522
kono
parents:
diff changeset
3523
kono
parents:
diff changeset
3524 /* Return true if N looks like likely target of a polymorphic call.
kono
parents:
diff changeset
3525 Rule out cxa_pure_virtual, noreturns, function declared cold and
kono
parents:
diff changeset
3526 other obvious cases. */
kono
parents:
diff changeset
3527
kono
parents:
diff changeset
3528 bool
kono
parents:
diff changeset
3529 likely_target_p (struct cgraph_node *n)
kono
parents:
diff changeset
3530 {
kono
parents:
diff changeset
3531 int flags;
kono
parents:
diff changeset
3532 /* cxa_pure_virtual and similar things are not likely. */
kono
parents:
diff changeset
3533 if (TREE_CODE (TREE_TYPE (n->decl)) != METHOD_TYPE)
kono
parents:
diff changeset
3534 return false;
kono
parents:
diff changeset
3535 flags = flags_from_decl_or_type (n->decl);
kono
parents:
diff changeset
3536 if (flags & ECF_NORETURN)
kono
parents:
diff changeset
3537 return false;
kono
parents:
diff changeset
3538 if (lookup_attribute ("cold",
kono
parents:
diff changeset
3539 DECL_ATTRIBUTES (n->decl)))
kono
parents:
diff changeset
3540 return false;
kono
parents:
diff changeset
3541 if (n->frequency < NODE_FREQUENCY_NORMAL)
kono
parents:
diff changeset
3542 return false;
kono
parents:
diff changeset
3543 /* If there are no live virtual tables referring the target,
kono
parents:
diff changeset
3544 the only way the target can be called is an instance coming from other
kono
parents:
diff changeset
3545 compilation unit; speculative devirtualization is built around an
kono
parents:
diff changeset
3546 assumption that won't happen. */
kono
parents:
diff changeset
3547 if (!referenced_from_vtable_p (n))
kono
parents:
diff changeset
3548 return false;
kono
parents:
diff changeset
3549 return true;
kono
parents:
diff changeset
3550 }
kono
parents:
diff changeset
3551
kono
parents:
diff changeset
3552 /* Compare type warning records P1 and P2 and choose one with larger count;
kono
parents:
diff changeset
3553 helper for qsort. */
kono
parents:
diff changeset
3554
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3555 static int
111
kono
parents:
diff changeset
3556 type_warning_cmp (const void *p1, const void *p2)
kono
parents:
diff changeset
3557 {
kono
parents:
diff changeset
3558 const odr_type_warn_count *t1 = (const odr_type_warn_count *)p1;
kono
parents:
diff changeset
3559 const odr_type_warn_count *t2 = (const odr_type_warn_count *)p2;
kono
parents:
diff changeset
3560
kono
parents:
diff changeset
3561 if (t1->dyn_count < t2->dyn_count)
kono
parents:
diff changeset
3562 return 1;
kono
parents:
diff changeset
3563 if (t1->dyn_count > t2->dyn_count)
kono
parents:
diff changeset
3564 return -1;
kono
parents:
diff changeset
3565 return t2->count - t1->count;
kono
parents:
diff changeset
3566 }
kono
parents:
diff changeset
3567
kono
parents:
diff changeset
3568 /* Compare decl warning records P1 and P2 and choose one with larger count;
kono
parents:
diff changeset
3569 helper for qsort. */
kono
parents:
diff changeset
3570
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3571 static int
111
kono
parents:
diff changeset
3572 decl_warning_cmp (const void *p1, const void *p2)
kono
parents:
diff changeset
3573 {
kono
parents:
diff changeset
3574 const decl_warn_count *t1 = *(const decl_warn_count * const *)p1;
kono
parents:
diff changeset
3575 const decl_warn_count *t2 = *(const decl_warn_count * const *)p2;
kono
parents:
diff changeset
3576
kono
parents:
diff changeset
3577 if (t1->dyn_count < t2->dyn_count)
kono
parents:
diff changeset
3578 return 1;
kono
parents:
diff changeset
3579 if (t1->dyn_count > t2->dyn_count)
kono
parents:
diff changeset
3580 return -1;
kono
parents:
diff changeset
3581 return t2->count - t1->count;
kono
parents:
diff changeset
3582 }
kono
parents:
diff changeset
3583
kono
parents:
diff changeset
3584
kono
parents:
diff changeset
3585 /* Try to speculatively devirtualize call to OTR_TYPE with OTR_TOKEN with
kono
parents:
diff changeset
3586 context CTX. */
kono
parents:
diff changeset
3587
kono
parents:
diff changeset
3588 struct cgraph_node *
kono
parents:
diff changeset
3589 try_speculative_devirtualization (tree otr_type, HOST_WIDE_INT otr_token,
kono
parents:
diff changeset
3590 ipa_polymorphic_call_context ctx)
kono
parents:
diff changeset
3591 {
kono
parents:
diff changeset
3592 vec <cgraph_node *>targets
kono
parents:
diff changeset
3593 = possible_polymorphic_call_targets
kono
parents:
diff changeset
3594 (otr_type, otr_token, ctx, NULL, NULL, true);
kono
parents:
diff changeset
3595 unsigned int i;
kono
parents:
diff changeset
3596 struct cgraph_node *likely_target = NULL;
kono
parents:
diff changeset
3597
kono
parents:
diff changeset
3598 for (i = 0; i < targets.length (); i++)
kono
parents:
diff changeset
3599 if (likely_target_p (targets[i]))
kono
parents:
diff changeset
3600 {
kono
parents:
diff changeset
3601 if (likely_target)
kono
parents:
diff changeset
3602 return NULL;
kono
parents:
diff changeset
3603 likely_target = targets[i];
kono
parents:
diff changeset
3604 }
kono
parents:
diff changeset
3605 if (!likely_target
kono
parents:
diff changeset
3606 ||!likely_target->definition
kono
parents:
diff changeset
3607 || DECL_EXTERNAL (likely_target->decl))
kono
parents:
diff changeset
3608 return NULL;
kono
parents:
diff changeset
3609
kono
parents:
diff changeset
3610 /* Don't use an implicitly-declared destructor (c++/58678). */
kono
parents:
diff changeset
3611 struct cgraph_node *non_thunk_target
kono
parents:
diff changeset
3612 = likely_target->function_symbol ();
kono
parents:
diff changeset
3613 if (DECL_ARTIFICIAL (non_thunk_target->decl))
kono
parents:
diff changeset
3614 return NULL;
kono
parents:
diff changeset
3615 if (likely_target->get_availability () <= AVAIL_INTERPOSABLE
kono
parents:
diff changeset
3616 && likely_target->can_be_discarded_p ())
kono
parents:
diff changeset
3617 return NULL;
kono
parents:
diff changeset
3618 return likely_target;
kono
parents:
diff changeset
3619 }
kono
parents:
diff changeset
3620
kono
parents:
diff changeset
3621 /* The ipa-devirt pass.
kono
parents:
diff changeset
3622 When polymorphic call has only one likely target in the unit,
kono
parents:
diff changeset
3623 turn it into a speculative call. */
kono
parents:
diff changeset
3624
kono
parents:
diff changeset
3625 static unsigned int
kono
parents:
diff changeset
3626 ipa_devirt (void)
kono
parents:
diff changeset
3627 {
kono
parents:
diff changeset
3628 struct cgraph_node *n;
kono
parents:
diff changeset
3629 hash_set<void *> bad_call_targets;
kono
parents:
diff changeset
3630 struct cgraph_edge *e;
kono
parents:
diff changeset
3631
kono
parents:
diff changeset
3632 int npolymorphic = 0, nspeculated = 0, nconverted = 0, ncold = 0;
kono
parents:
diff changeset
3633 int nmultiple = 0, noverwritable = 0, ndevirtualized = 0, nnotdefined = 0;
kono
parents:
diff changeset
3634 int nwrong = 0, nok = 0, nexternal = 0, nartificial = 0;
kono
parents:
diff changeset
3635 int ndropped = 0;
kono
parents:
diff changeset
3636
kono
parents:
diff changeset
3637 if (!odr_types_ptr)
kono
parents:
diff changeset
3638 return 0;
kono
parents:
diff changeset
3639
kono
parents:
diff changeset
3640 if (dump_file)
kono
parents:
diff changeset
3641 dump_type_inheritance_graph (dump_file);
kono
parents:
diff changeset
3642
kono
parents:
diff changeset
3643 /* We can output -Wsuggest-final-methods and -Wsuggest-final-types warnings.
kono
parents:
diff changeset
3644 This is implemented by setting up final_warning_records that are updated
kono
parents:
diff changeset
3645 by get_polymorphic_call_targets.
kono
parents:
diff changeset
3646 We need to clear cache in this case to trigger recomputation of all
kono
parents:
diff changeset
3647 entries. */
kono
parents:
diff changeset
3648 if (warn_suggest_final_methods || warn_suggest_final_types)
kono
parents:
diff changeset
3649 {
kono
parents:
diff changeset
3650 final_warning_records = new (final_warning_record);
kono
parents:
diff changeset
3651 final_warning_records->dyn_count = profile_count::zero ();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3652 final_warning_records->grow_type_warnings (odr_types.length ());
111
kono
parents:
diff changeset
3653 free_polymorphic_call_targets_hash ();
kono
parents:
diff changeset
3654 }
kono
parents:
diff changeset
3655
kono
parents:
diff changeset
3656 FOR_EACH_DEFINED_FUNCTION (n)
kono
parents:
diff changeset
3657 {
kono
parents:
diff changeset
3658 bool update = false;
kono
parents:
diff changeset
3659 if (!opt_for_fn (n->decl, flag_devirtualize))
kono
parents:
diff changeset
3660 continue;
kono
parents:
diff changeset
3661 if (dump_file && n->indirect_calls)
kono
parents:
diff changeset
3662 fprintf (dump_file, "\n\nProcesing function %s\n",
kono
parents:
diff changeset
3663 n->dump_name ());
kono
parents:
diff changeset
3664 for (e = n->indirect_calls; e; e = e->next_callee)
kono
parents:
diff changeset
3665 if (e->indirect_info->polymorphic)
kono
parents:
diff changeset
3666 {
kono
parents:
diff changeset
3667 struct cgraph_node *likely_target = NULL;
kono
parents:
diff changeset
3668 void *cache_token;
kono
parents:
diff changeset
3669 bool final;
kono
parents:
diff changeset
3670
kono
parents:
diff changeset
3671 if (final_warning_records)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3672 final_warning_records->dyn_count = e->count.ipa ();
111
kono
parents:
diff changeset
3673
kono
parents:
diff changeset
3674 vec <cgraph_node *>targets
kono
parents:
diff changeset
3675 = possible_polymorphic_call_targets
kono
parents:
diff changeset
3676 (e, &final, &cache_token, true);
kono
parents:
diff changeset
3677 unsigned int i;
kono
parents:
diff changeset
3678
kono
parents:
diff changeset
3679 /* Trigger warnings by calculating non-speculative targets. */
kono
parents:
diff changeset
3680 if (warn_suggest_final_methods || warn_suggest_final_types)
kono
parents:
diff changeset
3681 possible_polymorphic_call_targets (e);
kono
parents:
diff changeset
3682
kono
parents:
diff changeset
3683 if (dump_file)
kono
parents:
diff changeset
3684 dump_possible_polymorphic_call_targets
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3685 (dump_file, e, (dump_flags & TDF_DETAILS));
111
kono
parents:
diff changeset
3686
kono
parents:
diff changeset
3687 npolymorphic++;
kono
parents:
diff changeset
3688
kono
parents:
diff changeset
3689 /* See if the call can be devirtualized by means of ipa-prop's
kono
parents:
diff changeset
3690 polymorphic call context propagation. If not, we can just
kono
parents:
diff changeset
3691 forget about this call being polymorphic and avoid some heavy
kono
parents:
diff changeset
3692 lifting in remove_unreachable_nodes that will otherwise try to
kono
parents:
diff changeset
3693 keep all possible targets alive until inlining and in the inliner
kono
parents:
diff changeset
3694 itself.
kono
parents:
diff changeset
3695
kono
parents:
diff changeset
3696 This may need to be revisited once we add further ways to use
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3697 the may edges, but it is a reasonable thing to do right now. */
111
kono
parents:
diff changeset
3698
kono
parents:
diff changeset
3699 if ((e->indirect_info->param_index == -1
kono
parents:
diff changeset
3700 || (!opt_for_fn (n->decl, flag_devirtualize_speculatively)
kono
parents:
diff changeset
3701 && e->indirect_info->vptr_changed))
kono
parents:
diff changeset
3702 && !flag_ltrans_devirtualize)
kono
parents:
diff changeset
3703 {
kono
parents:
diff changeset
3704 e->indirect_info->polymorphic = false;
kono
parents:
diff changeset
3705 ndropped++;
kono
parents:
diff changeset
3706 if (dump_file)
kono
parents:
diff changeset
3707 fprintf (dump_file, "Dropping polymorphic call info;"
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3708 " it cannot be used by ipa-prop\n");
111
kono
parents:
diff changeset
3709 }
kono
parents:
diff changeset
3710
kono
parents:
diff changeset
3711 if (!opt_for_fn (n->decl, flag_devirtualize_speculatively))
kono
parents:
diff changeset
3712 continue;
kono
parents:
diff changeset
3713
kono
parents:
diff changeset
3714 if (!e->maybe_hot_p ())
kono
parents:
diff changeset
3715 {
kono
parents:
diff changeset
3716 if (dump_file)
kono
parents:
diff changeset
3717 fprintf (dump_file, "Call is cold\n\n");
kono
parents:
diff changeset
3718 ncold++;
kono
parents:
diff changeset
3719 continue;
kono
parents:
diff changeset
3720 }
kono
parents:
diff changeset
3721 if (e->speculative)
kono
parents:
diff changeset
3722 {
kono
parents:
diff changeset
3723 if (dump_file)
kono
parents:
diff changeset
3724 fprintf (dump_file, "Call is already speculated\n\n");
kono
parents:
diff changeset
3725 nspeculated++;
kono
parents:
diff changeset
3726
kono
parents:
diff changeset
3727 /* When dumping see if we agree with speculation. */
kono
parents:
diff changeset
3728 if (!dump_file)
kono
parents:
diff changeset
3729 continue;
kono
parents:
diff changeset
3730 }
kono
parents:
diff changeset
3731 if (bad_call_targets.contains (cache_token))
kono
parents:
diff changeset
3732 {
kono
parents:
diff changeset
3733 if (dump_file)
kono
parents:
diff changeset
3734 fprintf (dump_file, "Target list is known to be useless\n\n");
kono
parents:
diff changeset
3735 nmultiple++;
kono
parents:
diff changeset
3736 continue;
kono
parents:
diff changeset
3737 }
kono
parents:
diff changeset
3738 for (i = 0; i < targets.length (); i++)
kono
parents:
diff changeset
3739 if (likely_target_p (targets[i]))
kono
parents:
diff changeset
3740 {
kono
parents:
diff changeset
3741 if (likely_target)
kono
parents:
diff changeset
3742 {
kono
parents:
diff changeset
3743 likely_target = NULL;
kono
parents:
diff changeset
3744 if (dump_file)
kono
parents:
diff changeset
3745 fprintf (dump_file, "More than one likely target\n\n");
kono
parents:
diff changeset
3746 nmultiple++;
kono
parents:
diff changeset
3747 break;
kono
parents:
diff changeset
3748 }
kono
parents:
diff changeset
3749 likely_target = targets[i];
kono
parents:
diff changeset
3750 }
kono
parents:
diff changeset
3751 if (!likely_target)
kono
parents:
diff changeset
3752 {
kono
parents:
diff changeset
3753 bad_call_targets.add (cache_token);
kono
parents:
diff changeset
3754 continue;
kono
parents:
diff changeset
3755 }
kono
parents:
diff changeset
3756 /* This is reached only when dumping; check if we agree or disagree
kono
parents:
diff changeset
3757 with the speculation. */
kono
parents:
diff changeset
3758 if (e->speculative)
kono
parents:
diff changeset
3759 {
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3760 bool found = e->speculative_call_for_target (likely_target);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
3761 if (found)
111
kono
parents:
diff changeset
3762 {
kono
parents:
diff changeset
3763 fprintf (dump_file, "We agree with speculation\n\n");
kono
parents:
diff changeset
3764 nok++;
kono
parents:
diff changeset
3765 }
kono
parents:
diff changeset
3766 else
kono
parents:
diff changeset
3767 {
kono
parents:
diff changeset
3768 fprintf (dump_file, "We disagree with speculation\n\n");
kono
parents:
diff changeset
3769 nwrong++;
kono
parents:
diff changeset
3770 }
kono
parents:
diff changeset
3771 continue;
kono
parents:
diff changeset
3772 }
kono
parents:
diff changeset
3773 if (!likely_target->definition)
kono
parents:
diff changeset
3774 {
kono
parents:
diff changeset
3775 if (dump_file)
kono
parents:
diff changeset
3776 fprintf (dump_file, "Target is not a definition\n\n");
kono
parents:
diff changeset
3777 nnotdefined++;
kono
parents:
diff changeset
3778 continue;
kono
parents:
diff changeset
3779 }
kono
parents:
diff changeset
3780 /* Do not introduce new references to external symbols. While we
kono
parents:
diff changeset
3781 can handle these just well, it is common for programs to
kono
parents:
diff changeset
3782 incorrectly with headers defining methods they are linked
kono
parents:
diff changeset
3783 with. */
kono
parents:
diff changeset
3784 if (DECL_EXTERNAL (likely_target->decl))
kono
parents:
diff changeset
3785 {
kono
parents:
diff changeset
3786 if (dump_file)
kono
parents:
diff changeset
3787 fprintf (dump_file, "Target is external\n\n");
kono
parents:
diff changeset
3788 nexternal++;
kono
parents:
diff changeset
3789 continue;
kono
parents:
diff changeset
3790 }
kono
parents:
diff changeset
3791 /* Don't use an implicitly-declared destructor (c++/58678). */
kono
parents:
diff changeset
3792 struct cgraph_node *non_thunk_target
kono
parents:
diff changeset
3793 = likely_target->function_symbol ();
kono
parents:
diff changeset
3794 if (DECL_ARTIFICIAL (non_thunk_target->decl))
kono
parents:
diff changeset
3795 {
kono
parents:
diff changeset
3796 if (dump_file)
kono
parents:
diff changeset
3797 fprintf (dump_file, "Target is artificial\n\n");
kono
parents:
diff changeset
3798 nartificial++;
kono
parents:
diff changeset
3799 continue;
kono
parents:
diff changeset
3800 }
kono
parents:
diff changeset
3801 if (likely_target->get_availability () <= AVAIL_INTERPOSABLE
kono
parents:
diff changeset
3802 && likely_target->can_be_discarded_p ())
kono
parents:
diff changeset
3803 {
kono
parents:
diff changeset
3804 if (dump_file)
kono
parents:
diff changeset
3805 fprintf (dump_file, "Target is overwritable\n\n");
kono
parents:
diff changeset
3806 noverwritable++;
kono
parents:
diff changeset
3807 continue;
kono
parents:
diff changeset
3808 }
kono
parents:
diff changeset
3809 else if (dbg_cnt (devirt))
kono
parents:
diff changeset
3810 {
kono
parents:
diff changeset
3811 if (dump_enabled_p ())
kono
parents:
diff changeset
3812 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3813 dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, e->call_stmt,
111
kono
parents:
diff changeset
3814 "speculatively devirtualizing call "
kono
parents:
diff changeset
3815 "in %s to %s\n",
kono
parents:
diff changeset
3816 n->dump_name (),
kono
parents:
diff changeset
3817 likely_target->dump_name ());
kono
parents:
diff changeset
3818 }
kono
parents:
diff changeset
3819 if (!likely_target->can_be_discarded_p ())
kono
parents:
diff changeset
3820 {
kono
parents:
diff changeset
3821 cgraph_node *alias;
kono
parents:
diff changeset
3822 alias = dyn_cast<cgraph_node *> (likely_target->noninterposable_alias ());
kono
parents:
diff changeset
3823 if (alias)
kono
parents:
diff changeset
3824 likely_target = alias;
kono
parents:
diff changeset
3825 }
kono
parents:
diff changeset
3826 nconverted++;
kono
parents:
diff changeset
3827 update = true;
kono
parents:
diff changeset
3828 e->make_speculative
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
3829 (likely_target, e->count.apply_scale (8, 10));
111
kono
parents:
diff changeset
3830 }
kono
parents:
diff changeset
3831 }
kono
parents:
diff changeset
3832 if (update)
kono
parents:
diff changeset
3833 ipa_update_overall_fn_summary (n);
kono
parents:
diff changeset
3834 }
kono
parents:
diff changeset
3835 if (warn_suggest_final_methods || warn_suggest_final_types)
kono
parents:
diff changeset
3836 {
kono
parents:
diff changeset
3837 if (warn_suggest_final_types)
kono
parents:
diff changeset
3838 {
kono
parents:
diff changeset
3839 final_warning_records->type_warnings.qsort (type_warning_cmp);
kono
parents:
diff changeset
3840 for (unsigned int i = 0;
kono
parents:
diff changeset
3841 i < final_warning_records->type_warnings.length (); i++)
kono
parents:
diff changeset
3842 if (final_warning_records->type_warnings[i].count)
kono
parents:
diff changeset
3843 {
kono
parents:
diff changeset
3844 tree type = final_warning_records->type_warnings[i].type;
kono
parents:
diff changeset
3845 int count = final_warning_records->type_warnings[i].count;
kono
parents:
diff changeset
3846 profile_count dyn_count
kono
parents:
diff changeset
3847 = final_warning_records->type_warnings[i].dyn_count;
kono
parents:
diff changeset
3848
kono
parents:
diff changeset
3849 if (!(dyn_count > 0))
kono
parents:
diff changeset
3850 warning_n (DECL_SOURCE_LOCATION (TYPE_NAME (type)),
kono
parents:
diff changeset
3851 OPT_Wsuggest_final_types, count,
kono
parents:
diff changeset
3852 "Declaring type %qD final "
kono
parents:
diff changeset
3853 "would enable devirtualization of %i call",
kono
parents:
diff changeset
3854 "Declaring type %qD final "
kono
parents:
diff changeset
3855 "would enable devirtualization of %i calls",
kono
parents:
diff changeset
3856 type,
kono
parents:
diff changeset
3857 count);
kono
parents:
diff changeset
3858 else
kono
parents:
diff changeset
3859 warning_n (DECL_SOURCE_LOCATION (TYPE_NAME (type)),
kono
parents:
diff changeset
3860 OPT_Wsuggest_final_types, count,
kono
parents:
diff changeset
3861 "Declaring type %qD final "
kono
parents:
diff changeset
3862 "would enable devirtualization of %i call "
kono
parents:
diff changeset
3863 "executed %lli times",
kono
parents:
diff changeset
3864 "Declaring type %qD final "
kono
parents:
diff changeset
3865 "would enable devirtualization of %i calls "
kono
parents:
diff changeset
3866 "executed %lli times",
kono
parents:
diff changeset
3867 type,
kono
parents:
diff changeset
3868 count,
kono
parents:
diff changeset
3869 (long long) dyn_count.to_gcov_type ());
kono
parents:
diff changeset
3870 }
kono
parents:
diff changeset
3871 }
kono
parents:
diff changeset
3872
kono
parents:
diff changeset
3873 if (warn_suggest_final_methods)
kono
parents:
diff changeset
3874 {
kono
parents:
diff changeset
3875 auto_vec<const decl_warn_count*> decl_warnings_vec;
kono
parents:
diff changeset
3876
kono
parents:
diff changeset
3877 final_warning_records->decl_warnings.traverse
kono
parents:
diff changeset
3878 <vec<const decl_warn_count *> *, add_decl_warning> (&decl_warnings_vec);
kono
parents:
diff changeset
3879 decl_warnings_vec.qsort (decl_warning_cmp);
kono
parents:
diff changeset
3880 for (unsigned int i = 0; i < decl_warnings_vec.length (); i++)
kono
parents:
diff changeset
3881 {
kono
parents:
diff changeset
3882 tree decl = decl_warnings_vec[i]->decl;
kono
parents:
diff changeset
3883 int count = decl_warnings_vec[i]->count;
kono
parents:
diff changeset
3884 profile_count dyn_count
kono
parents:
diff changeset
3885 = decl_warnings_vec[i]->dyn_count;
kono
parents:
diff changeset
3886
kono
parents:
diff changeset
3887 if (!(dyn_count > 0))
kono
parents:
diff changeset
3888 if (DECL_CXX_DESTRUCTOR_P (decl))
kono
parents:
diff changeset
3889 warning_n (DECL_SOURCE_LOCATION (decl),
kono
parents:
diff changeset
3890 OPT_Wsuggest_final_methods, count,
kono
parents:
diff changeset
3891 "Declaring virtual destructor of %qD final "
kono
parents:
diff changeset
3892 "would enable devirtualization of %i call",
kono
parents:
diff changeset
3893 "Declaring virtual destructor of %qD final "
kono
parents:
diff changeset
3894 "would enable devirtualization of %i calls",
kono
parents:
diff changeset
3895 DECL_CONTEXT (decl), count);
kono
parents:
diff changeset
3896 else
kono
parents:
diff changeset
3897 warning_n (DECL_SOURCE_LOCATION (decl),
kono
parents:
diff changeset
3898 OPT_Wsuggest_final_methods, count,
kono
parents:
diff changeset
3899 "Declaring method %qD final "
kono
parents:
diff changeset
3900 "would enable devirtualization of %i call",
kono
parents:
diff changeset
3901 "Declaring method %qD final "
kono
parents:
diff changeset
3902 "would enable devirtualization of %i calls",
kono
parents:
diff changeset
3903 decl, count);
kono
parents:
diff changeset
3904 else if (DECL_CXX_DESTRUCTOR_P (decl))
kono
parents:
diff changeset
3905 warning_n (DECL_SOURCE_LOCATION (decl),
kono
parents:
diff changeset
3906 OPT_Wsuggest_final_methods, count,
kono
parents:
diff changeset
3907 "Declaring virtual destructor of %qD final "
kono
parents:
diff changeset
3908 "would enable devirtualization of %i call "
kono
parents:
diff changeset
3909 "executed %lli times",
kono
parents:
diff changeset
3910 "Declaring virtual destructor of %qD final "
kono
parents:
diff changeset
3911 "would enable devirtualization of %i calls "
kono
parents:
diff changeset
3912 "executed %lli times",
kono
parents:
diff changeset
3913 DECL_CONTEXT (decl), count,
kono
parents:
diff changeset
3914 (long long)dyn_count.to_gcov_type ());
kono
parents:
diff changeset
3915 else
kono
parents:
diff changeset
3916 warning_n (DECL_SOURCE_LOCATION (decl),
kono
parents:
diff changeset
3917 OPT_Wsuggest_final_methods, count,
kono
parents:
diff changeset
3918 "Declaring method %qD final "
kono
parents:
diff changeset
3919 "would enable devirtualization of %i call "
kono
parents:
diff changeset
3920 "executed %lli times",
kono
parents:
diff changeset
3921 "Declaring method %qD final "
kono
parents:
diff changeset
3922 "would enable devirtualization of %i calls "
kono
parents:
diff changeset
3923 "executed %lli times",
kono
parents:
diff changeset
3924 decl, count,
kono
parents:
diff changeset
3925 (long long)dyn_count.to_gcov_type ());
kono
parents:
diff changeset
3926 }
kono
parents:
diff changeset
3927 }
kono
parents:
diff changeset
3928
kono
parents:
diff changeset
3929 delete (final_warning_records);
kono
parents:
diff changeset
3930 final_warning_records = 0;
kono
parents:
diff changeset
3931 }
kono
parents:
diff changeset
3932
kono
parents:
diff changeset
3933 if (dump_file)
kono
parents:
diff changeset
3934 fprintf (dump_file,
kono
parents:
diff changeset
3935 "%i polymorphic calls, %i devirtualized,"
kono
parents:
diff changeset
3936 " %i speculatively devirtualized, %i cold\n"
kono
parents:
diff changeset
3937 "%i have multiple targets, %i overwritable,"
kono
parents:
diff changeset
3938 " %i already speculated (%i agree, %i disagree),"
kono
parents:
diff changeset
3939 " %i external, %i not defined, %i artificial, %i infos dropped\n",
kono
parents:
diff changeset
3940 npolymorphic, ndevirtualized, nconverted, ncold,
kono
parents:
diff changeset
3941 nmultiple, noverwritable, nspeculated, nok, nwrong,
kono
parents:
diff changeset
3942 nexternal, nnotdefined, nartificial, ndropped);
kono
parents:
diff changeset
3943 return ndevirtualized || ndropped ? TODO_remove_functions : 0;
kono
parents:
diff changeset
3944 }
kono
parents:
diff changeset
3945
kono
parents:
diff changeset
3946 namespace {
kono
parents:
diff changeset
3947
kono
parents:
diff changeset
3948 const pass_data pass_data_ipa_devirt =
kono
parents:
diff changeset
3949 {
kono
parents:
diff changeset
3950 IPA_PASS, /* type */
kono
parents:
diff changeset
3951 "devirt", /* name */
kono
parents:
diff changeset
3952 OPTGROUP_NONE, /* optinfo_flags */
kono
parents:
diff changeset
3953 TV_IPA_DEVIRT, /* tv_id */
kono
parents:
diff changeset
3954 0, /* properties_required */
kono
parents:
diff changeset
3955 0, /* properties_provided */
kono
parents:
diff changeset
3956 0, /* properties_destroyed */
kono
parents:
diff changeset
3957 0, /* todo_flags_start */
kono
parents:
diff changeset
3958 ( TODO_dump_symtab ), /* todo_flags_finish */
kono
parents:
diff changeset
3959 };
kono
parents:
diff changeset
3960
kono
parents:
diff changeset
3961 class pass_ipa_devirt : public ipa_opt_pass_d
kono
parents:
diff changeset
3962 {
kono
parents:
diff changeset
3963 public:
kono
parents:
diff changeset
3964 pass_ipa_devirt (gcc::context *ctxt)
kono
parents:
diff changeset
3965 : ipa_opt_pass_d (pass_data_ipa_devirt, ctxt,
kono
parents:
diff changeset
3966 NULL, /* generate_summary */
kono
parents:
diff changeset
3967 NULL, /* write_summary */
kono
parents:
diff changeset
3968 NULL, /* read_summary */
kono
parents:
diff changeset
3969 NULL, /* write_optimization_summary */
kono
parents:
diff changeset
3970 NULL, /* read_optimization_summary */
kono
parents:
diff changeset
3971 NULL, /* stmt_fixup */
kono
parents:
diff changeset
3972 0, /* function_transform_todo_flags_start */
kono
parents:
diff changeset
3973 NULL, /* function_transform */
kono
parents:
diff changeset
3974 NULL) /* variable_transform */
kono
parents:
diff changeset
3975 {}
kono
parents:
diff changeset
3976
kono
parents:
diff changeset
3977 /* opt_pass methods: */
kono
parents:
diff changeset
3978 virtual bool gate (function *)
kono
parents:
diff changeset
3979 {
kono
parents:
diff changeset
3980 /* In LTO, always run the IPA passes and decide on function basis if the
kono
parents:
diff changeset
3981 pass is enabled. */
kono
parents:
diff changeset
3982 if (in_lto_p)
kono
parents:
diff changeset
3983 return true;
kono
parents:
diff changeset
3984 return (flag_devirtualize
kono
parents:
diff changeset
3985 && (flag_devirtualize_speculatively
kono
parents:
diff changeset
3986 || (warn_suggest_final_methods
kono
parents:
diff changeset
3987 || warn_suggest_final_types))
kono
parents:
diff changeset
3988 && optimize);
kono
parents:
diff changeset
3989 }
kono
parents:
diff changeset
3990
kono
parents:
diff changeset
3991 virtual unsigned int execute (function *) { return ipa_devirt (); }
kono
parents:
diff changeset
3992
kono
parents:
diff changeset
3993 }; // class pass_ipa_devirt
kono
parents:
diff changeset
3994
kono
parents:
diff changeset
3995 } // anon namespace
kono
parents:
diff changeset
3996
kono
parents:
diff changeset
3997 ipa_opt_pass_d *
kono
parents:
diff changeset
3998 make_pass_ipa_devirt (gcc::context *ctxt)
kono
parents:
diff changeset
3999 {
kono
parents:
diff changeset
4000 return new pass_ipa_devirt (ctxt);
kono
parents:
diff changeset
4001 }
kono
parents:
diff changeset
4002
145
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4003 /* Print ODR name of a TYPE if available.
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4004 Use demangler when option DEMANGLE is used. */
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4005
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4006 DEBUG_FUNCTION void
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4007 debug_tree_odr_name (tree type, bool demangle)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4008 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4009 const char *odr = get_odr_name_for_type (type);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4010 if (demangle)
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4011 {
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4012 const int opts = DMGL_PARAMS | DMGL_ANSI | DMGL_TYPES;
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4013 odr = cplus_demangle (odr, opts);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4014 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4015
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4016 fprintf (stderr, "%s\n", odr);
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4017 }
1830386684a0 gcc-9.2.0
anatofuz
parents: 131
diff changeset
4018
111
kono
parents:
diff changeset
4019 #include "gt-ipa-devirt.h"