File: | build/gcc/tree-cfg.cc |
Warning: | line 1062, column 2 Argument to free() is the address of the local variable 'dispatcher_bb_array', which is not memory allocated by malloc() |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* Control flow functions for trees. | |||
2 | Copyright (C) 2001-2023 Free Software Foundation, Inc. | |||
3 | Contributed by Diego Novillo <dnovillo@redhat.com> | |||
4 | ||||
5 | This file is part of GCC. | |||
6 | ||||
7 | GCC is free software; you can redistribute it and/or modify | |||
8 | it under the terms of the GNU General Public License as published by | |||
9 | the Free Software Foundation; either version 3, or (at your option) | |||
10 | any later version. | |||
11 | ||||
12 | GCC is distributed in the hope that it will be useful, | |||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
15 | GNU General Public License for more details. | |||
16 | ||||
17 | You should have received a copy of the GNU General Public License | |||
18 | along with GCC; see the file COPYING3. If not see | |||
19 | <http://www.gnu.org/licenses/>. */ | |||
20 | ||||
21 | #include "config.h" | |||
22 | #include "system.h" | |||
23 | #include "coretypes.h" | |||
24 | #include "backend.h" | |||
25 | #include "target.h" | |||
26 | #include "rtl.h" | |||
27 | #include "tree.h" | |||
28 | #include "gimple.h" | |||
29 | #include "cfghooks.h" | |||
30 | #include "tree-pass.h" | |||
31 | #include "ssa.h" | |||
32 | #include "cgraph.h" | |||
33 | #include "gimple-pretty-print.h" | |||
34 | #include "diagnostic-core.h" | |||
35 | #include "fold-const.h" | |||
36 | #include "trans-mem.h" | |||
37 | #include "stor-layout.h" | |||
38 | #include "print-tree.h" | |||
39 | #include "cfganal.h" | |||
40 | #include "gimple-iterator.h" | |||
41 | #include "gimple-fold.h" | |||
42 | #include "tree-eh.h" | |||
43 | #include "gimplify-me.h" | |||
44 | #include "gimple-walk.h" | |||
45 | #include "tree-cfg.h" | |||
46 | #include "tree-ssa-loop-manip.h" | |||
47 | #include "tree-ssa-loop-niter.h" | |||
48 | #include "tree-into-ssa.h" | |||
49 | #include "tree-dfa.h" | |||
50 | #include "tree-ssa.h" | |||
51 | #include "except.h" | |||
52 | #include "cfgloop.h" | |||
53 | #include "tree-ssa-propagate.h" | |||
54 | #include "value-prof.h" | |||
55 | #include "tree-inline.h" | |||
56 | #include "tree-ssa-live.h" | |||
57 | #include "tree-ssa-dce.h" | |||
58 | #include "omp-general.h" | |||
59 | #include "omp-expand.h" | |||
60 | #include "tree-cfgcleanup.h" | |||
61 | #include "gimplify.h" | |||
62 | #include "attribs.h" | |||
63 | #include "selftest.h" | |||
64 | #include "opts.h" | |||
65 | #include "asan.h" | |||
66 | #include "profile.h" | |||
67 | #include "sreal.h" | |||
68 | ||||
69 | /* This file contains functions for building the Control Flow Graph (CFG) | |||
70 | for a function tree. */ | |||
71 | ||||
72 | /* Local declarations. */ | |||
73 | ||||
74 | /* Initial capacity for the basic block array. */ | |||
75 | static const int initial_cfg_capacity = 20; | |||
76 | ||||
77 | /* This hash table allows us to efficiently lookup all CASE_LABEL_EXPRs | |||
78 | which use a particular edge. The CASE_LABEL_EXPRs are chained together | |||
79 | via their CASE_CHAIN field, which we clear after we're done with the | |||
80 | hash table to prevent problems with duplication of GIMPLE_SWITCHes. | |||
81 | ||||
82 | Access to this list of CASE_LABEL_EXPRs allows us to efficiently | |||
83 | update the case vector in response to edge redirections. | |||
84 | ||||
85 | Right now this table is set up and torn down at key points in the | |||
86 | compilation process. It would be nice if we could make the table | |||
87 | more persistent. The key is getting notification of changes to | |||
88 | the CFG (particularly edge removal, creation and redirection). */ | |||
89 | ||||
90 | static hash_map<edge, tree> *edge_to_cases; | |||
91 | ||||
92 | /* If we record edge_to_cases, this bitmap will hold indexes | |||
93 | of basic blocks that end in a GIMPLE_SWITCH which we touched | |||
94 | due to edge manipulations. */ | |||
95 | ||||
96 | static bitmap touched_switch_bbs; | |||
97 | ||||
98 | /* OpenMP region idxs for blocks during cfg pass. */ | |||
99 | static vec<int> bb_to_omp_idx; | |||
100 | ||||
101 | /* CFG statistics. */ | |||
102 | struct cfg_stats_d | |||
103 | { | |||
104 | long num_merged_labels; | |||
105 | }; | |||
106 | ||||
107 | static struct cfg_stats_d cfg_stats; | |||
108 | ||||
109 | /* Data to pass to replace_block_vars_by_duplicates_1. */ | |||
110 | struct replace_decls_d | |||
111 | { | |||
112 | hash_map<tree, tree> *vars_map; | |||
113 | tree to_context; | |||
114 | }; | |||
115 | ||||
116 | /* Hash table to store last discriminator assigned for each locus. */ | |||
117 | struct locus_discrim_map | |||
118 | { | |||
119 | int location_line; | |||
120 | int discriminator; | |||
121 | }; | |||
122 | ||||
123 | /* Hashtable helpers. */ | |||
124 | ||||
125 | struct locus_discrim_hasher : free_ptr_hash <locus_discrim_map> | |||
126 | { | |||
127 | static inline hashval_t hash (const locus_discrim_map *); | |||
128 | static inline bool equal (const locus_discrim_map *, | |||
129 | const locus_discrim_map *); | |||
130 | }; | |||
131 | ||||
132 | /* Trivial hash function for a location_t. ITEM is a pointer to | |||
133 | a hash table entry that maps a location_t to a discriminator. */ | |||
134 | ||||
135 | inline hashval_t | |||
136 | locus_discrim_hasher::hash (const locus_discrim_map *item) | |||
137 | { | |||
138 | return item->location_line; | |||
139 | } | |||
140 | ||||
141 | /* Equality function for the locus-to-discriminator map. A and B | |||
142 | point to the two hash table entries to compare. */ | |||
143 | ||||
144 | inline bool | |||
145 | locus_discrim_hasher::equal (const locus_discrim_map *a, | |||
146 | const locus_discrim_map *b) | |||
147 | { | |||
148 | return a->location_line == b->location_line; | |||
149 | } | |||
150 | ||||
151 | static hash_table<locus_discrim_hasher> *discriminator_per_locus; | |||
152 | ||||
153 | /* Basic blocks and flowgraphs. */ | |||
154 | static void make_blocks (gimple_seq); | |||
155 | ||||
156 | /* Edges. */ | |||
157 | static void make_edges (void); | |||
158 | static void assign_discriminators (void); | |||
159 | static void make_cond_expr_edges (basic_block); | |||
160 | static void make_gimple_switch_edges (gswitch *, basic_block); | |||
161 | static bool make_goto_expr_edges (basic_block); | |||
162 | static void make_gimple_asm_edges (basic_block); | |||
163 | static edge gimple_redirect_edge_and_branch (edge, basic_block); | |||
164 | static edge gimple_try_redirect_by_replacing_jump (edge, basic_block); | |||
165 | ||||
166 | /* Various helpers. */ | |||
167 | static inline bool stmt_starts_bb_p (gimple *, gimple *); | |||
168 | static int gimple_verify_flow_info (void); | |||
169 | static void gimple_make_forwarder_block (edge); | |||
170 | static gimple *first_non_label_stmt (basic_block); | |||
171 | static bool verify_gimple_transaction (gtransaction *); | |||
172 | static bool call_can_make_abnormal_goto (gimple *); | |||
173 | ||||
174 | /* Flowgraph optimization and cleanup. */ | |||
175 | static void gimple_merge_blocks (basic_block, basic_block); | |||
176 | static bool gimple_can_merge_blocks_p (basic_block, basic_block); | |||
177 | static void remove_bb (basic_block); | |||
178 | static edge find_taken_edge_computed_goto (basic_block, tree); | |||
179 | static edge find_taken_edge_cond_expr (const gcond *, tree); | |||
180 | ||||
181 | void | |||
182 | init_empty_tree_cfg_for_function (struct function *fn) | |||
183 | { | |||
184 | /* Initialize the basic block array. */ | |||
185 | init_flow (fn); | |||
186 | profile_status_for_fn (fn)((fn)->cfg->x_profile_status) = PROFILE_ABSENT; | |||
187 | n_basic_blocks_for_fn (fn)((fn)->cfg->x_n_basic_blocks) = NUM_FIXED_BLOCKS(2); | |||
188 | last_basic_block_for_fn (fn)((fn)->cfg->x_last_basic_block) = NUM_FIXED_BLOCKS(2); | |||
189 | vec_safe_grow_cleared (basic_block_info_for_fn (fn)((fn)->cfg->x_basic_block_info), | |||
190 | initial_cfg_capacity, true); | |||
191 | ||||
192 | /* Build a mapping of labels to their associated blocks. */ | |||
193 | vec_safe_grow_cleared (label_to_block_map_for_fn (fn)((fn)->cfg->x_label_to_block_map), | |||
194 | initial_cfg_capacity, true); | |||
195 | ||||
196 | SET_BASIC_BLOCK_FOR_FN (fn, ENTRY_BLOCK, ENTRY_BLOCK_PTR_FOR_FN (fn))((*((fn)->cfg->x_basic_block_info))[((0))] = (((fn)-> cfg->x_entry_block_ptr))); | |||
197 | SET_BASIC_BLOCK_FOR_FN (fn, EXIT_BLOCK, EXIT_BLOCK_PTR_FOR_FN (fn))((*((fn)->cfg->x_basic_block_info))[((1))] = (((fn)-> cfg->x_exit_block_ptr))); | |||
198 | ||||
199 | ENTRY_BLOCK_PTR_FOR_FN (fn)((fn)->cfg->x_entry_block_ptr)->next_bb | |||
200 | = EXIT_BLOCK_PTR_FOR_FN (fn)((fn)->cfg->x_exit_block_ptr); | |||
201 | EXIT_BLOCK_PTR_FOR_FN (fn)((fn)->cfg->x_exit_block_ptr)->prev_bb | |||
202 | = ENTRY_BLOCK_PTR_FOR_FN (fn)((fn)->cfg->x_entry_block_ptr); | |||
203 | } | |||
204 | ||||
205 | void | |||
206 | init_empty_tree_cfg (void) | |||
207 | { | |||
208 | init_empty_tree_cfg_for_function (cfun(cfun + 0)); | |||
209 | } | |||
210 | ||||
211 | /*--------------------------------------------------------------------------- | |||
212 | Create basic blocks | |||
213 | ---------------------------------------------------------------------------*/ | |||
214 | ||||
215 | /* Entry point to the CFG builder for trees. SEQ is the sequence of | |||
216 | statements to be added to the flowgraph. */ | |||
217 | ||||
218 | static void | |||
219 | build_gimple_cfg (gimple_seq seq) | |||
220 | { | |||
221 | /* Register specific gimple functions. */ | |||
222 | gimple_register_cfg_hooks (); | |||
223 | ||||
224 | memset ((void *) &cfg_stats, 0, sizeof (cfg_stats)); | |||
225 | ||||
226 | init_empty_tree_cfg (); | |||
227 | ||||
228 | make_blocks (seq); | |||
229 | ||||
230 | /* Make sure there is always at least one block, even if it's empty. */ | |||
231 | if (n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks) == NUM_FIXED_BLOCKS(2)) | |||
232 | create_empty_bb (ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr)); | |||
233 | ||||
234 | /* Adjust the size of the array. */ | |||
235 | if (basic_block_info_for_fn (cfun)(((cfun + 0))->cfg->x_basic_block_info)->length () | |||
236 | < (size_t) n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks)) | |||
237 | vec_safe_grow_cleared (basic_block_info_for_fn (cfun)(((cfun + 0))->cfg->x_basic_block_info), | |||
238 | n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks)); | |||
239 | ||||
240 | /* To speed up statement iterator walks, we first purge dead labels. */ | |||
241 | cleanup_dead_labels (); | |||
242 | ||||
243 | /* Group case nodes to reduce the number of edges. | |||
244 | We do this after cleaning up dead labels because otherwise we miss | |||
245 | a lot of obvious case merging opportunities. */ | |||
246 | group_case_labels (); | |||
247 | ||||
248 | /* Create the edges of the flowgraph. */ | |||
249 | discriminator_per_locus = new hash_table<locus_discrim_hasher> (13); | |||
250 | make_edges (); | |||
251 | assign_discriminators (); | |||
252 | cleanup_dead_labels (); | |||
253 | delete discriminator_per_locus; | |||
254 | discriminator_per_locus = NULLnullptr; | |||
255 | } | |||
256 | ||||
257 | /* Look for ANNOTATE calls with loop annotation kind in BB; if found, remove | |||
258 | them and propagate the information to LOOP. We assume that the annotations | |||
259 | come immediately before the condition in BB, if any. */ | |||
260 | ||||
261 | static void | |||
262 | replace_loop_annotate_in_block (basic_block bb, class loop *loop) | |||
263 | { | |||
264 | gimple_stmt_iterator gsi = gsi_last_bb (bb); | |||
265 | gimple *stmt = gsi_stmt (gsi); | |||
266 | ||||
267 | if (!(stmt && gimple_code (stmt) == GIMPLE_COND)) | |||
268 | return; | |||
269 | ||||
270 | for (gsi_prev_nondebug (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi)) | |||
271 | { | |||
272 | stmt = gsi_stmt (gsi); | |||
273 | if (gimple_code (stmt) != GIMPLE_CALL) | |||
274 | break; | |||
275 | if (!gimple_call_internal_p (stmt) | |||
276 | || gimple_call_internal_fn (stmt) != IFN_ANNOTATE) | |||
277 | break; | |||
278 | ||||
279 | switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1))) | |||
280 | { | |||
281 | case annot_expr_ivdep_kind: | |||
282 | loop->safelen = INT_MAX2147483647; | |||
283 | break; | |||
284 | case annot_expr_unroll_kind: | |||
285 | loop->unroll | |||
286 | = (unsigned short) tree_to_shwi (gimple_call_arg (stmt, 2)); | |||
287 | cfun(cfun + 0)->has_unroll = true; | |||
288 | break; | |||
289 | case annot_expr_no_vector_kind: | |||
290 | loop->dont_vectorize = true; | |||
291 | break; | |||
292 | case annot_expr_vector_kind: | |||
293 | loop->force_vectorize = true; | |||
294 | cfun(cfun + 0)->has_force_vectorize_loops = true; | |||
295 | break; | |||
296 | case annot_expr_parallel_kind: | |||
297 | loop->can_be_parallel = true; | |||
298 | loop->safelen = INT_MAX2147483647; | |||
299 | break; | |||
300 | default: | |||
301 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 301, __FUNCTION__)); | |||
302 | } | |||
303 | ||||
304 | stmt = gimple_build_assign (gimple_call_lhs (stmt), | |||
305 | gimple_call_arg (stmt, 0)); | |||
306 | gsi_replace (&gsi, stmt, true); | |||
307 | } | |||
308 | } | |||
309 | ||||
310 | /* Look for ANNOTATE calls with loop annotation kind; if found, remove | |||
311 | them and propagate the information to the loop. We assume that the | |||
312 | annotations come immediately before the condition of the loop. */ | |||
313 | ||||
314 | static void | |||
315 | replace_loop_annotate (void) | |||
316 | { | |||
317 | basic_block bb; | |||
318 | gimple_stmt_iterator gsi; | |||
319 | gimple *stmt; | |||
320 | ||||
321 | for (auto loop : loops_list (cfun(cfun + 0), 0)) | |||
322 | { | |||
323 | /* First look into the header. */ | |||
324 | replace_loop_annotate_in_block (loop->header, loop); | |||
325 | ||||
326 | /* Then look into the latch, if any. */ | |||
327 | if (loop->latch) | |||
328 | replace_loop_annotate_in_block (loop->latch, loop); | |||
329 | ||||
330 | /* Push the global flag_finite_loops state down to individual loops. */ | |||
331 | loop->finite_p = flag_finite_loopsglobal_options.x_flag_finite_loops; | |||
332 | } | |||
333 | ||||
334 | /* Remove IFN_ANNOTATE. Safeguard for the case loop->latch == NULL. */ | |||
335 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
336 | { | |||
337 | for (gsi = gsi_last_bb (bb); !gsi_end_p (gsi); gsi_prev (&gsi)) | |||
338 | { | |||
339 | stmt = gsi_stmt (gsi); | |||
340 | if (gimple_code (stmt) != GIMPLE_CALL) | |||
341 | continue; | |||
342 | if (!gimple_call_internal_p (stmt) | |||
343 | || gimple_call_internal_fn (stmt) != IFN_ANNOTATE) | |||
344 | continue; | |||
345 | ||||
346 | switch ((annot_expr_kind) tree_to_shwi (gimple_call_arg (stmt, 1))) | |||
347 | { | |||
348 | case annot_expr_ivdep_kind: | |||
349 | case annot_expr_unroll_kind: | |||
350 | case annot_expr_no_vector_kind: | |||
351 | case annot_expr_vector_kind: | |||
352 | case annot_expr_parallel_kind: | |||
353 | break; | |||
354 | default: | |||
355 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 355, __FUNCTION__)); | |||
356 | } | |||
357 | ||||
358 | warning_at (gimple_location (stmt), 0, "ignoring loop annotation"); | |||
359 | stmt = gimple_build_assign (gimple_call_lhs (stmt), | |||
360 | gimple_call_arg (stmt, 0)); | |||
361 | gsi_replace (&gsi, stmt, true); | |||
362 | } | |||
363 | } | |||
364 | } | |||
365 | ||||
366 | static unsigned int | |||
367 | execute_build_cfg (void) | |||
368 | { | |||
369 | gimple_seq body = gimple_body (current_function_decl); | |||
370 | ||||
371 | build_gimple_cfg (body); | |||
372 | gimple_set_body (current_function_decl, NULLnullptr); | |||
373 | if (dump_file && (dump_flags & TDF_DETAILS)) | |||
374 | { | |||
375 | fprintf (dump_file, "Scope blocks:\n"); | |||
376 | dump_scope_blocks (dump_file, dump_flags); | |||
377 | } | |||
378 | cleanup_tree_cfg (); | |||
379 | ||||
380 | bb_to_omp_idx.release (); | |||
381 | ||||
382 | loop_optimizer_init (AVOID_CFG_MODIFICATIONS(LOOPS_MAY_HAVE_MULTIPLE_LATCHES)); | |||
383 | replace_loop_annotate (); | |||
384 | return 0; | |||
385 | } | |||
386 | ||||
387 | namespace { | |||
388 | ||||
389 | const pass_data pass_data_build_cfg = | |||
390 | { | |||
391 | GIMPLE_PASS, /* type */ | |||
392 | "cfg", /* name */ | |||
393 | OPTGROUP_NONE, /* optinfo_flags */ | |||
394 | TV_TREE_CFG, /* tv_id */ | |||
395 | PROP_gimple_leh(1 << 2), /* properties_required */ | |||
396 | ( PROP_cfg(1 << 3) | PROP_loops(1 << 11) ), /* properties_provided */ | |||
397 | 0, /* properties_destroyed */ | |||
398 | 0, /* todo_flags_start */ | |||
399 | 0, /* todo_flags_finish */ | |||
400 | }; | |||
401 | ||||
402 | class pass_build_cfg : public gimple_opt_pass | |||
403 | { | |||
404 | public: | |||
405 | pass_build_cfg (gcc::context *ctxt) | |||
406 | : gimple_opt_pass (pass_data_build_cfg, ctxt) | |||
407 | {} | |||
408 | ||||
409 | /* opt_pass methods: */ | |||
410 | unsigned int execute (function *) final override | |||
411 | { | |||
412 | return execute_build_cfg (); | |||
| ||||
413 | } | |||
414 | ||||
415 | }; // class pass_build_cfg | |||
416 | ||||
417 | } // anon namespace | |||
418 | ||||
419 | gimple_opt_pass * | |||
420 | make_pass_build_cfg (gcc::context *ctxt) | |||
421 | { | |||
422 | return new pass_build_cfg (ctxt); | |||
423 | } | |||
424 | ||||
425 | ||||
426 | /* Return true if T is a computed goto. */ | |||
427 | ||||
428 | bool | |||
429 | computed_goto_p (gimple *t) | |||
430 | { | |||
431 | return (gimple_code (t) == GIMPLE_GOTO | |||
432 | && TREE_CODE (gimple_goto_dest (t))((enum tree_code) (gimple_goto_dest (t))->base.code) != LABEL_DECL); | |||
433 | } | |||
434 | ||||
435 | /* Returns true if the sequence of statements STMTS only contains | |||
436 | a call to __builtin_unreachable (). */ | |||
437 | ||||
438 | bool | |||
439 | gimple_seq_unreachable_p (gimple_seq stmts) | |||
440 | { | |||
441 | if (stmts == NULLnullptr | |||
442 | /* Return false if -fsanitize=unreachable, we don't want to | |||
443 | optimize away those calls, but rather turn them into | |||
444 | __ubsan_handle_builtin_unreachable () or __builtin_trap () | |||
445 | later. */ | |||
446 | || sanitize_flags_p (SANITIZE_UNREACHABLE)) | |||
447 | return false; | |||
448 | ||||
449 | gimple_stmt_iterator gsi = gsi_last (stmts); | |||
450 | ||||
451 | if (!gimple_call_builtin_p (gsi_stmt (gsi), BUILT_IN_UNREACHABLE)) | |||
452 | return false; | |||
453 | ||||
454 | for (gsi_prev (&gsi); !gsi_end_p (gsi); gsi_prev (&gsi)) | |||
455 | { | |||
456 | gimple *stmt = gsi_stmt (gsi); | |||
457 | if (gimple_code (stmt) != GIMPLE_LABEL | |||
458 | && !is_gimple_debug (stmt) | |||
459 | && !gimple_clobber_p (stmt)) | |||
460 | return false; | |||
461 | } | |||
462 | return true; | |||
463 | } | |||
464 | ||||
465 | /* Returns true for edge E where e->src ends with a GIMPLE_COND and | |||
466 | the other edge points to a bb with just __builtin_unreachable (). | |||
467 | I.e. return true for C->M edge in: | |||
468 | <bb C>: | |||
469 | ... | |||
470 | if (something) | |||
471 | goto <bb N>; | |||
472 | else | |||
473 | goto <bb M>; | |||
474 | <bb N>: | |||
475 | __builtin_unreachable (); | |||
476 | <bb M>: */ | |||
477 | ||||
478 | bool | |||
479 | assert_unreachable_fallthru_edge_p (edge e) | |||
480 | { | |||
481 | basic_block pred_bb = e->src; | |||
482 | gimple *last = last_stmt (pred_bb); | |||
483 | if (last && gimple_code (last) == GIMPLE_COND) | |||
484 | { | |||
485 | basic_block other_bb = EDGE_SUCC (pred_bb, 0)(*(pred_bb)->succs)[(0)]->dest; | |||
486 | if (other_bb == e->dest) | |||
487 | other_bb = EDGE_SUCC (pred_bb, 1)(*(pred_bb)->succs)[(1)]->dest; | |||
488 | if (EDGE_COUNT (other_bb->succs)vec_safe_length (other_bb->succs) == 0) | |||
489 | return gimple_seq_unreachable_p (bb_seq (other_bb)); | |||
490 | } | |||
491 | return false; | |||
492 | } | |||
493 | ||||
494 | ||||
495 | /* Initialize GF_CALL_CTRL_ALTERING flag, which indicates the call | |||
496 | could alter control flow except via eh. We initialize the flag at | |||
497 | CFG build time and only ever clear it later. */ | |||
498 | ||||
499 | static void | |||
500 | gimple_call_initialize_ctrl_altering (gimple *stmt) | |||
501 | { | |||
502 | int flags = gimple_call_flags (stmt); | |||
503 | ||||
504 | /* A call alters control flow if it can make an abnormal goto. */ | |||
505 | if (call_can_make_abnormal_goto (stmt) | |||
506 | /* A call also alters control flow if it does not return. */ | |||
507 | || flags & ECF_NORETURN(1 << 3) | |||
508 | /* TM ending statements have backedges out of the transaction. | |||
509 | Return true so we split the basic block containing them. | |||
510 | Note that the TM_BUILTIN test is merely an optimization. */ | |||
511 | || ((flags & ECF_TM_BUILTIN(1 << 13)) | |||
512 | && is_tm_ending_fndecl (gimple_call_fndecl (stmt))) | |||
513 | /* BUILT_IN_RETURN call is same as return statement. */ | |||
514 | || gimple_call_builtin_p (stmt, BUILT_IN_RETURN) | |||
515 | /* IFN_UNIQUE should be the last insn, to make checking for it | |||
516 | as cheap as possible. */ | |||
517 | || (gimple_call_internal_p (stmt) | |||
518 | && gimple_call_internal_unique_p (stmt))) | |||
519 | gimple_call_set_ctrl_altering (stmt, true); | |||
520 | else | |||
521 | gimple_call_set_ctrl_altering (stmt, false); | |||
522 | } | |||
523 | ||||
524 | ||||
525 | /* Insert SEQ after BB and build a flowgraph. */ | |||
526 | ||||
527 | static basic_block | |||
528 | make_blocks_1 (gimple_seq seq, basic_block bb) | |||
529 | { | |||
530 | gimple_stmt_iterator i = gsi_start (seq); | |||
531 | gimple *stmt = NULLnullptr; | |||
532 | gimple *prev_stmt = NULLnullptr; | |||
533 | bool start_new_block = true; | |||
534 | bool first_stmt_of_seq = true; | |||
535 | ||||
536 | while (!gsi_end_p (i)) | |||
537 | { | |||
538 | /* PREV_STMT should only be set to a debug stmt if the debug | |||
539 | stmt is before nondebug stmts. Once stmt reaches a nondebug | |||
540 | nonlabel, prev_stmt will be set to it, so that | |||
541 | stmt_starts_bb_p will know to start a new block if a label is | |||
542 | found. However, if stmt was a label after debug stmts only, | |||
543 | keep the label in prev_stmt even if we find further debug | |||
544 | stmts, for there may be other labels after them, and they | |||
545 | should land in the same block. */ | |||
546 | if (!prev_stmt || !stmt || !is_gimple_debug (stmt)) | |||
547 | prev_stmt = stmt; | |||
548 | stmt = gsi_stmt (i); | |||
549 | ||||
550 | if (stmt && is_gimple_call (stmt)) | |||
551 | gimple_call_initialize_ctrl_altering (stmt); | |||
552 | ||||
553 | /* If the statement starts a new basic block or if we have determined | |||
554 | in a previous pass that we need to create a new block for STMT, do | |||
555 | so now. */ | |||
556 | if (start_new_block || stmt_starts_bb_p (stmt, prev_stmt)) | |||
557 | { | |||
558 | if (!first_stmt_of_seq) | |||
559 | gsi_split_seq_before (&i, &seq); | |||
560 | bb = create_basic_block (seq, bb); | |||
561 | start_new_block = false; | |||
562 | prev_stmt = NULLnullptr; | |||
563 | } | |||
564 | ||||
565 | /* Now add STMT to BB and create the subgraphs for special statement | |||
566 | codes. */ | |||
567 | gimple_set_bb (stmt, bb); | |||
568 | ||||
569 | /* If STMT is a basic block terminator, set START_NEW_BLOCK for the | |||
570 | next iteration. */ | |||
571 | if (stmt_ends_bb_p (stmt)) | |||
572 | { | |||
573 | /* If the stmt can make abnormal goto use a new temporary | |||
574 | for the assignment to the LHS. This makes sure the old value | |||
575 | of the LHS is available on the abnormal edge. Otherwise | |||
576 | we will end up with overlapping life-ranges for abnormal | |||
577 | SSA names. */ | |||
578 | if (gimple_has_lhs (stmt) | |||
579 | && stmt_can_make_abnormal_goto (stmt) | |||
580 | && is_gimple_reg_type (TREE_TYPE (gimple_get_lhs (stmt))((contains_struct_check ((gimple_get_lhs (stmt)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 580, __FUNCTION__))->typed.type))) | |||
581 | { | |||
582 | tree lhs = gimple_get_lhs (stmt); | |||
583 | tree tmp = create_tmp_var (TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 583, __FUNCTION__))->typed.type)); | |||
584 | gimple *s = gimple_build_assign (lhs, tmp); | |||
585 | gimple_set_location (s, gimple_location (stmt)); | |||
586 | gimple_set_block (s, gimple_block (stmt)); | |||
587 | gimple_set_lhs (stmt, tmp); | |||
588 | gsi_insert_after (&i, s, GSI_SAME_STMT); | |||
589 | } | |||
590 | start_new_block = true; | |||
591 | } | |||
592 | ||||
593 | gsi_next (&i); | |||
594 | first_stmt_of_seq = false; | |||
595 | } | |||
596 | return bb; | |||
597 | } | |||
598 | ||||
599 | /* Build a flowgraph for the sequence of stmts SEQ. */ | |||
600 | ||||
601 | static void | |||
602 | make_blocks (gimple_seq seq) | |||
603 | { | |||
604 | /* Look for debug markers right before labels, and move the debug | |||
605 | stmts after the labels. Accepting labels among debug markers | |||
606 | adds no value, just complexity; if we wanted to annotate labels | |||
607 | with view numbers (so sequencing among markers would matter) or | |||
608 | somesuch, we're probably better off still moving the labels, but | |||
609 | adding other debug annotations in their original positions or | |||
610 | emitting nonbind or bind markers associated with the labels in | |||
611 | the original position of the labels. | |||
612 | ||||
613 | Moving labels would probably be simpler, but we can't do that: | |||
614 | moving labels assigns label ids to them, and doing so because of | |||
615 | debug markers makes for -fcompare-debug and possibly even codegen | |||
616 | differences. So, we have to move the debug stmts instead. To | |||
617 | that end, we scan SEQ backwards, marking the position of the | |||
618 | latest (earliest we find) label, and moving debug stmts that are | |||
619 | not separated from it by nondebug nonlabel stmts after the | |||
620 | label. */ | |||
621 | if (MAY_HAVE_DEBUG_MARKER_STMTSglobal_options.x_debug_nonbind_markers_p) | |||
622 | { | |||
623 | gimple_stmt_iterator label = gsi_none (); | |||
624 | ||||
625 | for (gimple_stmt_iterator i = gsi_last (seq); !gsi_end_p (i); gsi_prev (&i)) | |||
626 | { | |||
627 | gimple *stmt = gsi_stmt (i); | |||
628 | ||||
629 | /* If this is the first label we encounter (latest in SEQ) | |||
630 | before nondebug stmts, record its position. */ | |||
631 | if (is_a <glabel *> (stmt)) | |||
632 | { | |||
633 | if (gsi_end_p (label)) | |||
634 | label = i; | |||
635 | continue; | |||
636 | } | |||
637 | ||||
638 | /* Without a recorded label position to move debug stmts to, | |||
639 | there's nothing to do. */ | |||
640 | if (gsi_end_p (label)) | |||
641 | continue; | |||
642 | ||||
643 | /* Move the debug stmt at I after LABEL. */ | |||
644 | if (is_gimple_debug (stmt)) | |||
645 | { | |||
646 | gcc_assert (gimple_debug_nonbind_marker_p (stmt))((void)(!(gimple_debug_nonbind_marker_p (stmt)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 646, __FUNCTION__), 0 : 0)); | |||
647 | /* As STMT is removed, I advances to the stmt after | |||
648 | STMT, so the gsi_prev in the for "increment" | |||
649 | expression gets us to the stmt we're to visit after | |||
650 | STMT. LABEL, however, would advance to the moved | |||
651 | stmt if we passed it to gsi_move_after, so pass it a | |||
652 | copy instead, so as to keep LABEL pointing to the | |||
653 | LABEL. */ | |||
654 | gimple_stmt_iterator copy = label; | |||
655 | gsi_move_after (&i, ©); | |||
656 | continue; | |||
657 | } | |||
658 | ||||
659 | /* There aren't any (more?) debug stmts before label, so | |||
660 | there isn't anything else to move after it. */ | |||
661 | label = gsi_none (); | |||
662 | } | |||
663 | } | |||
664 | ||||
665 | make_blocks_1 (seq, ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr)); | |||
666 | } | |||
667 | ||||
668 | /* Create and return a new empty basic block after bb AFTER. */ | |||
669 | ||||
670 | static basic_block | |||
671 | create_bb (void *h, void *e, basic_block after) | |||
672 | { | |||
673 | basic_block bb; | |||
674 | ||||
675 | gcc_assert (!e)((void)(!(!e) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 675, __FUNCTION__), 0 : 0)); | |||
676 | ||||
677 | /* Create and initialize a new basic block. Since alloc_block uses | |||
678 | GC allocation that clears memory to allocate a basic block, we do | |||
679 | not have to clear the newly allocated basic block here. */ | |||
680 | bb = alloc_block (); | |||
681 | ||||
682 | bb->index = last_basic_block_for_fn (cfun)(((cfun + 0))->cfg->x_last_basic_block); | |||
683 | bb->flags = BB_NEW; | |||
684 | set_bb_seq (bb, h ? (gimple_seq) h : NULLnullptr); | |||
685 | ||||
686 | /* Add the new block to the linked list of blocks. */ | |||
687 | link_block (bb, after); | |||
688 | ||||
689 | /* Grow the basic block array if needed. */ | |||
690 | if ((size_t) last_basic_block_for_fn (cfun)(((cfun + 0))->cfg->x_last_basic_block) | |||
691 | == basic_block_info_for_fn (cfun)(((cfun + 0))->cfg->x_basic_block_info)->length ()) | |||
692 | vec_safe_grow_cleared (basic_block_info_for_fn (cfun)(((cfun + 0))->cfg->x_basic_block_info), | |||
693 | last_basic_block_for_fn (cfun)(((cfun + 0))->cfg->x_last_basic_block) + 1); | |||
694 | ||||
695 | /* Add the newly created block to the array. */ | |||
696 | SET_BASIC_BLOCK_FOR_FN (cfun, last_basic_block_for_fn (cfun), bb)((*(((cfun + 0))->cfg->x_basic_block_info))[((((cfun + 0 ))->cfg->x_last_basic_block))] = (bb)); | |||
697 | ||||
698 | n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks)++; | |||
699 | last_basic_block_for_fn (cfun)(((cfun + 0))->cfg->x_last_basic_block)++; | |||
700 | ||||
701 | return bb; | |||
702 | } | |||
703 | ||||
704 | ||||
705 | /*--------------------------------------------------------------------------- | |||
706 | Edge creation | |||
707 | ---------------------------------------------------------------------------*/ | |||
708 | ||||
709 | /* If basic block BB has an abnormal edge to a basic block | |||
710 | containing IFN_ABNORMAL_DISPATCHER internal call, return | |||
711 | that the dispatcher's basic block, otherwise return NULL. */ | |||
712 | ||||
713 | basic_block | |||
714 | get_abnormal_succ_dispatcher (basic_block bb) | |||
715 | { | |||
716 | edge e; | |||
717 | edge_iterator ei; | |||
718 | ||||
719 | FOR_EACH_EDGE (e, ei, bb->succs)for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei) , &(e)); ei_next (&(ei))) | |||
720 | if ((e->flags & (EDGE_ABNORMAL | EDGE_EH)) == EDGE_ABNORMAL) | |||
721 | { | |||
722 | gimple_stmt_iterator gsi | |||
723 | = gsi_start_nondebug_after_labels_bb (e->dest); | |||
724 | gimple *g = gsi_stmt (gsi); | |||
725 | if (g && gimple_call_internal_p (g, IFN_ABNORMAL_DISPATCHER)) | |||
726 | return e->dest; | |||
727 | } | |||
728 | return NULLnullptr; | |||
729 | } | |||
730 | ||||
731 | /* Helper function for make_edges. Create a basic block with | |||
732 | with ABNORMAL_DISPATCHER internal call in it if needed, and | |||
733 | create abnormal edges from BBS to it and from it to FOR_BB | |||
734 | if COMPUTED_GOTO is false, otherwise factor the computed gotos. */ | |||
735 | ||||
736 | static void | |||
737 | handle_abnormal_edges (basic_block *dispatcher_bbs, basic_block for_bb, | |||
738 | auto_vec<basic_block> *bbs, bool computed_goto) | |||
739 | { | |||
740 | basic_block *dispatcher = dispatcher_bbs + (computed_goto ? 1 : 0); | |||
741 | unsigned int idx = 0; | |||
742 | basic_block bb; | |||
743 | bool inner = false; | |||
744 | ||||
745 | if (!bb_to_omp_idx.is_empty ()) | |||
746 | { | |||
747 | dispatcher = dispatcher_bbs + 2 * bb_to_omp_idx[for_bb->index]; | |||
748 | if (bb_to_omp_idx[for_bb->index] != 0) | |||
749 | inner = true; | |||
750 | } | |||
751 | ||||
752 | /* If the dispatcher has been created already, then there are basic | |||
753 | blocks with abnormal edges to it, so just make a new edge to | |||
754 | for_bb. */ | |||
755 | if (*dispatcher == NULLnullptr) | |||
756 | { | |||
757 | /* Check if there are any basic blocks that need to have | |||
758 | abnormal edges to this dispatcher. If there are none, return | |||
759 | early. */ | |||
760 | if (bb_to_omp_idx.is_empty ()) | |||
761 | { | |||
762 | if (bbs->is_empty ()) | |||
763 | return; | |||
764 | } | |||
765 | else | |||
766 | { | |||
767 | FOR_EACH_VEC_ELT (*bbs, idx, bb)for (idx = 0; (*bbs).iterate ((idx), &(bb)); ++(idx)) | |||
768 | if (bb_to_omp_idx[bb->index] == bb_to_omp_idx[for_bb->index]) | |||
769 | break; | |||
770 | if (bb == NULLnullptr) | |||
771 | return; | |||
772 | } | |||
773 | ||||
774 | /* Create the dispatcher bb. */ | |||
775 | *dispatcher = create_basic_block (NULLnullptr, for_bb); | |||
776 | if (computed_goto) | |||
777 | { | |||
778 | /* Factor computed gotos into a common computed goto site. Also | |||
779 | record the location of that site so that we can un-factor the | |||
780 | gotos after we have converted back to normal form. */ | |||
781 | gimple_stmt_iterator gsi = gsi_start_bb (*dispatcher); | |||
782 | ||||
783 | /* Create the destination of the factored goto. Each original | |||
784 | computed goto will put its desired destination into this | |||
785 | variable and jump to the label we create immediately below. */ | |||
786 | tree var = create_tmp_var (ptr_type_nodeglobal_trees[TI_PTR_TYPE], "gotovar"); | |||
787 | ||||
788 | /* Build a label for the new block which will contain the | |||
789 | factored computed goto. */ | |||
790 | tree factored_label_decl | |||
791 | = create_artificial_label (UNKNOWN_LOCATION((location_t) 0)); | |||
792 | gimple *factored_computed_goto_label | |||
793 | = gimple_build_label (factored_label_decl); | |||
794 | gsi_insert_after (&gsi, factored_computed_goto_label, GSI_NEW_STMT); | |||
795 | ||||
796 | /* Build our new computed goto. */ | |||
797 | gimple *factored_computed_goto = gimple_build_goto (var); | |||
798 | gsi_insert_after (&gsi, factored_computed_goto, GSI_NEW_STMT); | |||
799 | ||||
800 | FOR_EACH_VEC_ELT (*bbs, idx, bb)for (idx = 0; (*bbs).iterate ((idx), &(bb)); ++(idx)) | |||
801 | { | |||
802 | if (!bb_to_omp_idx.is_empty () | |||
803 | && bb_to_omp_idx[bb->index] != bb_to_omp_idx[for_bb->index]) | |||
804 | continue; | |||
805 | ||||
806 | gsi = gsi_last_bb (bb); | |||
807 | gimple *last = gsi_stmt (gsi); | |||
808 | ||||
809 | gcc_assert (computed_goto_p (last))((void)(!(computed_goto_p (last)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 809, __FUNCTION__), 0 : 0)); | |||
810 | ||||
811 | /* Copy the original computed goto's destination into VAR. */ | |||
812 | gimple *assignment | |||
813 | = gimple_build_assign (var, gimple_goto_dest (last)); | |||
814 | gsi_insert_before (&gsi, assignment, GSI_SAME_STMT); | |||
815 | ||||
816 | edge e = make_edge (bb, *dispatcher, EDGE_FALLTHRU); | |||
817 | e->goto_locus = gimple_location (last); | |||
818 | gsi_remove (&gsi, true); | |||
819 | } | |||
820 | } | |||
821 | else | |||
822 | { | |||
823 | tree arg = inner ? boolean_true_nodeglobal_trees[TI_BOOLEAN_TRUE] : boolean_false_nodeglobal_trees[TI_BOOLEAN_FALSE]; | |||
824 | gcall *g = gimple_build_call_internal (IFN_ABNORMAL_DISPATCHER, | |||
825 | 1, arg); | |||
826 | gimple_call_set_ctrl_altering (g, true); | |||
827 | gimple_stmt_iterator gsi = gsi_after_labels (*dispatcher); | |||
828 | gsi_insert_after (&gsi, g, GSI_NEW_STMT); | |||
829 | ||||
830 | /* Create predecessor edges of the dispatcher. */ | |||
831 | FOR_EACH_VEC_ELT (*bbs, idx, bb)for (idx = 0; (*bbs).iterate ((idx), &(bb)); ++(idx)) | |||
832 | { | |||
833 | if (!bb_to_omp_idx.is_empty () | |||
834 | && bb_to_omp_idx[bb->index] != bb_to_omp_idx[for_bb->index]) | |||
835 | continue; | |||
836 | make_edge (bb, *dispatcher, EDGE_ABNORMAL); | |||
837 | } | |||
838 | } | |||
839 | } | |||
840 | ||||
841 | make_edge (*dispatcher, for_bb, EDGE_ABNORMAL); | |||
842 | } | |||
843 | ||||
844 | /* Creates outgoing edges for BB. Returns 1 when it ends with an | |||
845 | computed goto, returns 2 when it ends with a statement that | |||
846 | might return to this function via an nonlocal goto, otherwise | |||
847 | return 0. Updates *PCUR_REGION with the OMP region this BB is in. */ | |||
848 | ||||
849 | static int | |||
850 | make_edges_bb (basic_block bb, struct omp_region **pcur_region, int *pomp_index) | |||
851 | { | |||
852 | gimple *last = last_stmt (bb); | |||
853 | bool fallthru = false; | |||
854 | int ret = 0; | |||
855 | ||||
856 | if (!last) | |||
857 | return ret; | |||
858 | ||||
859 | switch (gimple_code (last)) | |||
860 | { | |||
861 | case GIMPLE_GOTO: | |||
862 | if (make_goto_expr_edges (bb)) | |||
863 | ret = 1; | |||
864 | fallthru = false; | |||
865 | break; | |||
866 | case GIMPLE_RETURN: | |||
867 | { | |||
868 | edge e = make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_exit_block_ptr), 0); | |||
869 | e->goto_locus = gimple_location (last); | |||
870 | fallthru = false; | |||
871 | } | |||
872 | break; | |||
873 | case GIMPLE_COND: | |||
874 | make_cond_expr_edges (bb); | |||
875 | fallthru = false; | |||
876 | break; | |||
877 | case GIMPLE_SWITCH: | |||
878 | make_gimple_switch_edges (as_a <gswitch *> (last), bb); | |||
879 | fallthru = false; | |||
880 | break; | |||
881 | case GIMPLE_RESX: | |||
882 | make_eh_edges (last); | |||
883 | fallthru = false; | |||
884 | break; | |||
885 | case GIMPLE_EH_DISPATCH: | |||
886 | fallthru = make_eh_dispatch_edges (as_a <geh_dispatch *> (last)); | |||
887 | break; | |||
888 | ||||
889 | case GIMPLE_CALL: | |||
890 | /* If this function receives a nonlocal goto, then we need to | |||
891 | make edges from this call site to all the nonlocal goto | |||
892 | handlers. */ | |||
893 | if (stmt_can_make_abnormal_goto (last)) | |||
894 | ret = 2; | |||
895 | ||||
896 | /* If this statement has reachable exception handlers, then | |||
897 | create abnormal edges to them. */ | |||
898 | make_eh_edges (last); | |||
899 | ||||
900 | /* BUILTIN_RETURN is really a return statement. */ | |||
901 | if (gimple_call_builtin_p (last, BUILT_IN_RETURN)) | |||
902 | { | |||
903 | make_edge (bb, EXIT_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_exit_block_ptr), 0); | |||
904 | fallthru = false; | |||
905 | } | |||
906 | /* Some calls are known not to return. */ | |||
907 | else | |||
908 | fallthru = !gimple_call_noreturn_p (last); | |||
909 | break; | |||
910 | ||||
911 | case GIMPLE_ASSIGN: | |||
912 | /* A GIMPLE_ASSIGN may throw internally and thus be considered | |||
913 | control-altering. */ | |||
914 | if (is_ctrl_altering_stmt (last)) | |||
915 | make_eh_edges (last); | |||
916 | fallthru = true; | |||
917 | break; | |||
918 | ||||
919 | case GIMPLE_ASM: | |||
920 | make_gimple_asm_edges (bb); | |||
921 | fallthru = true; | |||
922 | break; | |||
923 | ||||
924 | CASE_GIMPLE_OMPcase GIMPLE_OMP_PARALLEL: case GIMPLE_OMP_TASK: case GIMPLE_OMP_FOR : case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SECTIONS_SWITCH: case GIMPLE_OMP_SINGLE: case GIMPLE_OMP_TARGET: case GIMPLE_OMP_TEAMS : case GIMPLE_OMP_SCOPE: case GIMPLE_OMP_SECTION: case GIMPLE_OMP_MASTER : case GIMPLE_OMP_MASKED: case GIMPLE_OMP_TASKGROUP: case GIMPLE_OMP_ORDERED : case GIMPLE_OMP_CRITICAL: case GIMPLE_OMP_SCAN: case GIMPLE_OMP_RETURN : case GIMPLE_OMP_ATOMIC_LOAD: case GIMPLE_OMP_ATOMIC_STORE: case GIMPLE_OMP_CONTINUE: | |||
925 | fallthru = omp_make_gimple_edges (bb, pcur_region, pomp_index); | |||
926 | break; | |||
927 | ||||
928 | case GIMPLE_TRANSACTION: | |||
929 | { | |||
930 | gtransaction *txn = as_a <gtransaction *> (last); | |||
931 | tree label1 = gimple_transaction_label_norm (txn); | |||
932 | tree label2 = gimple_transaction_label_uninst (txn); | |||
933 | ||||
934 | if (label1) | |||
935 | make_edge (bb, label_to_block (cfun(cfun + 0), label1), EDGE_FALLTHRU); | |||
936 | if (label2) | |||
937 | make_edge (bb, label_to_block (cfun(cfun + 0), label2), | |||
938 | EDGE_TM_UNINSTRUMENTED | (label1 ? 0 : EDGE_FALLTHRU)); | |||
939 | ||||
940 | tree label3 = gimple_transaction_label_over (txn); | |||
941 | if (gimple_transaction_subcode (txn) | |||
942 | & (GTMA_HAVE_ABORT(1u << 2) | GTMA_IS_OUTER(1u << 0))) | |||
943 | make_edge (bb, label_to_block (cfun(cfun + 0), label3), EDGE_TM_ABORT); | |||
944 | ||||
945 | fallthru = false; | |||
946 | } | |||
947 | break; | |||
948 | ||||
949 | default: | |||
950 | gcc_assert (!stmt_ends_bb_p (last))((void)(!(!stmt_ends_bb_p (last)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 950, __FUNCTION__), 0 : 0)); | |||
951 | fallthru = true; | |||
952 | break; | |||
953 | } | |||
954 | ||||
955 | if (fallthru) | |||
956 | make_edge (bb, bb->next_bb, EDGE_FALLTHRU); | |||
957 | ||||
958 | return ret; | |||
959 | } | |||
960 | ||||
961 | /* Join all the blocks in the flowgraph. */ | |||
962 | ||||
963 | static void | |||
964 | make_edges (void) | |||
965 | { | |||
966 | basic_block bb; | |||
967 | struct omp_region *cur_region = NULLnullptr; | |||
968 | auto_vec<basic_block> ab_edge_goto; | |||
969 | auto_vec<basic_block> ab_edge_call; | |||
970 | int cur_omp_region_idx = 0; | |||
971 | ||||
972 | /* Create an edge from entry to the first block with executable | |||
973 | statements in it. */ | |||
974 | make_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr), | |||
975 | BASIC_BLOCK_FOR_FN (cfun, NUM_FIXED_BLOCKS)((*(((cfun + 0))->cfg->x_basic_block_info))[((2))]), | |||
976 | EDGE_FALLTHRU); | |||
977 | ||||
978 | /* Traverse the basic block array placing edges. */ | |||
979 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
980 | { | |||
981 | int mer; | |||
982 | ||||
983 | if (!bb_to_omp_idx.is_empty ()) | |||
984 | bb_to_omp_idx[bb->index] = cur_omp_region_idx; | |||
985 | ||||
986 | mer = make_edges_bb (bb, &cur_region, &cur_omp_region_idx); | |||
987 | if (mer == 1) | |||
988 | ab_edge_goto.safe_push (bb); | |||
989 | else if (mer == 2) | |||
990 | ab_edge_call.safe_push (bb); | |||
991 | ||||
992 | if (cur_region && bb_to_omp_idx.is_empty ()) | |||
993 | bb_to_omp_idx.safe_grow_cleared (n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks), true); | |||
994 | } | |||
995 | ||||
996 | /* Computed gotos are hell to deal with, especially if there are | |||
997 | lots of them with a large number of destinations. So we factor | |||
998 | them to a common computed goto location before we build the | |||
999 | edge list. After we convert back to normal form, we will un-factor | |||
1000 | the computed gotos since factoring introduces an unwanted jump. | |||
1001 | For non-local gotos and abnormal edges from calls to calls that return | |||
1002 | twice or forced labels, factor the abnormal edges too, by having all | |||
1003 | abnormal edges from the calls go to a common artificial basic block | |||
1004 | with ABNORMAL_DISPATCHER internal call and abnormal edges from that | |||
1005 | basic block to all forced labels and calls returning twice. | |||
1006 | We do this per-OpenMP structured block, because those regions | |||
1007 | are guaranteed to be single entry single exit by the standard, | |||
1008 | so it is not allowed to enter or exit such regions abnormally this way, | |||
1009 | thus all computed gotos, non-local gotos and setjmp/longjmp calls | |||
1010 | must not transfer control across SESE region boundaries. */ | |||
1011 | if (!ab_edge_goto.is_empty () || !ab_edge_call.is_empty ()) | |||
1012 | { | |||
1013 | gimple_stmt_iterator gsi; | |||
1014 | basic_block dispatcher_bb_array[2] = { NULLnullptr, NULLnullptr }; | |||
1015 | basic_block *dispatcher_bbs = dispatcher_bb_array; | |||
1016 | int count = n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks); | |||
1017 | ||||
1018 | if (!bb_to_omp_idx.is_empty ()) | |||
1019 | dispatcher_bbs = XCNEWVEC (basic_block, 2 * count)((basic_block *) xcalloc ((2 * count), sizeof (basic_block))); | |||
1020 | ||||
1021 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
1022 | { | |||
1023 | for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | |||
1024 | { | |||
1025 | glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (gsi)); | |||
1026 | tree target; | |||
1027 | ||||
1028 | if (!label_stmt) | |||
1029 | break; | |||
1030 | ||||
1031 | target = gimple_label_label (label_stmt); | |||
1032 | ||||
1033 | /* Make an edge to every label block that has been marked as a | |||
1034 | potential target for a computed goto or a non-local goto. */ | |||
1035 | if (FORCED_LABEL (target)((tree_check ((target), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1035, __FUNCTION__, (LABEL_DECL)))->base.side_effects_flag )) | |||
1036 | handle_abnormal_edges (dispatcher_bbs, bb, &ab_edge_goto, | |||
1037 | true); | |||
1038 | if (DECL_NONLOCAL (target)((contains_struct_check ((target), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1038, __FUNCTION__))->decl_common.nonlocal_flag)) | |||
1039 | { | |||
1040 | handle_abnormal_edges (dispatcher_bbs, bb, &ab_edge_call, | |||
1041 | false); | |||
1042 | break; | |||
1043 | } | |||
1044 | } | |||
1045 | ||||
1046 | if (!gsi_end_p (gsi) && is_gimple_debug (gsi_stmt (gsi))) | |||
1047 | gsi_next_nondebug (&gsi); | |||
1048 | if (!gsi_end_p (gsi)) | |||
1049 | { | |||
1050 | /* Make an edge to every setjmp-like call. */ | |||
1051 | gimple *call_stmt = gsi_stmt (gsi); | |||
1052 | if (is_gimple_call (call_stmt) | |||
1053 | && ((gimple_call_flags (call_stmt) & ECF_RETURNS_TWICE(1 << 7)) | |||
1054 | || gimple_call_builtin_p (call_stmt, | |||
1055 | BUILT_IN_SETJMP_RECEIVER))) | |||
1056 | handle_abnormal_edges (dispatcher_bbs, bb, &ab_edge_call, | |||
1057 | false); | |||
1058 | } | |||
1059 | } | |||
1060 | ||||
1061 | if (!bb_to_omp_idx.is_empty ()) | |||
1062 | XDELETE (dispatcher_bbs)free ((void*) (dispatcher_bbs)); | |||
| ||||
1063 | } | |||
1064 | ||||
1065 | omp_free_regions (); | |||
1066 | } | |||
1067 | ||||
1068 | /* Add SEQ after GSI. Start new bb after GSI, and created further bbs as | |||
1069 | needed. Returns true if new bbs were created. | |||
1070 | Note: This is transitional code, and should not be used for new code. We | |||
1071 | should be able to get rid of this by rewriting all target va-arg | |||
1072 | gimplification hooks to use an interface gimple_build_cond_value as described | |||
1073 | in https://gcc.gnu.org/ml/gcc-patches/2015-02/msg01194.html. */ | |||
1074 | ||||
1075 | bool | |||
1076 | gimple_find_sub_bbs (gimple_seq seq, gimple_stmt_iterator *gsi) | |||
1077 | { | |||
1078 | gimple *stmt = gsi_stmt (*gsi); | |||
1079 | basic_block bb = gimple_bb (stmt); | |||
1080 | basic_block lastbb, afterbb; | |||
1081 | int old_num_bbs = n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks); | |||
1082 | edge e; | |||
1083 | lastbb = make_blocks_1 (seq, bb); | |||
1084 | if (old_num_bbs == n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks)) | |||
1085 | return false; | |||
1086 | e = split_block (bb, stmt); | |||
1087 | /* Move e->dest to come after the new basic blocks. */ | |||
1088 | afterbb = e->dest; | |||
1089 | unlink_block (afterbb); | |||
1090 | link_block (afterbb, lastbb); | |||
1091 | redirect_edge_succ (e, bb->next_bb); | |||
1092 | bb = bb->next_bb; | |||
1093 | while (bb != afterbb) | |||
1094 | { | |||
1095 | struct omp_region *cur_region = NULLnullptr; | |||
1096 | profile_count cnt = profile_count::zero (); | |||
1097 | bool all = true; | |||
1098 | ||||
1099 | int cur_omp_region_idx = 0; | |||
1100 | int mer = make_edges_bb (bb, &cur_region, &cur_omp_region_idx); | |||
1101 | gcc_assert (!mer && !cur_region)((void)(!(!mer && !cur_region) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1101, __FUNCTION__), 0 : 0)); | |||
1102 | add_bb_to_loop (bb, afterbb->loop_father); | |||
1103 | ||||
1104 | edge e; | |||
1105 | edge_iterator ei; | |||
1106 | FOR_EACH_EDGE (e, ei, bb->preds)for ((ei) = ei_start_1 (&((bb->preds))); ei_cond ((ei) , &(e)); ei_next (&(ei))) | |||
1107 | { | |||
1108 | if (e->count ().initialized_p ()) | |||
1109 | cnt += e->count (); | |||
1110 | else | |||
1111 | all = false; | |||
1112 | } | |||
1113 | tree_guess_outgoing_edge_probabilities (bb); | |||
1114 | if (all || profile_status_for_fn (cfun)(((cfun + 0))->cfg->x_profile_status) == PROFILE_READ) | |||
1115 | bb->count = cnt; | |||
1116 | ||||
1117 | bb = bb->next_bb; | |||
1118 | } | |||
1119 | return true; | |||
1120 | } | |||
1121 | ||||
1122 | /* Find the next available discriminator value for LOCUS. The | |||
1123 | discriminator distinguishes among several basic blocks that | |||
1124 | share a common locus, allowing for more accurate sample-based | |||
1125 | profiling. */ | |||
1126 | ||||
1127 | static int | |||
1128 | next_discriminator_for_locus (int line) | |||
1129 | { | |||
1130 | struct locus_discrim_map item; | |||
1131 | struct locus_discrim_map **slot; | |||
1132 | ||||
1133 | item.location_line = line; | |||
1134 | item.discriminator = 0; | |||
1135 | slot = discriminator_per_locus->find_slot_with_hash (&item, line, INSERT); | |||
1136 | gcc_assert (slot)((void)(!(slot) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1136, __FUNCTION__), 0 : 0)); | |||
1137 | if (*slot == HTAB_EMPTY_ENTRY((void *) 0)) | |||
1138 | { | |||
1139 | *slot = XNEW (struct locus_discrim_map)((struct locus_discrim_map *) xmalloc (sizeof (struct locus_discrim_map ))); | |||
1140 | gcc_assert (*slot)((void)(!(*slot) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1140, __FUNCTION__), 0 : 0)); | |||
1141 | (*slot)->location_line = line; | |||
1142 | (*slot)->discriminator = 0; | |||
1143 | } | |||
1144 | (*slot)->discriminator++; | |||
1145 | return (*slot)->discriminator; | |||
1146 | } | |||
1147 | ||||
1148 | /* Return TRUE if LOCUS1 and LOCUS2 refer to the same source line. */ | |||
1149 | ||||
1150 | static bool | |||
1151 | same_line_p (location_t locus1, expanded_location *from, location_t locus2) | |||
1152 | { | |||
1153 | expanded_location to; | |||
1154 | ||||
1155 | if (locus1 == locus2) | |||
1156 | return true; | |||
1157 | ||||
1158 | to = expand_location (locus2); | |||
1159 | ||||
1160 | if (from->line != to.line) | |||
1161 | return false; | |||
1162 | if (from->file == to.file) | |||
1163 | return true; | |||
1164 | return (from->file != NULLnullptr | |||
1165 | && to.file != NULLnullptr | |||
1166 | && filename_cmp (from->file, to.file) == 0); | |||
1167 | } | |||
1168 | ||||
1169 | /* Assign a unique discriminator value to all statements in block bb that | |||
1170 | have the same line number as locus. */ | |||
1171 | ||||
1172 | static void | |||
1173 | assign_discriminator (location_t locus, basic_block bb) | |||
1174 | { | |||
1175 | gimple_stmt_iterator gsi; | |||
1176 | int discriminator; | |||
1177 | ||||
1178 | if (locus == UNKNOWN_LOCATION((location_t) 0)) | |||
1179 | return; | |||
1180 | ||||
1181 | expanded_location locus_e = expand_location (locus); | |||
1182 | ||||
1183 | discriminator = next_discriminator_for_locus (locus_e.line); | |||
1184 | ||||
1185 | for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | |||
1186 | { | |||
1187 | gimple *stmt = gsi_stmt (gsi); | |||
1188 | location_t stmt_locus = gimple_location (stmt); | |||
1189 | if (same_line_p (locus, &locus_e, stmt_locus)) | |||
1190 | gimple_set_location (stmt, | |||
1191 | location_with_discriminator (stmt_locus, discriminator)); | |||
1192 | } | |||
1193 | } | |||
1194 | ||||
1195 | /* Assign discriminators to statement locations. */ | |||
1196 | ||||
1197 | static void | |||
1198 | assign_discriminators (void) | |||
1199 | { | |||
1200 | basic_block bb; | |||
1201 | ||||
1202 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
1203 | { | |||
1204 | edge e; | |||
1205 | edge_iterator ei; | |||
1206 | gimple_stmt_iterator gsi; | |||
1207 | location_t curr_locus = UNKNOWN_LOCATION((location_t) 0); | |||
1208 | expanded_location curr_locus_e = {}; | |||
1209 | int curr_discr = 0; | |||
1210 | ||||
1211 | /* Traverse the basic block, if two function calls within a basic block | |||
1212 | are mapped to the same line, assign a new discriminator because a call | |||
1213 | stmt could be a split point of a basic block. */ | |||
1214 | for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | |||
1215 | { | |||
1216 | gimple *stmt = gsi_stmt (gsi); | |||
1217 | ||||
1218 | if (curr_locus == UNKNOWN_LOCATION((location_t) 0)) | |||
1219 | { | |||
1220 | curr_locus = gimple_location (stmt); | |||
1221 | curr_locus_e = expand_location (curr_locus); | |||
1222 | } | |||
1223 | else if (!same_line_p (curr_locus, &curr_locus_e, gimple_location (stmt))) | |||
1224 | { | |||
1225 | curr_locus = gimple_location (stmt); | |||
1226 | curr_locus_e = expand_location (curr_locus); | |||
1227 | curr_discr = 0; | |||
1228 | } | |||
1229 | else if (curr_discr != 0) | |||
1230 | { | |||
1231 | location_t loc = gimple_location (stmt); | |||
1232 | location_t dloc = location_with_discriminator (loc, curr_discr); | |||
1233 | gimple_set_location (stmt, dloc); | |||
1234 | } | |||
1235 | /* Allocate a new discriminator for CALL stmt. */ | |||
1236 | if (gimple_code (stmt) == GIMPLE_CALL) | |||
1237 | curr_discr = next_discriminator_for_locus (curr_locus); | |||
1238 | } | |||
1239 | ||||
1240 | gimple *last = last_stmt (bb); | |||
1241 | location_t locus = last ? gimple_location (last) : UNKNOWN_LOCATION((location_t) 0); | |||
1242 | if (locus == UNKNOWN_LOCATION((location_t) 0)) | |||
1243 | continue; | |||
1244 | ||||
1245 | expanded_location locus_e = expand_location (locus); | |||
1246 | ||||
1247 | FOR_EACH_EDGE (e, ei, bb->succs)for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei) , &(e)); ei_next (&(ei))) | |||
1248 | { | |||
1249 | gimple *first = first_non_label_stmt (e->dest); | |||
1250 | gimple *last = last_stmt (e->dest); | |||
1251 | ||||
1252 | gimple *stmt_on_same_line = NULLnullptr; | |||
1253 | if (first && same_line_p (locus, &locus_e, | |||
1254 | gimple_location (first))) | |||
1255 | stmt_on_same_line = first; | |||
1256 | else if (last && same_line_p (locus, &locus_e, | |||
1257 | gimple_location (last))) | |||
1258 | stmt_on_same_line = last; | |||
1259 | ||||
1260 | if (stmt_on_same_line) | |||
1261 | { | |||
1262 | if (has_discriminator (gimple_location (stmt_on_same_line)) | |||
1263 | && !has_discriminator (locus)) | |||
1264 | assign_discriminator (locus, bb); | |||
1265 | else | |||
1266 | assign_discriminator (locus, e->dest); | |||
1267 | } | |||
1268 | } | |||
1269 | } | |||
1270 | } | |||
1271 | ||||
1272 | /* Create the edges for a GIMPLE_COND starting at block BB. */ | |||
1273 | ||||
1274 | static void | |||
1275 | make_cond_expr_edges (basic_block bb) | |||
1276 | { | |||
1277 | gcond *entry = as_a <gcond *> (last_stmt (bb)); | |||
1278 | gimple *then_stmt, *else_stmt; | |||
1279 | basic_block then_bb, else_bb; | |||
1280 | tree then_label, else_label; | |||
1281 | edge e; | |||
1282 | ||||
1283 | gcc_assert (entry)((void)(!(entry) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1283, __FUNCTION__), 0 : 0)); | |||
1284 | gcc_assert (gimple_code (entry) == GIMPLE_COND)((void)(!(gimple_code (entry) == GIMPLE_COND) ? fancy_abort ( "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1284, __FUNCTION__), 0 : 0)); | |||
1285 | ||||
1286 | /* Entry basic blocks for each component. */ | |||
1287 | then_label = gimple_cond_true_label (entry); | |||
1288 | else_label = gimple_cond_false_label (entry); | |||
1289 | then_bb = label_to_block (cfun(cfun + 0), then_label); | |||
1290 | else_bb = label_to_block (cfun(cfun + 0), else_label); | |||
1291 | then_stmt = first_stmt (then_bb); | |||
1292 | else_stmt = first_stmt (else_bb); | |||
1293 | ||||
1294 | e = make_edge (bb, then_bb, EDGE_TRUE_VALUE); | |||
1295 | e->goto_locus = gimple_location (then_stmt); | |||
1296 | e = make_edge (bb, else_bb, EDGE_FALSE_VALUE); | |||
1297 | if (e) | |||
1298 | e->goto_locus = gimple_location (else_stmt); | |||
1299 | ||||
1300 | /* We do not need the labels anymore. */ | |||
1301 | gimple_cond_set_true_label (entry, NULL_TREE(tree) nullptr); | |||
1302 | gimple_cond_set_false_label (entry, NULL_TREE(tree) nullptr); | |||
1303 | } | |||
1304 | ||||
1305 | ||||
1306 | /* Called for each element in the hash table (P) as we delete the | |||
1307 | edge to cases hash table. | |||
1308 | ||||
1309 | Clear all the CASE_CHAINs to prevent problems with copying of | |||
1310 | SWITCH_EXPRs and structure sharing rules, then free the hash table | |||
1311 | element. */ | |||
1312 | ||||
1313 | bool | |||
1314 | edge_to_cases_cleanup (edge const &, tree const &value, void *) | |||
1315 | { | |||
1316 | tree t, next; | |||
1317 | ||||
1318 | for (t = value; t; t = next) | |||
1319 | { | |||
1320 | next = CASE_CHAIN (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1320, __FUNCTION__, (CASE_LABEL_EXPR)))), (3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1320, __FUNCTION__))))); | |||
1321 | CASE_CHAIN (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1321, __FUNCTION__, (CASE_LABEL_EXPR)))), (3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1321, __FUNCTION__))))) = NULLnullptr; | |||
1322 | } | |||
1323 | ||||
1324 | return true; | |||
1325 | } | |||
1326 | ||||
1327 | /* Start recording information mapping edges to case labels. */ | |||
1328 | ||||
1329 | void | |||
1330 | start_recording_case_labels (void) | |||
1331 | { | |||
1332 | gcc_assert (edge_to_cases == NULL)((void)(!(edge_to_cases == nullptr) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1332, __FUNCTION__), 0 : 0)); | |||
1333 | edge_to_cases = new hash_map<edge, tree>; | |||
1334 | touched_switch_bbs = BITMAP_ALLOCbitmap_alloc (NULLnullptr); | |||
1335 | } | |||
1336 | ||||
1337 | /* Return nonzero if we are recording information for case labels. */ | |||
1338 | ||||
1339 | static bool | |||
1340 | recording_case_labels_p (void) | |||
1341 | { | |||
1342 | return (edge_to_cases != NULLnullptr); | |||
1343 | } | |||
1344 | ||||
1345 | /* Stop recording information mapping edges to case labels and | |||
1346 | remove any information we have recorded. */ | |||
1347 | void | |||
1348 | end_recording_case_labels (void) | |||
1349 | { | |||
1350 | bitmap_iterator bi; | |||
1351 | unsigned i; | |||
1352 | edge_to_cases->traverse<void *, edge_to_cases_cleanup> (NULLnullptr); | |||
1353 | delete edge_to_cases; | |||
1354 | edge_to_cases = NULLnullptr; | |||
1355 | EXECUTE_IF_SET_IN_BITMAP (touched_switch_bbs, 0, i, bi)for (bmp_iter_set_init (&(bi), (touched_switch_bbs), (0), &(i)); bmp_iter_set (&(bi), &(i)); bmp_iter_next (&(bi), &(i))) | |||
1356 | { | |||
1357 | basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i)((*(((cfun + 0))->cfg->x_basic_block_info))[(i)]); | |||
1358 | if (bb) | |||
1359 | { | |||
1360 | gimple *stmt = last_stmt (bb); | |||
1361 | if (stmt && gimple_code (stmt) == GIMPLE_SWITCH) | |||
1362 | group_case_labels_stmt (as_a <gswitch *> (stmt)); | |||
1363 | } | |||
1364 | } | |||
1365 | BITMAP_FREE (touched_switch_bbs)((void) (bitmap_obstack_free ((bitmap) touched_switch_bbs), ( touched_switch_bbs) = (bitmap) nullptr)); | |||
1366 | } | |||
1367 | ||||
1368 | /* If we are inside a {start,end}_recording_cases block, then return | |||
1369 | a chain of CASE_LABEL_EXPRs from T which reference E. | |||
1370 | ||||
1371 | Otherwise return NULL. */ | |||
1372 | ||||
1373 | tree | |||
1374 | get_cases_for_edge (edge e, gswitch *t) | |||
1375 | { | |||
1376 | tree *slot; | |||
1377 | size_t i, n; | |||
1378 | ||||
1379 | /* If we are not recording cases, then we do not have CASE_LABEL_EXPR | |||
1380 | chains available. Return NULL so the caller can detect this case. */ | |||
1381 | if (!recording_case_labels_p ()) | |||
1382 | return NULLnullptr; | |||
1383 | ||||
1384 | slot = edge_to_cases->get (e); | |||
1385 | if (slot) | |||
1386 | return *slot; | |||
1387 | ||||
1388 | /* If we did not find E in the hash table, then this must be the first | |||
1389 | time we have been queried for information about E & T. Add all the | |||
1390 | elements from T to the hash table then perform the query again. */ | |||
1391 | ||||
1392 | n = gimple_switch_num_labels (t); | |||
1393 | for (i = 0; i < n; i++) | |||
1394 | { | |||
1395 | tree elt = gimple_switch_label (t, i); | |||
1396 | tree lab = CASE_LABEL (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1396, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1396, __FUNCTION__))))); | |||
1397 | basic_block label_bb = label_to_block (cfun(cfun + 0), lab); | |||
1398 | edge this_edge = find_edge (e->src, label_bb); | |||
1399 | ||||
1400 | /* Add it to the chain of CASE_LABEL_EXPRs referencing E, or create | |||
1401 | a new chain. */ | |||
1402 | tree &s = edge_to_cases->get_or_insert (this_edge); | |||
1403 | CASE_CHAIN (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1403, __FUNCTION__, (CASE_LABEL_EXPR)))), (3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1403, __FUNCTION__))))) = s; | |||
1404 | s = elt; | |||
1405 | } | |||
1406 | ||||
1407 | return *edge_to_cases->get (e); | |||
1408 | } | |||
1409 | ||||
1410 | /* Create the edges for a GIMPLE_SWITCH starting at block BB. */ | |||
1411 | ||||
1412 | static void | |||
1413 | make_gimple_switch_edges (gswitch *entry, basic_block bb) | |||
1414 | { | |||
1415 | size_t i, n; | |||
1416 | ||||
1417 | n = gimple_switch_num_labels (entry); | |||
1418 | ||||
1419 | for (i = 0; i < n; ++i) | |||
1420 | { | |||
1421 | basic_block label_bb = gimple_switch_label_bb (cfun(cfun + 0), entry, i); | |||
1422 | make_edge (bb, label_bb, 0); | |||
1423 | } | |||
1424 | } | |||
1425 | ||||
1426 | ||||
1427 | /* Return the basic block holding label DEST. */ | |||
1428 | ||||
1429 | basic_block | |||
1430 | label_to_block (struct function *ifun, tree dest) | |||
1431 | { | |||
1432 | int uid = LABEL_DECL_UID (dest)((tree_check ((dest), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1432, __FUNCTION__, (LABEL_DECL)))->label_decl.label_decl_uid ); | |||
1433 | ||||
1434 | /* We would die hard when faced by an undefined label. Emit a label to | |||
1435 | the very first basic block. This will hopefully make even the dataflow | |||
1436 | and undefined variable warnings quite right. */ | |||
1437 | if (seen_error () && uid < 0) | |||
1438 | { | |||
1439 | gimple_stmt_iterator gsi = | |||
1440 | gsi_start_bb (BASIC_BLOCK_FOR_FN (cfun, NUM_FIXED_BLOCKS)((*(((cfun + 0))->cfg->x_basic_block_info))[((2))])); | |||
1441 | gimple *stmt; | |||
1442 | ||||
1443 | stmt = gimple_build_label (dest); | |||
1444 | gsi_insert_before (&gsi, stmt, GSI_NEW_STMT); | |||
1445 | uid = LABEL_DECL_UID (dest)((tree_check ((dest), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1445, __FUNCTION__, (LABEL_DECL)))->label_decl.label_decl_uid ); | |||
1446 | } | |||
1447 | if (vec_safe_length (ifun->cfg->x_label_to_block_map) <= (unsigned int) uid) | |||
1448 | return NULLnullptr; | |||
1449 | return (*ifun->cfg->x_label_to_block_map)[uid]; | |||
1450 | } | |||
1451 | ||||
1452 | /* Create edges for a goto statement at block BB. Returns true | |||
1453 | if abnormal edges should be created. */ | |||
1454 | ||||
1455 | static bool | |||
1456 | make_goto_expr_edges (basic_block bb) | |||
1457 | { | |||
1458 | gimple_stmt_iterator last = gsi_last_bb (bb); | |||
1459 | gimple *goto_t = gsi_stmt (last); | |||
1460 | ||||
1461 | /* A simple GOTO creates normal edges. */ | |||
1462 | if (simple_goto_p (goto_t)) | |||
1463 | { | |||
1464 | tree dest = gimple_goto_dest (goto_t); | |||
1465 | basic_block label_bb = label_to_block (cfun(cfun + 0), dest); | |||
1466 | edge e = make_edge (bb, label_bb, EDGE_FALLTHRU); | |||
1467 | e->goto_locus = gimple_location (goto_t); | |||
1468 | gsi_remove (&last, true); | |||
1469 | return false; | |||
1470 | } | |||
1471 | ||||
1472 | /* A computed GOTO creates abnormal edges. */ | |||
1473 | return true; | |||
1474 | } | |||
1475 | ||||
1476 | /* Create edges for an asm statement with labels at block BB. */ | |||
1477 | ||||
1478 | static void | |||
1479 | make_gimple_asm_edges (basic_block bb) | |||
1480 | { | |||
1481 | gasm *stmt = as_a <gasm *> (last_stmt (bb)); | |||
1482 | int i, n = gimple_asm_nlabels (stmt); | |||
1483 | ||||
1484 | for (i = 0; i < n; ++i) | |||
1485 | { | |||
1486 | tree label = TREE_VALUE (gimple_asm_label_op (stmt, i))((tree_check ((gimple_asm_label_op (stmt, i)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1486, __FUNCTION__, (TREE_LIST)))->list.value); | |||
1487 | basic_block label_bb = label_to_block (cfun(cfun + 0), label); | |||
1488 | make_edge (bb, label_bb, 0); | |||
1489 | } | |||
1490 | } | |||
1491 | ||||
1492 | /*--------------------------------------------------------------------------- | |||
1493 | Flowgraph analysis | |||
1494 | ---------------------------------------------------------------------------*/ | |||
1495 | ||||
1496 | /* Cleanup useless labels in basic blocks. This is something we wish | |||
1497 | to do early because it allows us to group case labels before creating | |||
1498 | the edges for the CFG, and it speeds up block statement iterators in | |||
1499 | all passes later on. | |||
1500 | We rerun this pass after CFG is created, to get rid of the labels that | |||
1501 | are no longer referenced. After then we do not run it any more, since | |||
1502 | (almost) no new labels should be created. */ | |||
1503 | ||||
1504 | /* A map from basic block index to the leading label of that block. */ | |||
1505 | struct label_record | |||
1506 | { | |||
1507 | /* The label. */ | |||
1508 | tree label; | |||
1509 | ||||
1510 | /* True if the label is referenced from somewhere. */ | |||
1511 | bool used; | |||
1512 | }; | |||
1513 | ||||
1514 | /* Given LABEL return the first label in the same basic block. */ | |||
1515 | ||||
1516 | static tree | |||
1517 | main_block_label (tree label, label_record *label_for_bb) | |||
1518 | { | |||
1519 | basic_block bb = label_to_block (cfun(cfun + 0), label); | |||
1520 | tree main_label = label_for_bb[bb->index].label; | |||
1521 | ||||
1522 | /* label_to_block possibly inserted undefined label into the chain. */ | |||
1523 | if (!main_label) | |||
1524 | { | |||
1525 | label_for_bb[bb->index].label = label; | |||
1526 | main_label = label; | |||
1527 | } | |||
1528 | ||||
1529 | label_for_bb[bb->index].used = true; | |||
1530 | return main_label; | |||
1531 | } | |||
1532 | ||||
1533 | /* Clean up redundant labels within the exception tree. */ | |||
1534 | ||||
1535 | static void | |||
1536 | cleanup_dead_labels_eh (label_record *label_for_bb) | |||
1537 | { | |||
1538 | eh_landing_pad lp; | |||
1539 | eh_region r; | |||
1540 | tree lab; | |||
1541 | int i; | |||
1542 | ||||
1543 | if (cfun(cfun + 0)->eh == NULLnullptr) | |||
1544 | return; | |||
1545 | ||||
1546 | for (i = 1; vec_safe_iterate (cfun(cfun + 0)->eh->lp_array, i, &lp); ++i) | |||
1547 | if (lp && lp->post_landing_pad) | |||
1548 | { | |||
1549 | lab = main_block_label (lp->post_landing_pad, label_for_bb); | |||
1550 | if (lab != lp->post_landing_pad) | |||
1551 | { | |||
1552 | EH_LANDING_PAD_NR (lp->post_landing_pad)((tree_check ((lp->post_landing_pad), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1552, __FUNCTION__, (LABEL_DECL)))->label_decl.eh_landing_pad_nr ) = 0; | |||
1553 | lp->post_landing_pad = lab; | |||
1554 | EH_LANDING_PAD_NR (lab)((tree_check ((lab), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1554, __FUNCTION__, (LABEL_DECL)))->label_decl.eh_landing_pad_nr ) = lp->index; | |||
1555 | } | |||
1556 | } | |||
1557 | ||||
1558 | FOR_ALL_EH_REGION (r)for ((r) = ((cfun + 0))->eh->region_tree; (r) != nullptr ; (r) = ehr_next (r, nullptr)) | |||
1559 | switch (r->type) | |||
1560 | { | |||
1561 | case ERT_CLEANUP: | |||
1562 | case ERT_MUST_NOT_THROW: | |||
1563 | break; | |||
1564 | ||||
1565 | case ERT_TRY: | |||
1566 | { | |||
1567 | eh_catch c; | |||
1568 | for (c = r->u.eh_try.first_catch; c ; c = c->next_catch) | |||
1569 | { | |||
1570 | lab = c->label; | |||
1571 | if (lab) | |||
1572 | c->label = main_block_label (lab, label_for_bb); | |||
1573 | } | |||
1574 | } | |||
1575 | break; | |||
1576 | ||||
1577 | case ERT_ALLOWED_EXCEPTIONS: | |||
1578 | lab = r->u.allowed.label; | |||
1579 | if (lab) | |||
1580 | r->u.allowed.label = main_block_label (lab, label_for_bb); | |||
1581 | break; | |||
1582 | } | |||
1583 | } | |||
1584 | ||||
1585 | ||||
1586 | /* Cleanup redundant labels. This is a three-step process: | |||
1587 | 1) Find the leading label for each block. | |||
1588 | 2) Redirect all references to labels to the leading labels. | |||
1589 | 3) Cleanup all useless labels. */ | |||
1590 | ||||
1591 | void | |||
1592 | cleanup_dead_labels (void) | |||
1593 | { | |||
1594 | basic_block bb; | |||
1595 | label_record *label_for_bb = XCNEWVEC (struct label_record,((struct label_record *) xcalloc (((((cfun + 0))->cfg-> x_last_basic_block)), sizeof (struct label_record))) | |||
1596 | last_basic_block_for_fn (cfun))((struct label_record *) xcalloc (((((cfun + 0))->cfg-> x_last_basic_block)), sizeof (struct label_record))); | |||
1597 | ||||
1598 | /* Find a suitable label for each block. We use the first user-defined | |||
1599 | label if there is one, or otherwise just the first label we see. */ | |||
1600 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
1601 | { | |||
1602 | gimple_stmt_iterator i; | |||
1603 | ||||
1604 | for (i = gsi_start_bb (bb); !gsi_end_p (i); gsi_next (&i)) | |||
1605 | { | |||
1606 | tree label; | |||
1607 | glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (i)); | |||
1608 | ||||
1609 | if (!label_stmt) | |||
1610 | break; | |||
1611 | ||||
1612 | label = gimple_label_label (label_stmt); | |||
1613 | ||||
1614 | /* If we have not yet seen a label for the current block, | |||
1615 | remember this one and see if there are more labels. */ | |||
1616 | if (!label_for_bb[bb->index].label) | |||
1617 | { | |||
1618 | label_for_bb[bb->index].label = label; | |||
1619 | continue; | |||
1620 | } | |||
1621 | ||||
1622 | /* If we did see a label for the current block already, but it | |||
1623 | is an artificially created label, replace it if the current | |||
1624 | label is a user defined label. */ | |||
1625 | if (!DECL_ARTIFICIAL (label)((contains_struct_check ((label), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1625, __FUNCTION__))->decl_common.artificial_flag) | |||
1626 | && DECL_ARTIFICIAL (label_for_bb[bb->index].label)((contains_struct_check ((label_for_bb[bb->index].label), ( TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1626, __FUNCTION__))->decl_common.artificial_flag)) | |||
1627 | { | |||
1628 | label_for_bb[bb->index].label = label; | |||
1629 | break; | |||
1630 | } | |||
1631 | } | |||
1632 | } | |||
1633 | ||||
1634 | /* Now redirect all jumps/branches to the selected label. | |||
1635 | First do so for each block ending in a control statement. */ | |||
1636 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
1637 | { | |||
1638 | gimple *stmt = last_stmt (bb); | |||
1639 | tree label, new_label; | |||
1640 | ||||
1641 | if (!stmt) | |||
1642 | continue; | |||
1643 | ||||
1644 | switch (gimple_code (stmt)) | |||
1645 | { | |||
1646 | case GIMPLE_COND: | |||
1647 | { | |||
1648 | gcond *cond_stmt = as_a <gcond *> (stmt); | |||
1649 | label = gimple_cond_true_label (cond_stmt); | |||
1650 | if (label) | |||
1651 | { | |||
1652 | new_label = main_block_label (label, label_for_bb); | |||
1653 | if (new_label != label) | |||
1654 | gimple_cond_set_true_label (cond_stmt, new_label); | |||
1655 | } | |||
1656 | ||||
1657 | label = gimple_cond_false_label (cond_stmt); | |||
1658 | if (label) | |||
1659 | { | |||
1660 | new_label = main_block_label (label, label_for_bb); | |||
1661 | if (new_label != label) | |||
1662 | gimple_cond_set_false_label (cond_stmt, new_label); | |||
1663 | } | |||
1664 | } | |||
1665 | break; | |||
1666 | ||||
1667 | case GIMPLE_SWITCH: | |||
1668 | { | |||
1669 | gswitch *switch_stmt = as_a <gswitch *> (stmt); | |||
1670 | size_t i, n = gimple_switch_num_labels (switch_stmt); | |||
1671 | ||||
1672 | /* Replace all destination labels. */ | |||
1673 | for (i = 0; i < n; ++i) | |||
1674 | { | |||
1675 | tree case_label = gimple_switch_label (switch_stmt, i); | |||
1676 | label = CASE_LABEL (case_label)(*((const_cast<tree*> (tree_operand_check (((tree_check ((case_label), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1676, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1676, __FUNCTION__))))); | |||
1677 | new_label = main_block_label (label, label_for_bb); | |||
1678 | if (new_label != label) | |||
1679 | CASE_LABEL (case_label)(*((const_cast<tree*> (tree_operand_check (((tree_check ((case_label), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1679, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1679, __FUNCTION__))))) = new_label; | |||
1680 | } | |||
1681 | break; | |||
1682 | } | |||
1683 | ||||
1684 | case GIMPLE_ASM: | |||
1685 | { | |||
1686 | gasm *asm_stmt = as_a <gasm *> (stmt); | |||
1687 | int i, n = gimple_asm_nlabels (asm_stmt); | |||
1688 | ||||
1689 | for (i = 0; i < n; ++i) | |||
1690 | { | |||
1691 | tree cons = gimple_asm_label_op (asm_stmt, i); | |||
1692 | tree label = main_block_label (TREE_VALUE (cons)((tree_check ((cons), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1692, __FUNCTION__, (TREE_LIST)))->list.value), label_for_bb); | |||
1693 | TREE_VALUE (cons)((tree_check ((cons), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1693, __FUNCTION__, (TREE_LIST)))->list.value) = label; | |||
1694 | } | |||
1695 | break; | |||
1696 | } | |||
1697 | ||||
1698 | /* We have to handle gotos until they're removed, and we don't | |||
1699 | remove them until after we've created the CFG edges. */ | |||
1700 | case GIMPLE_GOTO: | |||
1701 | if (!computed_goto_p (stmt)) | |||
1702 | { | |||
1703 | ggoto *goto_stmt = as_a <ggoto *> (stmt); | |||
1704 | label = gimple_goto_dest (goto_stmt); | |||
1705 | new_label = main_block_label (label, label_for_bb); | |||
1706 | if (new_label != label) | |||
1707 | gimple_goto_set_dest (goto_stmt, new_label); | |||
1708 | } | |||
1709 | break; | |||
1710 | ||||
1711 | case GIMPLE_TRANSACTION: | |||
1712 | { | |||
1713 | gtransaction *txn = as_a <gtransaction *> (stmt); | |||
1714 | ||||
1715 | label = gimple_transaction_label_norm (txn); | |||
1716 | if (label) | |||
1717 | { | |||
1718 | new_label = main_block_label (label, label_for_bb); | |||
1719 | if (new_label != label) | |||
1720 | gimple_transaction_set_label_norm (txn, new_label); | |||
1721 | } | |||
1722 | ||||
1723 | label = gimple_transaction_label_uninst (txn); | |||
1724 | if (label) | |||
1725 | { | |||
1726 | new_label = main_block_label (label, label_for_bb); | |||
1727 | if (new_label != label) | |||
1728 | gimple_transaction_set_label_uninst (txn, new_label); | |||
1729 | } | |||
1730 | ||||
1731 | label = gimple_transaction_label_over (txn); | |||
1732 | if (label) | |||
1733 | { | |||
1734 | new_label = main_block_label (label, label_for_bb); | |||
1735 | if (new_label != label) | |||
1736 | gimple_transaction_set_label_over (txn, new_label); | |||
1737 | } | |||
1738 | } | |||
1739 | break; | |||
1740 | ||||
1741 | default: | |||
1742 | break; | |||
1743 | } | |||
1744 | } | |||
1745 | ||||
1746 | /* Do the same for the exception region tree labels. */ | |||
1747 | cleanup_dead_labels_eh (label_for_bb); | |||
1748 | ||||
1749 | /* Finally, purge dead labels. All user-defined labels and labels that | |||
1750 | can be the target of non-local gotos and labels which have their | |||
1751 | address taken are preserved. */ | |||
1752 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
1753 | { | |||
1754 | gimple_stmt_iterator i; | |||
1755 | tree label_for_this_bb = label_for_bb[bb->index].label; | |||
1756 | ||||
1757 | if (!label_for_this_bb) | |||
1758 | continue; | |||
1759 | ||||
1760 | /* If the main label of the block is unused, we may still remove it. */ | |||
1761 | if (!label_for_bb[bb->index].used) | |||
1762 | label_for_this_bb = NULLnullptr; | |||
1763 | ||||
1764 | for (i = gsi_start_bb (bb); !gsi_end_p (i); ) | |||
1765 | { | |||
1766 | tree label; | |||
1767 | glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (i)); | |||
1768 | ||||
1769 | if (!label_stmt) | |||
1770 | break; | |||
1771 | ||||
1772 | label = gimple_label_label (label_stmt); | |||
1773 | ||||
1774 | if (label == label_for_this_bb | |||
1775 | || !DECL_ARTIFICIAL (label)((contains_struct_check ((label), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1775, __FUNCTION__))->decl_common.artificial_flag) | |||
1776 | || DECL_NONLOCAL (label)((contains_struct_check ((label), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1776, __FUNCTION__))->decl_common.nonlocal_flag) | |||
1777 | || FORCED_LABEL (label)((tree_check ((label), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1777, __FUNCTION__, (LABEL_DECL)))->base.side_effects_flag )) | |||
1778 | gsi_next (&i); | |||
1779 | else | |||
1780 | { | |||
1781 | gcc_checking_assert (EH_LANDING_PAD_NR (label) == 0)((void)(!(((tree_check ((label), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1781, __FUNCTION__, (LABEL_DECL)))->label_decl.eh_landing_pad_nr ) == 0) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1781, __FUNCTION__), 0 : 0)); | |||
1782 | gsi_remove (&i, true); | |||
1783 | } | |||
1784 | } | |||
1785 | } | |||
1786 | ||||
1787 | free (label_for_bb); | |||
1788 | } | |||
1789 | ||||
1790 | /* Scan the sorted vector of cases in STMT (a GIMPLE_SWITCH) and combine | |||
1791 | the ones jumping to the same label. | |||
1792 | Eg. three separate entries 1: 2: 3: become one entry 1..3: */ | |||
1793 | ||||
1794 | bool | |||
1795 | group_case_labels_stmt (gswitch *stmt) | |||
1796 | { | |||
1797 | int old_size = gimple_switch_num_labels (stmt); | |||
1798 | int i, next_index, new_size; | |||
1799 | basic_block default_bb = NULLnullptr; | |||
1800 | hash_set<tree> *removed_labels = NULLnullptr; | |||
1801 | ||||
1802 | default_bb = gimple_switch_default_bb (cfun(cfun + 0), stmt); | |||
1803 | ||||
1804 | /* Look for possible opportunities to merge cases. */ | |||
1805 | new_size = i = 1; | |||
1806 | while (i < old_size) | |||
1807 | { | |||
1808 | tree base_case, base_high; | |||
1809 | basic_block base_bb; | |||
1810 | ||||
1811 | base_case = gimple_switch_label (stmt, i); | |||
1812 | ||||
1813 | gcc_assert (base_case)((void)(!(base_case) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1813, __FUNCTION__), 0 : 0)); | |||
1814 | base_bb = label_to_block (cfun(cfun + 0), CASE_LABEL (base_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((base_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1814, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1814, __FUNCTION__)))))); | |||
1815 | ||||
1816 | /* Discard cases that have the same destination as the default case or | |||
1817 | whose destination blocks have already been removed as unreachable. */ | |||
1818 | if (base_bb == NULLnullptr | |||
1819 | || base_bb == default_bb | |||
1820 | || (removed_labels | |||
1821 | && removed_labels->contains (CASE_LABEL (base_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((base_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1821, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1821, __FUNCTION__)))))))) | |||
1822 | { | |||
1823 | i++; | |||
1824 | continue; | |||
1825 | } | |||
1826 | ||||
1827 | base_high = CASE_HIGH (base_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((base_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1827, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1827, __FUNCTION__))))) | |||
1828 | ? CASE_HIGH (base_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((base_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1828, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1828, __FUNCTION__))))) | |||
1829 | : CASE_LOW (base_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((base_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1829, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1829, __FUNCTION__))))); | |||
1830 | next_index = i + 1; | |||
1831 | ||||
1832 | /* Try to merge case labels. Break out when we reach the end | |||
1833 | of the label vector or when we cannot merge the next case | |||
1834 | label with the current one. */ | |||
1835 | while (next_index < old_size) | |||
1836 | { | |||
1837 | tree merge_case = gimple_switch_label (stmt, next_index); | |||
1838 | basic_block merge_bb = label_to_block (cfun(cfun + 0), CASE_LABEL (merge_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((merge_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1838, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1838, __FUNCTION__)))))); | |||
1839 | wide_int bhp1 = wi::to_wide (base_high) + 1; | |||
1840 | ||||
1841 | /* Merge the cases if they jump to the same place, | |||
1842 | and their ranges are consecutive. */ | |||
1843 | if (merge_bb == base_bb | |||
1844 | && (removed_labels == NULLnullptr | |||
1845 | || !removed_labels->contains (CASE_LABEL (merge_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((merge_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1845, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1845, __FUNCTION__))))))) | |||
1846 | && wi::to_wide (CASE_LOW (merge_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((merge_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1846, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1846, __FUNCTION__)))))) == bhp1) | |||
1847 | { | |||
1848 | base_high | |||
1849 | = (CASE_HIGH (merge_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((merge_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1849, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1849, __FUNCTION__))))) | |||
1850 | ? CASE_HIGH (merge_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((merge_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1850, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1850, __FUNCTION__))))) : CASE_LOW (merge_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((merge_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1850, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1850, __FUNCTION__)))))); | |||
1851 | CASE_HIGH (base_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((base_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1851, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1851, __FUNCTION__))))) = base_high; | |||
1852 | next_index++; | |||
1853 | } | |||
1854 | else | |||
1855 | break; | |||
1856 | } | |||
1857 | ||||
1858 | /* Discard cases that have an unreachable destination block. */ | |||
1859 | if (EDGE_COUNT (base_bb->succs)vec_safe_length (base_bb->succs) == 0 | |||
1860 | && gimple_seq_unreachable_p (bb_seq (base_bb)) | |||
1861 | /* Don't optimize this if __builtin_unreachable () is the | |||
1862 | implicitly added one by the C++ FE too early, before | |||
1863 | -Wreturn-type can be diagnosed. We'll optimize it later | |||
1864 | during switchconv pass or any other cfg cleanup. */ | |||
1865 | && (gimple_in_ssa_p (cfun(cfun + 0)) | |||
1866 | || (LOCATION_LOCUS (gimple_location (last_stmt (base_bb)))((IS_ADHOC_LOC (gimple_location (last_stmt (base_bb)))) ? get_location_from_adhoc_loc (line_table, gimple_location (last_stmt (base_bb))) : (gimple_location (last_stmt (base_bb)))) | |||
1867 | != BUILTINS_LOCATION((location_t) 1)))) | |||
1868 | { | |||
1869 | edge base_edge = find_edge (gimple_bb (stmt), base_bb); | |||
1870 | if (base_edge != NULLnullptr) | |||
1871 | { | |||
1872 | for (gimple_stmt_iterator gsi = gsi_start_bb (base_bb); | |||
1873 | !gsi_end_p (gsi); gsi_next (&gsi)) | |||
1874 | if (glabel *stmt = dyn_cast <glabel *> (gsi_stmt (gsi))) | |||
1875 | { | |||
1876 | if (FORCED_LABEL (gimple_label_label (stmt))((tree_check ((gimple_label_label (stmt)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1876, __FUNCTION__, (LABEL_DECL)))->base.side_effects_flag ) | |||
1877 | || DECL_NONLOCAL (gimple_label_label (stmt))((contains_struct_check ((gimple_label_label (stmt)), (TS_DECL_COMMON ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1877, __FUNCTION__))->decl_common.nonlocal_flag)) | |||
1878 | { | |||
1879 | /* Forced/non-local labels aren't going to be removed, | |||
1880 | but they will be moved to some neighbouring basic | |||
1881 | block. If some later case label refers to one of | |||
1882 | those labels, we should throw that case away rather | |||
1883 | than keeping it around and refering to some random | |||
1884 | other basic block without an edge to it. */ | |||
1885 | if (removed_labels == NULLnullptr) | |||
1886 | removed_labels = new hash_set<tree>; | |||
1887 | removed_labels->add (gimple_label_label (stmt)); | |||
1888 | } | |||
1889 | } | |||
1890 | else | |||
1891 | break; | |||
1892 | remove_edge_and_dominated_blocks (base_edge); | |||
1893 | } | |||
1894 | i = next_index; | |||
1895 | continue; | |||
1896 | } | |||
1897 | ||||
1898 | if (new_size < i) | |||
1899 | gimple_switch_set_label (stmt, new_size, | |||
1900 | gimple_switch_label (stmt, i)); | |||
1901 | i = next_index; | |||
1902 | new_size++; | |||
1903 | } | |||
1904 | ||||
1905 | gcc_assert (new_size <= old_size)((void)(!(new_size <= old_size) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1905, __FUNCTION__), 0 : 0)); | |||
1906 | ||||
1907 | if (new_size < old_size) | |||
1908 | gimple_switch_set_num_labels (stmt, new_size); | |||
1909 | ||||
1910 | delete removed_labels; | |||
1911 | return new_size < old_size; | |||
1912 | } | |||
1913 | ||||
1914 | /* Look for blocks ending in a multiway branch (a GIMPLE_SWITCH), | |||
1915 | and scan the sorted vector of cases. Combine the ones jumping to the | |||
1916 | same label. */ | |||
1917 | ||||
1918 | bool | |||
1919 | group_case_labels (void) | |||
1920 | { | |||
1921 | basic_block bb; | |||
1922 | bool changed = false; | |||
1923 | ||||
1924 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
1925 | { | |||
1926 | gimple *stmt = last_stmt (bb); | |||
1927 | if (stmt && gimple_code (stmt) == GIMPLE_SWITCH) | |||
1928 | changed |= group_case_labels_stmt (as_a <gswitch *> (stmt)); | |||
1929 | } | |||
1930 | ||||
1931 | return changed; | |||
1932 | } | |||
1933 | ||||
1934 | /* Checks whether we can merge block B into block A. */ | |||
1935 | ||||
1936 | static bool | |||
1937 | gimple_can_merge_blocks_p (basic_block a, basic_block b) | |||
1938 | { | |||
1939 | gimple *stmt; | |||
1940 | ||||
1941 | if (!single_succ_p (a)) | |||
1942 | return false; | |||
1943 | ||||
1944 | if (single_succ_edge (a)->flags & EDGE_COMPLEX(EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_PRESERVE )) | |||
1945 | return false; | |||
1946 | ||||
1947 | if (single_succ (a) != b) | |||
1948 | return false; | |||
1949 | ||||
1950 | if (!single_pred_p (b)) | |||
1951 | return false; | |||
1952 | ||||
1953 | if (a == ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr) | |||
1954 | || b == EXIT_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_exit_block_ptr)) | |||
1955 | return false; | |||
1956 | ||||
1957 | /* If A ends by a statement causing exceptions or something similar, we | |||
1958 | cannot merge the blocks. */ | |||
1959 | stmt = last_stmt (a); | |||
1960 | if (stmt && stmt_ends_bb_p (stmt)) | |||
1961 | return false; | |||
1962 | ||||
1963 | /* Do not allow a block with only a non-local label to be merged. */ | |||
1964 | if (stmt) | |||
1965 | if (glabel *label_stmt = dyn_cast <glabel *> (stmt)) | |||
1966 | if (DECL_NONLOCAL (gimple_label_label (label_stmt))((contains_struct_check ((gimple_label_label (label_stmt)), ( TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1966, __FUNCTION__))->decl_common.nonlocal_flag)) | |||
1967 | return false; | |||
1968 | ||||
1969 | /* Examine the labels at the beginning of B. */ | |||
1970 | for (gimple_stmt_iterator gsi = gsi_start_bb (b); !gsi_end_p (gsi); | |||
1971 | gsi_next (&gsi)) | |||
1972 | { | |||
1973 | tree lab; | |||
1974 | glabel *label_stmt = dyn_cast <glabel *> (gsi_stmt (gsi)); | |||
1975 | if (!label_stmt) | |||
1976 | break; | |||
1977 | lab = gimple_label_label (label_stmt); | |||
1978 | ||||
1979 | /* Do not remove user forced labels or for -O0 any user labels. */ | |||
1980 | if (!DECL_ARTIFICIAL (lab)((contains_struct_check ((lab), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1980, __FUNCTION__))->decl_common.artificial_flag) && (!optimizeglobal_options.x_optimize || FORCED_LABEL (lab)((tree_check ((lab), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 1980, __FUNCTION__, (LABEL_DECL)))->base.side_effects_flag ))) | |||
1981 | return false; | |||
1982 | } | |||
1983 | ||||
1984 | /* Protect simple loop latches. We only want to avoid merging | |||
1985 | the latch with the loop header or with a block in another | |||
1986 | loop in this case. */ | |||
1987 | if (current_loops((cfun + 0)->x_current_loops) | |||
1988 | && b->loop_father->latch == b | |||
1989 | && loops_state_satisfies_p (LOOPS_HAVE_SIMPLE_LATCHES) | |||
1990 | && (b->loop_father->header == a | |||
1991 | || b->loop_father != a->loop_father)) | |||
1992 | return false; | |||
1993 | ||||
1994 | /* It must be possible to eliminate all phi nodes in B. If ssa form | |||
1995 | is not up-to-date and a name-mapping is registered, we cannot eliminate | |||
1996 | any phis. Symbols marked for renaming are never a problem though. */ | |||
1997 | for (gphi_iterator gsi = gsi_start_phis (b); !gsi_end_p (gsi); | |||
1998 | gsi_next (&gsi)) | |||
1999 | { | |||
2000 | gphi *phi = gsi.phi (); | |||
2001 | /* Technically only new names matter. */ | |||
2002 | if (name_registered_for_update_p (PHI_RESULT (phi)get_def_from_ptr (gimple_phi_result_ptr (phi)))) | |||
2003 | return false; | |||
2004 | } | |||
2005 | ||||
2006 | /* When not optimizing, don't merge if we'd lose goto_locus. */ | |||
2007 | if (!optimizeglobal_options.x_optimize | |||
2008 | && single_succ_edge (a)->goto_locus != UNKNOWN_LOCATION((location_t) 0)) | |||
2009 | { | |||
2010 | location_t goto_locus = single_succ_edge (a)->goto_locus; | |||
2011 | gimple_stmt_iterator prev, next; | |||
2012 | prev = gsi_last_nondebug_bb (a); | |||
2013 | next = gsi_after_labels (b); | |||
2014 | if (!gsi_end_p (next) && is_gimple_debug (gsi_stmt (next))) | |||
2015 | gsi_next_nondebug (&next); | |||
2016 | if ((gsi_end_p (prev) | |||
2017 | || gimple_location (gsi_stmt (prev)) != goto_locus) | |||
2018 | && (gsi_end_p (next) | |||
2019 | || gimple_location (gsi_stmt (next)) != goto_locus)) | |||
2020 | return false; | |||
2021 | } | |||
2022 | ||||
2023 | return true; | |||
2024 | } | |||
2025 | ||||
2026 | /* Replaces all uses of NAME by VAL. */ | |||
2027 | ||||
2028 | void | |||
2029 | replace_uses_by (tree name, tree val) | |||
2030 | { | |||
2031 | imm_use_iterator imm_iter; | |||
2032 | use_operand_p use; | |||
2033 | gimple *stmt; | |||
2034 | edge e; | |||
2035 | ||||
2036 | FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)for (struct auto_end_imm_use_stmt_traverse auto_end_imm_use_stmt_traverse ((((stmt) = first_imm_use_stmt (&(imm_iter), (name))), & (imm_iter))); !end_imm_use_stmt_p (&(imm_iter)); (void) ( (stmt) = next_imm_use_stmt (&(imm_iter)))) | |||
2037 | { | |||
2038 | /* Mark the block if we change the last stmt in it. */ | |||
2039 | if (cfgcleanup_altered_bbs | |||
2040 | && stmt_ends_bb_p (stmt)) | |||
2041 | bitmap_set_bit (cfgcleanup_altered_bbs, gimple_bb (stmt)->index); | |||
2042 | ||||
2043 | FOR_EACH_IMM_USE_ON_STMT (use, imm_iter)for ((use) = first_imm_use_on_stmt (&(imm_iter)); !end_imm_use_on_stmt_p (&(imm_iter)); (void) ((use) = next_imm_use_on_stmt (& (imm_iter)))) | |||
2044 | { | |||
2045 | replace_exp (use, val); | |||
2046 | ||||
2047 | if (gimple_code (stmt) == GIMPLE_PHI) | |||
2048 | { | |||
2049 | e = gimple_phi_arg_edge (as_a <gphi *> (stmt), | |||
2050 | PHI_ARG_INDEX_FROM_USE (use)phi_arg_index_from_use (use)); | |||
2051 | if (e->flags & EDGE_ABNORMAL | |||
2052 | && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val)(tree_check ((val), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2052, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag) | |||
2053 | { | |||
2054 | /* This can only occur for virtual operands, since | |||
2055 | for the real ones SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name)) | |||
2056 | would prevent replacement. */ | |||
2057 | gcc_checking_assert (virtual_operand_p (name))((void)(!(virtual_operand_p (name)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2057, __FUNCTION__), 0 : 0)); | |||
2058 | SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val)(tree_check ((val), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2058, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag = 1; | |||
2059 | } | |||
2060 | } | |||
2061 | } | |||
2062 | ||||
2063 | if (gimple_code (stmt) != GIMPLE_PHI) | |||
2064 | { | |||
2065 | gimple_stmt_iterator gsi = gsi_for_stmt (stmt); | |||
2066 | gimple *orig_stmt = stmt; | |||
2067 | size_t i; | |||
2068 | ||||
2069 | /* FIXME. It shouldn't be required to keep TREE_CONSTANT | |||
2070 | on ADDR_EXPRs up-to-date on GIMPLE. Propagation will | |||
2071 | only change sth from non-invariant to invariant, and only | |||
2072 | when propagating constants. */ | |||
2073 | if (is_gimple_min_invariant (val)) | |||
2074 | for (i = 0; i < gimple_num_ops (stmt); i++) | |||
2075 | { | |||
2076 | tree op = gimple_op (stmt, i); | |||
2077 | /* Operands may be empty here. For example, the labels | |||
2078 | of a GIMPLE_COND are nulled out following the creation | |||
2079 | of the corresponding CFG edges. */ | |||
2080 | if (op && TREE_CODE (op)((enum tree_code) (op)->base.code) == ADDR_EXPR) | |||
2081 | recompute_tree_invariant_for_addr_expr (op); | |||
2082 | } | |||
2083 | ||||
2084 | if (fold_stmt (&gsi)) | |||
2085 | stmt = gsi_stmt (gsi); | |||
2086 | ||||
2087 | if (maybe_clean_or_replace_eh_stmt (orig_stmt, stmt)) | |||
2088 | gimple_purge_dead_eh_edges (gimple_bb (stmt)); | |||
2089 | ||||
2090 | update_stmt (stmt); | |||
2091 | } | |||
2092 | } | |||
2093 | ||||
2094 | gcc_checking_assert (has_zero_uses (name))((void)(!(has_zero_uses (name)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2094, __FUNCTION__), 0 : 0)); | |||
2095 | ||||
2096 | /* Also update the trees stored in loop structures. */ | |||
2097 | if (current_loops((cfun + 0)->x_current_loops)) | |||
2098 | { | |||
2099 | for (auto loop : loops_list (cfun(cfun + 0), 0)) | |||
2100 | substitute_in_loop_info (loop, name, val); | |||
2101 | } | |||
2102 | } | |||
2103 | ||||
2104 | /* Merge block B into block A. */ | |||
2105 | ||||
2106 | static void | |||
2107 | gimple_merge_blocks (basic_block a, basic_block b) | |||
2108 | { | |||
2109 | gimple_stmt_iterator last, gsi; | |||
2110 | gphi_iterator psi; | |||
2111 | ||||
2112 | if (dump_file) | |||
2113 | fprintf (dump_file, "Merging blocks %d and %d\n", a->index, b->index); | |||
2114 | ||||
2115 | /* Remove all single-valued PHI nodes from block B of the form | |||
2116 | V_i = PHI <V_j> by propagating V_j to all the uses of V_i. */ | |||
2117 | gsi = gsi_last_bb (a); | |||
2118 | for (psi = gsi_start_phis (b); !gsi_end_p (psi); ) | |||
2119 | { | |||
2120 | gimple *phi = gsi_stmt (psi); | |||
2121 | tree def = gimple_phi_result (phi), use = gimple_phi_arg_def (phi, 0); | |||
2122 | gimple *copy; | |||
2123 | bool may_replace_uses = (virtual_operand_p (def) | |||
2124 | || may_propagate_copy (def, use)); | |||
2125 | ||||
2126 | /* In case we maintain loop closed ssa form, do not propagate arguments | |||
2127 | of loop exit phi nodes. */ | |||
2128 | if (current_loops((cfun + 0)->x_current_loops) | |||
2129 | && loops_state_satisfies_p (LOOP_CLOSED_SSA) | |||
2130 | && !virtual_operand_p (def) | |||
2131 | && TREE_CODE (use)((enum tree_code) (use)->base.code) == SSA_NAME | |||
2132 | && a->loop_father != b->loop_father) | |||
2133 | may_replace_uses = false; | |||
2134 | ||||
2135 | if (!may_replace_uses) | |||
2136 | { | |||
2137 | gcc_assert (!virtual_operand_p (def))((void)(!(!virtual_operand_p (def)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2137, __FUNCTION__), 0 : 0)); | |||
2138 | ||||
2139 | /* Note that just emitting the copies is fine -- there is no problem | |||
2140 | with ordering of phi nodes. This is because A is the single | |||
2141 | predecessor of B, therefore results of the phi nodes cannot | |||
2142 | appear as arguments of the phi nodes. */ | |||
2143 | copy = gimple_build_assign (def, use); | |||
2144 | gsi_insert_after (&gsi, copy, GSI_NEW_STMT); | |||
2145 | remove_phi_node (&psi, false); | |||
2146 | } | |||
2147 | else | |||
2148 | { | |||
2149 | /* If we deal with a PHI for virtual operands, we can simply | |||
2150 | propagate these without fussing with folding or updating | |||
2151 | the stmt. */ | |||
2152 | if (virtual_operand_p (def)) | |||
2153 | { | |||
2154 | imm_use_iterator iter; | |||
2155 | use_operand_p use_p; | |||
2156 | gimple *stmt; | |||
2157 | ||||
2158 | FOR_EACH_IMM_USE_STMT (stmt, iter, def)for (struct auto_end_imm_use_stmt_traverse auto_end_imm_use_stmt_traverse ((((stmt) = first_imm_use_stmt (&(iter), (def))), &( iter))); !end_imm_use_stmt_p (&(iter)); (void) ((stmt) = next_imm_use_stmt (&(iter)))) | |||
2159 | FOR_EACH_IMM_USE_ON_STMT (use_p, iter)for ((use_p) = first_imm_use_on_stmt (&(iter)); !end_imm_use_on_stmt_p (&(iter)); (void) ((use_p) = next_imm_use_on_stmt (& (iter)))) | |||
2160 | SET_USE (use_p, use)set_ssa_use_from_ptr (use_p, use); | |||
2161 | ||||
2162 | if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (def)(tree_check ((def), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2162, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag) | |||
2163 | SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use)(tree_check ((use), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2163, __FUNCTION__, (SSA_NAME)))->base.asm_written_flag = 1; | |||
2164 | } | |||
2165 | else | |||
2166 | replace_uses_by (def, use); | |||
2167 | ||||
2168 | remove_phi_node (&psi, true); | |||
2169 | } | |||
2170 | } | |||
2171 | ||||
2172 | /* Ensure that B follows A. */ | |||
2173 | move_block_after (b, a); | |||
2174 | ||||
2175 | gcc_assert (single_succ_edge (a)->flags & EDGE_FALLTHRU)((void)(!(single_succ_edge (a)->flags & EDGE_FALLTHRU) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2175, __FUNCTION__), 0 : 0)); | |||
2176 | gcc_assert (!last_stmt (a) || !stmt_ends_bb_p (last_stmt (a)))((void)(!(!last_stmt (a) || !stmt_ends_bb_p (last_stmt (a))) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2176, __FUNCTION__), 0 : 0)); | |||
2177 | ||||
2178 | /* Remove labels from B and set gimple_bb to A for other statements. */ | |||
2179 | for (gsi = gsi_start_bb (b); !gsi_end_p (gsi);) | |||
2180 | { | |||
2181 | gimple *stmt = gsi_stmt (gsi); | |||
2182 | if (glabel *label_stmt = dyn_cast <glabel *> (stmt)) | |||
2183 | { | |||
2184 | tree label = gimple_label_label (label_stmt); | |||
2185 | int lp_nr; | |||
2186 | ||||
2187 | gsi_remove (&gsi, false); | |||
2188 | ||||
2189 | /* Now that we can thread computed gotos, we might have | |||
2190 | a situation where we have a forced label in block B | |||
2191 | However, the label at the start of block B might still be | |||
2192 | used in other ways (think about the runtime checking for | |||
2193 | Fortran assigned gotos). So we cannot just delete the | |||
2194 | label. Instead we move the label to the start of block A. */ | |||
2195 | if (FORCED_LABEL (label)((tree_check ((label), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2195, __FUNCTION__, (LABEL_DECL)))->base.side_effects_flag )) | |||
2196 | { | |||
2197 | gimple_stmt_iterator dest_gsi = gsi_start_bb (a); | |||
2198 | tree first_label = NULL_TREE(tree) nullptr; | |||
2199 | if (!gsi_end_p (dest_gsi)) | |||
2200 | if (glabel *first_label_stmt | |||
2201 | = dyn_cast <glabel *> (gsi_stmt (dest_gsi))) | |||
2202 | first_label = gimple_label_label (first_label_stmt); | |||
2203 | if (first_label | |||
2204 | && (DECL_NONLOCAL (first_label)((contains_struct_check ((first_label), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2204, __FUNCTION__))->decl_common.nonlocal_flag) | |||
2205 | || EH_LANDING_PAD_NR (first_label)((tree_check ((first_label), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2205, __FUNCTION__, (LABEL_DECL)))->label_decl.eh_landing_pad_nr ) != 0)) | |||
2206 | gsi_insert_after (&dest_gsi, stmt, GSI_NEW_STMT); | |||
2207 | else | |||
2208 | gsi_insert_before (&dest_gsi, stmt, GSI_NEW_STMT); | |||
2209 | } | |||
2210 | /* Other user labels keep around in a form of a debug stmt. */ | |||
2211 | else if (!DECL_ARTIFICIAL (label)((contains_struct_check ((label), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2211, __FUNCTION__))->decl_common.artificial_flag) && MAY_HAVE_DEBUG_BIND_STMTSglobal_options.x_flag_var_tracking_assignments) | |||
2212 | { | |||
2213 | gimple *dbg = gimple_build_debug_bind (label, | |||
2214 | integer_zero_nodeglobal_trees[TI_INTEGER_ZERO], | |||
2215 | stmt); | |||
2216 | gimple_debug_bind_reset_value (dbg); | |||
2217 | gsi_insert_before (&gsi, dbg, GSI_SAME_STMT); | |||
2218 | } | |||
2219 | ||||
2220 | lp_nr = EH_LANDING_PAD_NR (label)((tree_check ((label), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2220, __FUNCTION__, (LABEL_DECL)))->label_decl.eh_landing_pad_nr ); | |||
2221 | if (lp_nr) | |||
2222 | { | |||
2223 | eh_landing_pad lp = get_eh_landing_pad_from_number (lp_nr); | |||
2224 | lp->post_landing_pad = NULLnullptr; | |||
2225 | } | |||
2226 | } | |||
2227 | else | |||
2228 | { | |||
2229 | gimple_set_bb (stmt, a); | |||
2230 | gsi_next (&gsi); | |||
2231 | } | |||
2232 | } | |||
2233 | ||||
2234 | /* When merging two BBs, if their counts are different, the larger count | |||
2235 | is selected as the new bb count. This is to handle inconsistent | |||
2236 | profiles. */ | |||
2237 | if (a->loop_father == b->loop_father) | |||
2238 | { | |||
2239 | a->count = a->count.merge (b->count); | |||
2240 | } | |||
2241 | ||||
2242 | /* Merge the sequences. */ | |||
2243 | last = gsi_last_bb (a); | |||
2244 | gsi_insert_seq_after (&last, bb_seq (b), GSI_NEW_STMT); | |||
2245 | set_bb_seq (b, NULLnullptr); | |||
2246 | ||||
2247 | if (cfgcleanup_altered_bbs) | |||
2248 | bitmap_set_bit (cfgcleanup_altered_bbs, a->index); | |||
2249 | } | |||
2250 | ||||
2251 | ||||
2252 | /* Return the one of two successors of BB that is not reachable by a | |||
2253 | complex edge, if there is one. Else, return BB. We use | |||
2254 | this in optimizations that use post-dominators for their heuristics, | |||
2255 | to catch the cases in C++ where function calls are involved. */ | |||
2256 | ||||
2257 | basic_block | |||
2258 | single_noncomplex_succ (basic_block bb) | |||
2259 | { | |||
2260 | edge e0, e1; | |||
2261 | if (EDGE_COUNT (bb->succs)vec_safe_length (bb->succs) != 2) | |||
2262 | return bb; | |||
2263 | ||||
2264 | e0 = EDGE_SUCC (bb, 0)(*(bb)->succs)[(0)]; | |||
2265 | e1 = EDGE_SUCC (bb, 1)(*(bb)->succs)[(1)]; | |||
2266 | if (e0->flags & EDGE_COMPLEX(EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_PRESERVE )) | |||
2267 | return e1->dest; | |||
2268 | if (e1->flags & EDGE_COMPLEX(EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_PRESERVE )) | |||
2269 | return e0->dest; | |||
2270 | ||||
2271 | return bb; | |||
2272 | } | |||
2273 | ||||
2274 | /* T is CALL_EXPR. Set current_function_calls_* flags. */ | |||
2275 | ||||
2276 | void | |||
2277 | notice_special_calls (gcall *call) | |||
2278 | { | |||
2279 | int flags = gimple_call_flags (call); | |||
2280 | ||||
2281 | if (flags & ECF_MAY_BE_ALLOCA(1 << 5)) | |||
2282 | cfun(cfun + 0)->calls_alloca = true; | |||
2283 | if (flags & ECF_RETURNS_TWICE(1 << 7)) | |||
2284 | cfun(cfun + 0)->calls_setjmp = true; | |||
2285 | } | |||
2286 | ||||
2287 | ||||
2288 | /* Clear flags set by notice_special_calls. Used by dead code removal | |||
2289 | to update the flags. */ | |||
2290 | ||||
2291 | void | |||
2292 | clear_special_calls (void) | |||
2293 | { | |||
2294 | cfun(cfun + 0)->calls_alloca = false; | |||
2295 | cfun(cfun + 0)->calls_setjmp = false; | |||
2296 | } | |||
2297 | ||||
2298 | /* Remove PHI nodes associated with basic block BB and all edges out of BB. */ | |||
2299 | ||||
2300 | static void | |||
2301 | remove_phi_nodes_and_edges_for_unreachable_block (basic_block bb) | |||
2302 | { | |||
2303 | /* Since this block is no longer reachable, we can just delete all | |||
2304 | of its PHI nodes. */ | |||
2305 | remove_phi_nodes (bb); | |||
2306 | ||||
2307 | /* Remove edges to BB's successors. */ | |||
2308 | while (EDGE_COUNT (bb->succs)vec_safe_length (bb->succs) > 0) | |||
2309 | remove_edge (EDGE_SUCC (bb, 0)(*(bb)->succs)[(0)]); | |||
2310 | } | |||
2311 | ||||
2312 | ||||
2313 | /* Remove statements of basic block BB. */ | |||
2314 | ||||
2315 | static void | |||
2316 | remove_bb (basic_block bb) | |||
2317 | { | |||
2318 | gimple_stmt_iterator i; | |||
2319 | ||||
2320 | if (dump_file) | |||
2321 | { | |||
2322 | fprintf (dump_file, "Removing basic block %d\n", bb->index); | |||
2323 | if (dump_flags & TDF_DETAILS) | |||
2324 | { | |||
2325 | dump_bb (dump_file, bb, 0, TDF_BLOCKS); | |||
2326 | fprintf (dump_file, "\n"); | |||
2327 | } | |||
2328 | } | |||
2329 | ||||
2330 | if (current_loops((cfun + 0)->x_current_loops)) | |||
2331 | { | |||
2332 | class loop *loop = bb->loop_father; | |||
2333 | ||||
2334 | /* If a loop gets removed, clean up the information associated | |||
2335 | with it. */ | |||
2336 | if (loop->latch == bb | |||
2337 | || loop->header == bb) | |||
2338 | free_numbers_of_iterations_estimates (loop); | |||
2339 | } | |||
2340 | ||||
2341 | /* Remove all the instructions in the block. */ | |||
2342 | if (bb_seq (bb) != NULLnullptr) | |||
2343 | { | |||
2344 | /* Walk backwards so as to get a chance to substitute all | |||
2345 | released DEFs into debug stmts. See | |||
2346 | eliminate_unnecessary_stmts() in tree-ssa-dce.cc for more | |||
2347 | details. */ | |||
2348 | for (i = gsi_last_bb (bb); !gsi_end_p (i);) | |||
2349 | { | |||
2350 | gimple *stmt = gsi_stmt (i); | |||
2351 | glabel *label_stmt = dyn_cast <glabel *> (stmt); | |||
2352 | if (label_stmt | |||
2353 | && (FORCED_LABEL (gimple_label_label (label_stmt))((tree_check ((gimple_label_label (label_stmt)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2353, __FUNCTION__, (LABEL_DECL)))->base.side_effects_flag ) | |||
2354 | || DECL_NONLOCAL (gimple_label_label (label_stmt))((contains_struct_check ((gimple_label_label (label_stmt)), ( TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2354, __FUNCTION__))->decl_common.nonlocal_flag))) | |||
2355 | { | |||
2356 | basic_block new_bb; | |||
2357 | gimple_stmt_iterator new_gsi; | |||
2358 | ||||
2359 | /* A non-reachable non-local label may still be referenced. | |||
2360 | But it no longer needs to carry the extra semantics of | |||
2361 | non-locality. */ | |||
2362 | if (DECL_NONLOCAL (gimple_label_label (label_stmt))((contains_struct_check ((gimple_label_label (label_stmt)), ( TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2362, __FUNCTION__))->decl_common.nonlocal_flag)) | |||
2363 | { | |||
2364 | DECL_NONLOCAL (gimple_label_label (label_stmt))((contains_struct_check ((gimple_label_label (label_stmt)), ( TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2364, __FUNCTION__))->decl_common.nonlocal_flag) = 0; | |||
2365 | FORCED_LABEL (gimple_label_label (label_stmt))((tree_check ((gimple_label_label (label_stmt)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2365, __FUNCTION__, (LABEL_DECL)))->base.side_effects_flag ) = 1; | |||
2366 | } | |||
2367 | ||||
2368 | new_bb = bb->prev_bb; | |||
2369 | /* Don't move any labels into ENTRY block. */ | |||
2370 | if (new_bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr)) | |||
2371 | { | |||
2372 | new_bb = single_succ (new_bb); | |||
2373 | gcc_assert (new_bb != bb)((void)(!(new_bb != bb) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2373, __FUNCTION__), 0 : 0)); | |||
2374 | } | |||
2375 | if ((unsigned) bb->index < bb_to_omp_idx.length () | |||
2376 | && ((unsigned) new_bb->index >= bb_to_omp_idx.length () | |||
2377 | || (bb_to_omp_idx[bb->index] | |||
2378 | != bb_to_omp_idx[new_bb->index]))) | |||
2379 | { | |||
2380 | /* During cfg pass make sure to put orphaned labels | |||
2381 | into the right OMP region. */ | |||
2382 | unsigned int i; | |||
2383 | int idx; | |||
2384 | new_bb = NULLnullptr; | |||
2385 | FOR_EACH_VEC_ELT (bb_to_omp_idx, i, idx)for (i = 0; (bb_to_omp_idx).iterate ((i), &(idx)); ++(i)) | |||
2386 | if (i >= NUM_FIXED_BLOCKS(2) | |||
2387 | && idx == bb_to_omp_idx[bb->index] | |||
2388 | && i != (unsigned) bb->index) | |||
2389 | { | |||
2390 | new_bb = BASIC_BLOCK_FOR_FN (cfun, i)((*(((cfun + 0))->cfg->x_basic_block_info))[(i)]); | |||
2391 | break; | |||
2392 | } | |||
2393 | if (new_bb == NULLnullptr) | |||
2394 | { | |||
2395 | new_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)(((cfun + 0))->cfg->x_entry_block_ptr)); | |||
2396 | gcc_assert (new_bb != bb)((void)(!(new_bb != bb) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2396, __FUNCTION__), 0 : 0)); | |||
2397 | } | |||
2398 | } | |||
2399 | new_gsi = gsi_after_labels (new_bb); | |||
2400 | gsi_remove (&i, false); | |||
2401 | gsi_insert_before (&new_gsi, stmt, GSI_NEW_STMT); | |||
2402 | } | |||
2403 | else | |||
2404 | { | |||
2405 | /* Release SSA definitions. */ | |||
2406 | release_defs (stmt); | |||
2407 | gsi_remove (&i, true); | |||
2408 | } | |||
2409 | ||||
2410 | if (gsi_end_p (i)) | |||
2411 | i = gsi_last_bb (bb); | |||
2412 | else | |||
2413 | gsi_prev (&i); | |||
2414 | } | |||
2415 | } | |||
2416 | ||||
2417 | if ((unsigned) bb->index < bb_to_omp_idx.length ()) | |||
2418 | bb_to_omp_idx[bb->index] = -1; | |||
2419 | remove_phi_nodes_and_edges_for_unreachable_block (bb); | |||
2420 | bb->il.gimple.seq = NULLnullptr; | |||
2421 | bb->il.gimple.phi_nodes = NULLnullptr; | |||
2422 | } | |||
2423 | ||||
2424 | ||||
2425 | /* Given a basic block BB and a value VAL for use in the final statement | |||
2426 | of the block (if a GIMPLE_COND, GIMPLE_SWITCH, or computed goto), return | |||
2427 | the edge that will be taken out of the block. | |||
2428 | If VAL is NULL_TREE, then the current value of the final statement's | |||
2429 | predicate or index is used. | |||
2430 | If the value does not match a unique edge, NULL is returned. */ | |||
2431 | ||||
2432 | edge | |||
2433 | find_taken_edge (basic_block bb, tree val) | |||
2434 | { | |||
2435 | gimple *stmt; | |||
2436 | ||||
2437 | stmt = last_stmt (bb); | |||
2438 | ||||
2439 | /* Handle ENTRY and EXIT. */ | |||
2440 | if (!stmt) | |||
2441 | return NULLnullptr; | |||
2442 | ||||
2443 | if (gimple_code (stmt) == GIMPLE_COND) | |||
2444 | return find_taken_edge_cond_expr (as_a <gcond *> (stmt), val); | |||
2445 | ||||
2446 | if (gimple_code (stmt) == GIMPLE_SWITCH) | |||
2447 | return find_taken_edge_switch_expr (as_a <gswitch *> (stmt), val); | |||
2448 | ||||
2449 | if (computed_goto_p (stmt)) | |||
2450 | { | |||
2451 | /* Only optimize if the argument is a label, if the argument is | |||
2452 | not a label then we cannot construct a proper CFG. | |||
2453 | ||||
2454 | It may be the case that we only need to allow the LABEL_REF to | |||
2455 | appear inside an ADDR_EXPR, but we also allow the LABEL_REF to | |||
2456 | appear inside a LABEL_EXPR just to be safe. */ | |||
2457 | if (val | |||
2458 | && (TREE_CODE (val)((enum tree_code) (val)->base.code) == ADDR_EXPR || TREE_CODE (val)((enum tree_code) (val)->base.code) == LABEL_EXPR) | |||
2459 | && TREE_CODE (TREE_OPERAND (val, 0))((enum tree_code) ((*((const_cast<tree*> (tree_operand_check ((val), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2459, __FUNCTION__))))))->base.code) == LABEL_DECL) | |||
2460 | return find_taken_edge_computed_goto (bb, TREE_OPERAND (val, 0)(*((const_cast<tree*> (tree_operand_check ((val), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2460, __FUNCTION__)))))); | |||
2461 | } | |||
2462 | ||||
2463 | /* Otherwise we only know the taken successor edge if it's unique. */ | |||
2464 | return single_succ_p (bb) ? single_succ_edge (bb) : NULLnullptr; | |||
2465 | } | |||
2466 | ||||
2467 | /* Given a constant value VAL and the entry block BB to a GOTO_EXPR | |||
2468 | statement, determine which of the outgoing edges will be taken out of the | |||
2469 | block. Return NULL if either edge may be taken. */ | |||
2470 | ||||
2471 | static edge | |||
2472 | find_taken_edge_computed_goto (basic_block bb, tree val) | |||
2473 | { | |||
2474 | basic_block dest; | |||
2475 | edge e = NULLnullptr; | |||
2476 | ||||
2477 | dest = label_to_block (cfun(cfun + 0), val); | |||
2478 | if (dest) | |||
2479 | e = find_edge (bb, dest); | |||
2480 | ||||
2481 | /* It's possible for find_edge to return NULL here on invalid code | |||
2482 | that abuses the labels-as-values extension (e.g. code that attempts to | |||
2483 | jump *between* functions via stored labels-as-values; PR 84136). | |||
2484 | If so, then we simply return that NULL for the edge. | |||
2485 | We don't currently have a way of detecting such invalid code, so we | |||
2486 | can't assert that it was the case when a NULL edge occurs here. */ | |||
2487 | ||||
2488 | return e; | |||
2489 | } | |||
2490 | ||||
2491 | /* Given COND_STMT and a constant value VAL for use as the predicate, | |||
2492 | determine which of the two edges will be taken out of | |||
2493 | the statement's block. Return NULL if either edge may be taken. | |||
2494 | If VAL is NULL_TREE, then the current value of COND_STMT's predicate | |||
2495 | is used. */ | |||
2496 | ||||
2497 | static edge | |||
2498 | find_taken_edge_cond_expr (const gcond *cond_stmt, tree val) | |||
2499 | { | |||
2500 | edge true_edge, false_edge; | |||
2501 | ||||
2502 | if (val == NULL_TREE(tree) nullptr) | |||
2503 | { | |||
2504 | /* Use the current value of the predicate. */ | |||
2505 | if (gimple_cond_true_p (cond_stmt)) | |||
2506 | val = integer_one_nodeglobal_trees[TI_INTEGER_ONE]; | |||
2507 | else if (gimple_cond_false_p (cond_stmt)) | |||
2508 | val = integer_zero_nodeglobal_trees[TI_INTEGER_ZERO]; | |||
2509 | else | |||
2510 | return NULLnullptr; | |||
2511 | } | |||
2512 | else if (TREE_CODE (val)((enum tree_code) (val)->base.code) != INTEGER_CST) | |||
2513 | return NULLnullptr; | |||
2514 | ||||
2515 | extract_true_false_edges_from_block (gimple_bb (cond_stmt), | |||
2516 | &true_edge, &false_edge); | |||
2517 | ||||
2518 | return (integer_zerop (val) ? false_edge : true_edge); | |||
2519 | } | |||
2520 | ||||
2521 | /* Given SWITCH_STMT and an INTEGER_CST VAL for use as the index, determine | |||
2522 | which edge will be taken out of the statement's block. Return NULL if any | |||
2523 | edge may be taken. | |||
2524 | If VAL is NULL_TREE, then the current value of SWITCH_STMT's index | |||
2525 | is used. */ | |||
2526 | ||||
2527 | edge | |||
2528 | find_taken_edge_switch_expr (const gswitch *switch_stmt, tree val) | |||
2529 | { | |||
2530 | basic_block dest_bb; | |||
2531 | edge e; | |||
2532 | tree taken_case; | |||
2533 | ||||
2534 | if (gimple_switch_num_labels (switch_stmt) == 1) | |||
2535 | taken_case = gimple_switch_default_label (switch_stmt); | |||
2536 | else | |||
2537 | { | |||
2538 | if (val == NULL_TREE(tree) nullptr) | |||
2539 | val = gimple_switch_index (switch_stmt); | |||
2540 | if (TREE_CODE (val)((enum tree_code) (val)->base.code) != INTEGER_CST) | |||
2541 | return NULLnullptr; | |||
2542 | else | |||
2543 | taken_case = find_case_label_for_value (switch_stmt, val); | |||
2544 | } | |||
2545 | dest_bb = label_to_block (cfun(cfun + 0), CASE_LABEL (taken_case)(*((const_cast<tree*> (tree_operand_check (((tree_check ((taken_case), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2545, __FUNCTION__, (CASE_LABEL_EXPR)))), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2545, __FUNCTION__)))))); | |||
2546 | ||||
2547 | e = find_edge (gimple_bb (switch_stmt), dest_bb); | |||
2548 | gcc_assert (e)((void)(!(e) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2548, __FUNCTION__), 0 : 0)); | |||
2549 | return e; | |||
2550 | } | |||
2551 | ||||
2552 | ||||
2553 | /* Return the CASE_LABEL_EXPR that SWITCH_STMT will take for VAL. | |||
2554 | We can make optimal use here of the fact that the case labels are | |||
2555 | sorted: We can do a binary search for a case matching VAL. */ | |||
2556 | ||||
2557 | tree | |||
2558 | find_case_label_for_value (const gswitch *switch_stmt, tree val) | |||
2559 | { | |||
2560 | size_t low, high, n = gimple_switch_num_labels (switch_stmt); | |||
2561 | tree default_case = gimple_switch_default_label (switch_stmt); | |||
2562 | ||||
2563 | for (low = 0, high = n; high - low > 1; ) | |||
2564 | { | |||
2565 | size_t i = (high + low) / 2; | |||
2566 | tree t = gimple_switch_label (switch_stmt, i); | |||
2567 | int cmp; | |||
2568 | ||||
2569 | /* Cache the result of comparing CASE_LOW and val. */ | |||
2570 | cmp = tree_int_cst_compare (CASE_LOW (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2570, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2570, __FUNCTION__))))), val); | |||
2571 | ||||
2572 | if (cmp > 0) | |||
2573 | high = i; | |||
2574 | else | |||
2575 | low = i; | |||
2576 | ||||
2577 | if (CASE_HIGH (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2577, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2577, __FUNCTION__))))) == NULLnullptr) | |||
2578 | { | |||
2579 | /* A singe-valued case label. */ | |||
2580 | if (cmp == 0) | |||
2581 | return t; | |||
2582 | } | |||
2583 | else | |||
2584 | { | |||
2585 | /* A case range. We can only handle integer ranges. */ | |||
2586 | if (cmp <= 0 && tree_int_cst_compare (CASE_HIGH (t)(*((const_cast<tree*> (tree_operand_check (((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2586, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2586, __FUNCTION__))))), val) >= 0) | |||
2587 | return t; | |||
2588 | } | |||
2589 | } | |||
2590 | ||||
2591 | return default_case; | |||
2592 | } | |||
2593 | ||||
2594 | ||||
2595 | /* Dump a basic block on stderr. */ | |||
2596 | ||||
2597 | void | |||
2598 | gimple_debug_bb (basic_block bb) | |||
2599 | { | |||
2600 | dump_bb (stderrstderr, bb, 0, TDF_VOPS|TDF_MEMSYMS|TDF_BLOCKS); | |||
2601 | } | |||
2602 | ||||
2603 | ||||
2604 | /* Dump basic block with index N on stderr. */ | |||
2605 | ||||
2606 | basic_block | |||
2607 | gimple_debug_bb_n (int n) | |||
2608 | { | |||
2609 | gimple_debug_bb (BASIC_BLOCK_FOR_FN (cfun, n)((*(((cfun + 0))->cfg->x_basic_block_info))[(n)])); | |||
2610 | return BASIC_BLOCK_FOR_FN (cfun, n)((*(((cfun + 0))->cfg->x_basic_block_info))[(n)]); | |||
2611 | } | |||
2612 | ||||
2613 | ||||
2614 | /* Dump the CFG on stderr. | |||
2615 | ||||
2616 | FLAGS are the same used by the tree dumping functions | |||
2617 | (see TDF_* in dumpfile.h). */ | |||
2618 | ||||
2619 | void | |||
2620 | gimple_debug_cfg (dump_flags_t flags) | |||
2621 | { | |||
2622 | gimple_dump_cfg (stderrstderr, flags); | |||
2623 | } | |||
2624 | ||||
2625 | ||||
2626 | /* Dump the program showing basic block boundaries on the given FILE. | |||
2627 | ||||
2628 | FLAGS are the same used by the tree dumping functions (see TDF_* in | |||
2629 | tree.h). */ | |||
2630 | ||||
2631 | void | |||
2632 | gimple_dump_cfg (FILE *file, dump_flags_t flags) | |||
2633 | { | |||
2634 | if (flags & TDF_DETAILS) | |||
2635 | { | |||
2636 | dump_function_header (file, current_function_decl, flags); | |||
2637 | fprintf (file, ";; \n%d basic blocks, %d edges, last basic block %d.\n\n", | |||
2638 | n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks), n_edges_for_fn (cfun)(((cfun + 0))->cfg->x_n_edges), | |||
2639 | last_basic_block_for_fn (cfun)(((cfun + 0))->cfg->x_last_basic_block)); | |||
2640 | ||||
2641 | brief_dump_cfg (file, flags); | |||
2642 | fprintf (file, "\n"); | |||
2643 | } | |||
2644 | ||||
2645 | if (flags & TDF_STATS) | |||
2646 | dump_cfg_stats (file); | |||
2647 | ||||
2648 | dump_function_to_file (current_function_decl, file, flags | TDF_BLOCKS); | |||
2649 | } | |||
2650 | ||||
2651 | ||||
2652 | /* Dump CFG statistics on FILE. */ | |||
2653 | ||||
2654 | void | |||
2655 | dump_cfg_stats (FILE *file) | |||
2656 | { | |||
2657 | static long max_num_merged_labels = 0; | |||
2658 | unsigned long size, total = 0; | |||
2659 | long num_edges; | |||
2660 | basic_block bb; | |||
2661 | const char * const fmt_str = "%-30s%-13s%12s\n"; | |||
2662 | const char * const fmt_str_1 = "%-30s%13d" PRsa (11)"%" "11" "l" "u" "%c" "\n"; | |||
2663 | const char * const fmt_str_2 = "%-30s%13ld" PRsa (11)"%" "11" "l" "u" "%c" "\n"; | |||
2664 | const char * const fmt_str_3 = "%-43s" PRsa (11)"%" "11" "l" "u" "%c" "\n"; | |||
2665 | const char *funcname = current_function_name (); | |||
2666 | ||||
2667 | fprintf (file, "\nCFG Statistics for %s\n\n", funcname); | |||
2668 | ||||
2669 | fprintf (file, "---------------------------------------------------------\n"); | |||
2670 | fprintf (file, fmt_str, "", " Number of ", "Memory"); | |||
2671 | fprintf (file, fmt_str, "", " instances ", "used "); | |||
2672 | fprintf (file, "---------------------------------------------------------\n"); | |||
2673 | ||||
2674 | size = n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks) * sizeof (struct basic_block_def); | |||
2675 | total += size; | |||
2676 | fprintf (file, fmt_str_1, "Basic blocks", n_basic_blocks_for_fn (cfun)(((cfun + 0))->cfg->x_n_basic_blocks), | |||
2677 | SIZE_AMOUNT (size)(uint64_t)(((size) < 10 * 1024 ? (size) : ((size) < 10 * (1024 * 1024) ? (size) / 1024 : (size) / (1024 * 1024)))), ( (size) < 10 * 1024 ? ' ' : ((size) < 10 * (1024 * 1024) ? 'k' : 'M'))); | |||
2678 | ||||
2679 | num_edges = 0; | |||
2680 | FOR_EACH_BB_FN (bb, cfun)for (bb = ((cfun + 0))->cfg->x_entry_block_ptr->next_bb ; bb != ((cfun + 0))->cfg->x_exit_block_ptr; bb = bb-> next_bb) | |||
2681 | num_edges += EDGE_COUNT (bb->succs)vec_safe_length (bb->succs); | |||
2682 | size = num_edges * sizeof (class edge_def); | |||
2683 | total += size; | |||
2684 | fprintf (file, fmt_str_2, "Edges", num_edges, SIZE_AMOUNT (size)(uint64_t)(((size) < 10 * 1024 ? (size) : ((size) < 10 * (1024 * 1024) ? (size) / 1024 : (size) / (1024 * 1024)))), ( (size) < 10 * 1024 ? ' ' : ((size) < 10 * (1024 * 1024) ? 'k' : 'M'))); | |||
2685 | ||||
2686 | fprintf (file, "---------------------------------------------------------\n"); | |||
2687 | fprintf (file, fmt_str_3, "Total memory used by CFG data", | |||
2688 | SIZE_AMOUNT (total)(uint64_t)(((total) < 10 * 1024 ? (total) : ((total) < 10 * (1024 * 1024) ? (total) / 1024 : (total) / (1024 * 1024))) ), ((total) < 10 * 1024 ? ' ' : ((total) < 10 * (1024 * 1024) ? 'k' : 'M'))); | |||
2689 | fprintf (file, "---------------------------------------------------------\n"); | |||
2690 | fprintf (file, "\n"); | |||
2691 | ||||
2692 | if (cfg_stats.num_merged_labels > max_num_merged_labels) | |||
2693 | max_num_merged_labels = cfg_stats.num_merged_labels; | |||
2694 | ||||
2695 | fprintf (file, "Coalesced label blocks: %ld (Max so far: %ld)\n", | |||
2696 | cfg_stats.num_merged_labels, max_num_merged_labels); | |||
2697 | ||||
2698 | fprintf (file, "\n"); | |||
2699 | } | |||
2700 | ||||
2701 | ||||
2702 | /* Dump CFG statistics on stderr. Keep extern so that it's always | |||
2703 | linked in the final executable. */ | |||
2704 | ||||
2705 | DEBUG_FUNCTION__attribute__ ((__used__)) void | |||
2706 | debug_cfg_stats (void) | |||
2707 | { | |||
2708 | dump_cfg_stats (stderrstderr); | |||
2709 | } | |||
2710 | ||||
2711 | /*--------------------------------------------------------------------------- | |||
2712 | Miscellaneous helpers | |||
2713 | ---------------------------------------------------------------------------*/ | |||
2714 | ||||
2715 | /* Return true if T, a GIMPLE_CALL, can make an abnormal transfer of control | |||
2716 | flow. Transfers of control flow associated with EH are excluded. */ | |||
2717 | ||||
2718 | static bool | |||
2719 | call_can_make_abnormal_goto (gimple *t) | |||
2720 | { | |||
2721 | /* If the function has no non-local labels, then a call cannot make an | |||
2722 | abnormal transfer of control. */ | |||
2723 | if (!cfun(cfun + 0)->has_nonlocal_label | |||
2724 | && !cfun(cfun + 0)->calls_setjmp) | |||
2725 | return false; | |||
2726 | ||||
2727 | /* Likewise if the call has no side effects. */ | |||
2728 | if (!gimple_has_side_effects (t)) | |||
2729 | return false; | |||
2730 | ||||
2731 | /* Likewise if the called function is leaf. */ | |||
2732 | if (gimple_call_flags (t) & ECF_LEAF(1 << 10)) | |||
2733 | return false; | |||
2734 | ||||
2735 | return true; | |||
2736 | } | |||
2737 | ||||
2738 | ||||
2739 | /* Return true if T can make an abnormal transfer of control flow. | |||
2740 | Transfers of control flow associated with EH are excluded. */ | |||
2741 | ||||
2742 | bool | |||
2743 | stmt_can_make_abnormal_goto (gimple *t) | |||
2744 | { | |||
2745 | if (computed_goto_p (t)) | |||
2746 | return true; | |||
2747 | if (is_gimple_call (t)) | |||
2748 | return call_can_make_abnormal_goto (t); | |||
2749 | return false; | |||
2750 | } | |||
2751 | ||||
2752 | ||||
2753 | /* Return true if T represents a stmt that always transfers control. */ | |||
2754 | ||||
2755 | bool | |||
2756 | is_ctrl_stmt (gimple *t) | |||
2757 | { | |||
2758 | switch (gimple_code (t)) | |||
2759 | { | |||
2760 | case GIMPLE_COND: | |||
2761 | case GIMPLE_SWITCH: | |||
2762 | case GIMPLE_GOTO: | |||
2763 | case GIMPLE_RETURN: | |||
2764 | case GIMPLE_RESX: | |||
2765 | return true; | |||
2766 | default: | |||
2767 | return false; | |||
2768 | } | |||
2769 | } | |||
2770 | ||||
2771 | ||||
2772 | /* Return true if T is a statement that may alter the flow of control | |||
2773 | (e.g., a call to a non-returning function). */ | |||
2774 | ||||
2775 | bool | |||
2776 | is_ctrl_altering_stmt (gimple *t) | |||
2777 | { | |||
2778 | gcc_assert (t)((void)(!(t) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2778, __FUNCTION__), 0 : 0)); | |||
2779 | ||||
2780 | switch (gimple_code (t)) | |||
2781 | { | |||
2782 | case GIMPLE_CALL: | |||
2783 | /* Per stmt call flag indicates whether the call could alter | |||
2784 | controlflow. */ | |||
2785 | if (gimple_call_ctrl_altering_p (t)) | |||
2786 | return true; | |||
2787 | break; | |||
2788 | ||||
2789 | case GIMPLE_EH_DISPATCH: | |||
2790 | /* EH_DISPATCH branches to the individual catch handlers at | |||
2791 | this level of a try or allowed-exceptions region. It can | |||
2792 | fallthru to the next statement as well. */ | |||
2793 | return true; | |||
2794 | ||||
2795 | case GIMPLE_ASM: | |||
2796 | if (gimple_asm_nlabels (as_a <gasm *> (t)) > 0) | |||
2797 | return true; | |||
2798 | break; | |||
2799 | ||||
2800 | CASE_GIMPLE_OMPcase GIMPLE_OMP_PARALLEL: case GIMPLE_OMP_TASK: case GIMPLE_OMP_FOR : case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SECTIONS_SWITCH: case GIMPLE_OMP_SINGLE: case GIMPLE_OMP_TARGET: case GIMPLE_OMP_TEAMS : case GIMPLE_OMP_SCOPE: case GIMPLE_OMP_SECTION: case GIMPLE_OMP_MASTER : case GIMPLE_OMP_MASKED: case GIMPLE_OMP_TASKGROUP: case GIMPLE_OMP_ORDERED : case GIMPLE_OMP_CRITICAL: case GIMPLE_OMP_SCAN: case GIMPLE_OMP_RETURN : case GIMPLE_OMP_ATOMIC_LOAD: case GIMPLE_OMP_ATOMIC_STORE: case GIMPLE_OMP_CONTINUE: | |||
2801 | /* OpenMP directives alter control flow. */ | |||
2802 | return true; | |||
2803 | ||||
2804 | case GIMPLE_TRANSACTION: | |||
2805 | /* A transaction start alters control flow. */ | |||
2806 | return true; | |||
2807 | ||||
2808 | default: | |||
2809 | break; | |||
2810 | } | |||
2811 | ||||
2812 | /* If a statement can throw, it alters control flow. */ | |||
2813 | return stmt_can_throw_internal (cfun(cfun + 0), t); | |||
2814 | } | |||
2815 | ||||
2816 | ||||
2817 | /* Return true if T is a simple local goto. */ | |||
2818 | ||||
2819 | bool | |||
2820 | simple_goto_p (gimple *t) | |||
2821 | { | |||
2822 | return (gimple_code (t) == GIMPLE_GOTO | |||
2823 | && TREE_CODE (gimple_goto_dest (t))((enum tree_code) (gimple_goto_dest (t))->base.code) == LABEL_DECL); | |||
2824 | } | |||
2825 | ||||
2826 | ||||
2827 | /* Return true if STMT should start a new basic block. PREV_STMT is | |||
2828 | the statement preceding STMT. It is used when STMT is a label or a | |||
2829 | case label. Labels should only start a new basic block if their | |||
2830 | previous statement wasn't a label. Otherwise, sequence of labels | |||
2831 | would generate unnecessary basic blocks that only contain a single | |||
2832 | label. */ | |||
2833 | ||||
2834 | static inline bool | |||
2835 | stmt_starts_bb_p (gimple *stmt, gimple *prev_stmt) | |||
2836 | { | |||
2837 | if (stmt == NULLnullptr) | |||
2838 | return false; | |||
2839 | ||||
2840 | /* PREV_STMT is only set to a debug stmt if the debug stmt is before | |||
2841 | any nondebug stmts in the block. We don't want to start another | |||
2842 | block in this case: the debug stmt will already have started the | |||
2843 | one STMT would start if we weren't outputting debug stmts. */ | |||
2844 | if (prev_stmt && is_gimple_debug (prev_stmt)) | |||
2845 | return false; | |||
2846 | ||||
2847 | /* Labels start a new basic block only if the preceding statement | |||
2848 | wasn't a label of the same type. This prevents the creation of | |||
2849 | consecutive blocks that have nothing but a single label. */ | |||
2850 | if (glabel *label_stmt = dyn_cast <glabel *> (stmt)) | |||
2851 | { | |||
2852 | /* Nonlocal and computed GOTO targets always start a new block. */ | |||
2853 | if (DECL_NONLOCAL (gimple_label_label (label_stmt))((contains_struct_check ((gimple_label_label (label_stmt)), ( TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2853, __FUNCTION__))->decl_common.nonlocal_flag) | |||
2854 | || FORCED_LABEL (gimple_label_label (label_stmt))((tree_check ((gimple_label_label (label_stmt)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2854, __FUNCTION__, (LABEL_DECL)))->base.side_effects_flag )) | |||
2855 | return true; | |||
2856 | ||||
2857 | if (glabel *plabel = safe_dyn_cast <glabel *> (prev_stmt)) | |||
2858 | { | |||
2859 | if (DECL_NONLOCAL (gimple_label_label (plabel))((contains_struct_check ((gimple_label_label (plabel)), (TS_DECL_COMMON ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2859, __FUNCTION__))->decl_common.nonlocal_flag) | |||
2860 | || !DECL_ARTIFICIAL (gimple_label_label (plabel))((contains_struct_check ((gimple_label_label (plabel)), (TS_DECL_COMMON ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 2860, __FUNCTION__))->decl_common.artificial_flag)) | |||
2861 | return true; | |||
2862 | ||||
2863 | cfg_stats.num_merged_labels++; | |||
2864 | return false; | |||
2865 | } | |||
2866 | else | |||
2867 | return true; | |||
2868 | } | |||
2869 | else if (gimple_code (stmt) == GIMPLE_CALL) | |||
2870 | { | |||
2871 | if (gimple_call_flags (stmt) & ECF_RETURNS_TWICE(1 << 7)) | |||
2872 | /* setjmp acts similar to a nonlocal GOTO target and thus should | |||
2873 | start a new block. */ | |||
2874 | return true; | |||
2875 | if (gimple_call_internal_p (stmt, IFN_PHI) | |||
2876 | && prev_stmt | |||
2877 | && gimple_code (prev_stmt) != GIMPLE_LABEL | |||
2878 | && (gimple_code (prev_stmt) != GIMPLE_CALL | |||
2879 | || ! gimple_call_internal_p (prev_stmt, IFN_PHI))) | |||
2880 | /* PHI nodes start a new block unless preceeded by a label | |||
2881 | or another PHI. */ | |||
2882 | return true; | |||
2883 | } | |||
2884 | ||||
2885 | return false; | |||
2886 | } | |||
2887 | ||||
2888 | ||||
2889 | /* Return true if T should end a basic block. */ | |||
2890 | ||||
2891 | bool | |||
2892 | stmt_ends_bb_p (gimple *t) | |||
2893 | { | |||
2894 | return is_ctrl_stmt (t) || is_ctrl_altering_stmt (t); | |||
2895 | } | |||
2896 | ||||
2897 | /* Remove block annotations and other data structures. */ | |||
2898 | ||||
2899 | void | |||
2900 | delete_tree_cfg_annotations (struct function *fn) | |||
2901 | { | |||
2902 | vec_free (label_to_block_map_for_fn (fn)((fn)->cfg->x_label_to_block_map)); | |||
2903 | } | |||
2904 | ||||
2905 | /* Return the virtual phi in BB. */ | |||
2906 | ||||
2907 | gphi * | |||
2908 | get_virtual_phi (basic_block bb) | |||
2909 | { | |||
2910 | for (gphi_iterator gsi = gsi_start_phis (bb); | |||
2911 | !gsi_end_p (gsi); | |||
2912 | gsi_next (&gsi)) | |||
2913 | { | |||
2914 | gphi *phi = gsi.phi (); | |||
2915 | ||||
2916 | if (virtual_operand_p (PHI_RESULT (phi)get_def_from_ptr (gimple_phi_result_ptr (phi)))) | |||
2917 | return phi; | |||
2918 | } | |||
2919 | ||||
2920 | return NULLnullptr; | |||
2921 | } | |||
2922 | ||||
2923 | /* Return the first statement in basic block BB. */ | |||
2924 | ||||
2925 | gimple * | |||
2926 | first_stmt (basic_block bb) | |||
2927 | { | |||
2928 | gimple_stmt_iterator i = gsi_start_bb (bb); | |||
2929 | gimple *stmt = NULLnullptr; | |||
2930 | ||||
2931 | while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i)))) | |||
2932 | { | |||
2933 | gsi_next (&i); | |||
2934 | stmt = NULLnullptr; | |||
2935 | } | |||
2936 | return stmt; | |||
2937 | } | |||
2938 | ||||
2939 | /* Return the first non-label statement in basic block BB. */ | |||
2940 | ||||
2941 | static gimple * | |||
2942 | first_non_label_stmt (basic_block bb) | |||
2943 | { | |||
2944 | gimple_stmt_iterator i = gsi_start_bb (bb); | |||
2945 | while (!gsi_end_p (i) && gimple_code (gsi_stmt (i)) == GIMPLE_LABEL) | |||
2946 | gsi_next (&i); | |||
2947 | return !gsi_end_p (i) ? gsi_stmt (i) : NULLnullptr; | |||
2948 | } | |||
2949 | ||||
2950 | /* Return the last statement in basic block BB. */ | |||
2951 | ||||
2952 | gimple * | |||
2953 | last_stmt (basic_block bb) | |||
2954 | { | |||
2955 | gimple_stmt_iterator i = gsi_last_bb (bb); | |||
2956 | gimple *stmt = NULLnullptr; | |||
2957 | ||||
2958 | while (!gsi_end_p (i) && is_gimple_debug ((stmt = gsi_stmt (i)))) | |||
2959 | { | |||
2960 | gsi_prev (&i); | |||
2961 | stmt = NULLnullptr; | |||
2962 | } | |||
2963 | return stmt; | |||
2964 | } | |||
2965 | ||||
2966 | /* Return the last statement of an otherwise empty block. Return NULL | |||
2967 | if the block is totally empty, or if it contains more than one | |||
2968 | statement. */ | |||
2969 | ||||
2970 | gimple * | |||
2971 | last_and_only_stmt (basic_block bb) | |||
2972 | { | |||
2973 | gimple_stmt_iterator i = gsi_last_nondebug_bb (bb); | |||
2974 | gimple *last, *prev; | |||
2975 | ||||
2976 | if (gsi_end_p (i)) | |||
2977 | return NULLnullptr; | |||
2978 | ||||
2979 | last = gsi_stmt (i); | |||
2980 | gsi_prev_nondebug (&i); | |||
2981 | if (gsi_end_p (i)) | |||
2982 | return last; | |||
2983 | ||||
2984 | /* Empty statements should no longer appear in the instruction stream. | |||
2985 | Everything that might have appeared before should be deleted by | |||
2986 | remove_useless_stmts, and the optimizers should just gsi_remove | |||
2987 | instead of smashing with build_empty_stmt. | |||
2988 | ||||
2989 | Thus the only thing that should appear here in a block containing | |||
2990 | one executable statement is a label. */ | |||
2991 | prev = gsi_stmt (i); | |||
2992 | if (gimple_code (prev) == GIMPLE_LABEL) | |||
2993 | return last; | |||
2994 | else | |||
2995 | return NULLnullptr; | |||
2996 | } | |||
2997 | ||||
2998 | /* Returns the basic block after which the new basic block created | |||
2999 | by splitting edge EDGE_IN should be placed. Tries to keep the new block | |||
3000 | near its "logical" location. This is of most help to humans looking | |||
3001 | at debugging dumps. */ | |||
3002 | ||||
3003 | basic_block | |||
3004 | split_edge_bb_loc (edge edge_in) | |||
3005 | { | |||
3006 | basic_block dest = edge_in->dest; | |||
3007 | basic_block dest_prev = dest->prev_bb; | |||
3008 | ||||
3009 | if (dest_prev) | |||
3010 | { | |||
3011 | edge e = find_edge (dest_prev, dest); | |||
3012 | if (e && !(e->flags & EDGE_COMPLEX(EDGE_ABNORMAL | EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_PRESERVE ))) | |||
3013 | return edge_in->src; | |||
3014 | } | |||
3015 | return dest_prev; | |||
3016 | } | |||
3017 | ||||
3018 | /* Split a (typically critical) edge EDGE_IN. Return the new block. | |||
3019 | Abort on abnormal edges. */ | |||
3020 | ||||
3021 | static basic_block | |||
3022 | gimple_split_edge (edge edge_in) | |||
3023 | { | |||
3024 | basic_block new_bb, after_bb, dest; | |||
3025 | edge new_edge, e; | |||
3026 | ||||
3027 | /* Abnormal edges cannot be split. */ | |||
3028 | gcc_assert (!(edge_in->flags & EDGE_ABNORMAL))((void)(!(!(edge_in->flags & EDGE_ABNORMAL)) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3028, __FUNCTION__), 0 : 0)); | |||
3029 | ||||
3030 | dest = edge_in->dest; | |||
3031 | ||||
3032 | after_bb = split_edge_bb_loc (edge_in); | |||
3033 | ||||
3034 | new_bb = create_empty_bb (after_bb); | |||
3035 | new_bb->count = edge_in->count (); | |||
3036 | ||||
3037 | /* We want to avoid re-allocating PHIs when we first | |||
3038 | add the fallthru edge from new_bb to dest but we also | |||
3039 | want to avoid changing PHI argument order when | |||
3040 | first redirecting edge_in away from dest. The former | |||
3041 | avoids changing PHI argument order by adding them | |||
3042 | last and then the redirection swapping it back into | |||
3043 | place by means of unordered remove. | |||
3044 | So hack around things by temporarily removing all PHIs | |||
3045 | from the destination during the edge redirection and then | |||
3046 | making sure the edges stay in order. */ | |||
3047 | gimple_seq saved_phis = phi_nodes (dest); | |||
3048 | unsigned old_dest_idx = edge_in->dest_idx; | |||
3049 | set_phi_nodes (dest, NULLnullptr); | |||
3050 | new_edge = make_single_succ_edge (new_bb, dest, EDGE_FALLTHRU); | |||
3051 | e = redirect_edge_and_branch (edge_in, new_bb); | |||
3052 | gcc_assert (e == edge_in && new_edge->dest_idx == old_dest_idx)((void)(!(e == edge_in && new_edge->dest_idx == old_dest_idx ) ? fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3052, __FUNCTION__), 0 : 0)); | |||
3053 | /* set_phi_nodes sets the BB of the PHI nodes, so do it manually here. */ | |||
3054 | dest->il.gimple.phi_nodes = saved_phis; | |||
3055 | ||||
3056 | return new_bb; | |||
3057 | } | |||
3058 | ||||
3059 | ||||
3060 | /* Verify properties of the address expression T whose base should be | |||
3061 | TREE_ADDRESSABLE if VERIFY_ADDRESSABLE is true. */ | |||
3062 | ||||
3063 | static bool | |||
3064 | verify_address (tree t, bool verify_addressable) | |||
3065 | { | |||
3066 | bool old_constant; | |||
3067 | bool old_side_effects; | |||
3068 | bool new_constant; | |||
3069 | bool new_side_effects; | |||
3070 | ||||
3071 | old_constant = TREE_CONSTANT (t)((non_type_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3071, __FUNCTION__))->base.constant_flag); | |||
3072 | old_side_effects = TREE_SIDE_EFFECTS (t)((non_type_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3072, __FUNCTION__))->base.side_effects_flag); | |||
3073 | ||||
3074 | recompute_tree_invariant_for_addr_expr (t); | |||
3075 | new_side_effects = TREE_SIDE_EFFECTS (t)((non_type_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3075, __FUNCTION__))->base.side_effects_flag); | |||
3076 | new_constant = TREE_CONSTANT (t)((non_type_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3076, __FUNCTION__))->base.constant_flag); | |||
3077 | ||||
3078 | if (old_constant != new_constant) | |||
3079 | { | |||
3080 | error ("constant not recomputed when %<ADDR_EXPR%> changed"); | |||
3081 | return true; | |||
3082 | } | |||
3083 | if (old_side_effects != new_side_effects) | |||
3084 | { | |||
3085 | error ("side effects not recomputed when %<ADDR_EXPR%> changed"); | |||
3086 | return true; | |||
3087 | } | |||
3088 | ||||
3089 | tree base = TREE_OPERAND (t, 0)(*((const_cast<tree*> (tree_operand_check ((t), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3089, __FUNCTION__))))); | |||
3090 | while (handled_component_p (base)) | |||
3091 | base = TREE_OPERAND (base, 0)(*((const_cast<tree*> (tree_operand_check ((base), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3091, __FUNCTION__))))); | |||
3092 | ||||
3093 | if (!(VAR_P (base)(((enum tree_code) (base)->base.code) == VAR_DECL) | |||
3094 | || TREE_CODE (base)((enum tree_code) (base)->base.code) == PARM_DECL | |||
3095 | || TREE_CODE (base)((enum tree_code) (base)->base.code) == RESULT_DECL)) | |||
3096 | return false; | |||
3097 | ||||
3098 | if (verify_addressable && !TREE_ADDRESSABLE (base)((base)->base.addressable_flag)) | |||
3099 | { | |||
3100 | error ("address taken but %<TREE_ADDRESSABLE%> bit not set"); | |||
3101 | return true; | |||
3102 | } | |||
3103 | ||||
3104 | return false; | |||
3105 | } | |||
3106 | ||||
3107 | ||||
3108 | /* Verify if EXPR is a valid GIMPLE reference expression. If | |||
3109 | REQUIRE_LVALUE is true verifies it is an lvalue. Returns true | |||
3110 | if there is an error, otherwise false. */ | |||
3111 | ||||
3112 | static bool | |||
3113 | verify_types_in_gimple_reference (tree expr, bool require_lvalue) | |||
3114 | { | |||
3115 | const char *code_name = get_tree_code_name (TREE_CODE (expr)((enum tree_code) (expr)->base.code)); | |||
3116 | ||||
3117 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == REALPART_EXPR | |||
3118 | || TREE_CODE (expr)((enum tree_code) (expr)->base.code) == IMAGPART_EXPR | |||
3119 | || TREE_CODE (expr)((enum tree_code) (expr)->base.code) == BIT_FIELD_REF) | |||
3120 | { | |||
3121 | tree op = TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3121, __FUNCTION__))))); | |||
3122 | if (!is_gimple_reg_type (TREE_TYPE (expr)((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3122, __FUNCTION__))->typed.type))) | |||
3123 | { | |||
3124 | error ("non-scalar %qs", code_name); | |||
3125 | return true; | |||
3126 | } | |||
3127 | ||||
3128 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == BIT_FIELD_REF) | |||
3129 | { | |||
3130 | tree t1 = TREE_OPERAND (expr, 1)(*((const_cast<tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3130, __FUNCTION__))))); | |||
3131 | tree t2 = TREE_OPERAND (expr, 2)(*((const_cast<tree*> (tree_operand_check ((expr), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3131, __FUNCTION__))))); | |||
3132 | poly_uint64 size, bitpos; | |||
3133 | if (!poly_int_tree_p (t1, &size) | |||
3134 | || !poly_int_tree_p (t2, &bitpos) | |||
3135 | || !types_compatible_p (bitsizetypesizetype_tab[(int) stk_bitsizetype], TREE_TYPE (t1)((contains_struct_check ((t1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3135, __FUNCTION__))->typed.type)) | |||
3136 | || !types_compatible_p (bitsizetypesizetype_tab[(int) stk_bitsizetype], TREE_TYPE (t2)((contains_struct_check ((t2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3136, __FUNCTION__))->typed.type))) | |||
3137 | { | |||
3138 | error ("invalid position or size operand to %qs", code_name); | |||
3139 | return true; | |||
3140 | } | |||
3141 | if (INTEGRAL_TYPE_P (TREE_TYPE (expr))(((enum tree_code) (((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3141, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3141, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3141, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3142 | && maybe_ne (TYPE_PRECISION (TREE_TYPE (expr))((tree_class_check ((((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3142, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3142, __FUNCTION__))->type_common.precision), size)) | |||
3143 | { | |||
3144 | error ("integral result type precision does not match " | |||
3145 | "field size of %qs", code_name); | |||
3146 | return true; | |||
3147 | } | |||
3148 | else if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))(((enum tree_code) (((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3148, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3148, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3148, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3149 | && TYPE_MODE (TREE_TYPE (expr))((((enum tree_code) ((tree_class_check ((((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3149, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3149, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3149, __FUNCTION__))->typed.type)) : (((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3149, __FUNCTION__))->typed.type))->type_common.mode) != BLKmode((void) 0, E_BLKmode) | |||
3150 | && maybe_ne (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (expr))((((enum tree_code) ((tree_class_check ((((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3150, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3150, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3150, __FUNCTION__))->typed.type)) : (((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3150, __FUNCTION__))->typed.type))->type_common.mode)), | |||
3151 | size)) | |||
3152 | { | |||
3153 | error ("mode size of non-integral result does not " | |||
3154 | "match field size of %qs", | |||
3155 | code_name); | |||
3156 | return true; | |||
3157 | } | |||
3158 | if (INTEGRAL_TYPE_P (TREE_TYPE (op))(((enum tree_code) (((contains_struct_check ((op), (TS_TYPED) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3158, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3158, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3158, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3159 | && !type_has_mode_precision_p (TREE_TYPE (op)((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3159, __FUNCTION__))->typed.type))) | |||
3160 | { | |||
3161 | error ("%qs of non-mode-precision operand", code_name); | |||
3162 | return true; | |||
3163 | } | |||
3164 | if (!AGGREGATE_TYPE_P (TREE_TYPE (op))(((enum tree_code) (((contains_struct_check ((op), (TS_TYPED) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3164, __FUNCTION__))->typed.type))->base.code) == ARRAY_TYPE || (((enum tree_code) (((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3164, __FUNCTION__))->typed.type))->base.code) == RECORD_TYPE || ((enum tree_code) (((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3164, __FUNCTION__))->typed.type))->base.code) == UNION_TYPE || ((enum tree_code) (((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3164, __FUNCTION__))->typed.type))->base.code) == QUAL_UNION_TYPE )) | |||
3165 | && maybe_gt (size + bitpos,maybe_lt (tree_to_poly_uint64 (((tree_class_check ((((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3166, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3166, __FUNCTION__))->type_common.size)), size + bitpos) | |||
3166 | tree_to_poly_uint64 (TYPE_SIZE (TREE_TYPE (op))))maybe_lt (tree_to_poly_uint64 (((tree_class_check ((((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3166, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3166, __FUNCTION__))->type_common.size)), size + bitpos)) | |||
3167 | { | |||
3168 | error ("position plus size exceeds size of referenced object in " | |||
3169 | "%qs", code_name); | |||
3170 | return true; | |||
3171 | } | |||
3172 | } | |||
3173 | ||||
3174 | if ((TREE_CODE (expr)((enum tree_code) (expr)->base.code) == REALPART_EXPR | |||
3175 | || TREE_CODE (expr)((enum tree_code) (expr)->base.code) == IMAGPART_EXPR) | |||
3176 | && !useless_type_conversion_p (TREE_TYPE (expr)((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3176, __FUNCTION__))->typed.type), | |||
3177 | TREE_TYPE (TREE_TYPE (op))((contains_struct_check ((((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3177, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3177, __FUNCTION__))->typed.type))) | |||
3178 | { | |||
3179 | error ("type mismatch in %qs reference", code_name); | |||
3180 | debug_generic_stmt (TREE_TYPE (expr)((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3180, __FUNCTION__))->typed.type)); | |||
3181 | debug_generic_stmt (TREE_TYPE (TREE_TYPE (op))((contains_struct_check ((((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3181, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3181, __FUNCTION__))->typed.type)); | |||
3182 | return true; | |||
3183 | } | |||
3184 | expr = op; | |||
3185 | } | |||
3186 | ||||
3187 | while (handled_component_p (expr)) | |||
3188 | { | |||
3189 | code_name = get_tree_code_name (TREE_CODE (expr)((enum tree_code) (expr)->base.code)); | |||
3190 | ||||
3191 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == REALPART_EXPR | |||
3192 | || TREE_CODE (expr)((enum tree_code) (expr)->base.code) == IMAGPART_EXPR | |||
3193 | || TREE_CODE (expr)((enum tree_code) (expr)->base.code) == BIT_FIELD_REF) | |||
3194 | { | |||
3195 | error ("non-top-level %qs", code_name); | |||
3196 | return true; | |||
3197 | } | |||
3198 | ||||
3199 | tree op = TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3199, __FUNCTION__))))); | |||
3200 | ||||
3201 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == ARRAY_REF | |||
3202 | || TREE_CODE (expr)((enum tree_code) (expr)->base.code) == ARRAY_RANGE_REF) | |||
3203 | { | |||
3204 | if (!is_gimple_val (TREE_OPERAND (expr, 1)(*((const_cast<tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3204, __FUNCTION__)))))) | |||
3205 | || (TREE_OPERAND (expr, 2)(*((const_cast<tree*> (tree_operand_check ((expr), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3205, __FUNCTION__))))) | |||
3206 | && !is_gimple_val (TREE_OPERAND (expr, 2)(*((const_cast<tree*> (tree_operand_check ((expr), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3206, __FUNCTION__))))))) | |||
3207 | || (TREE_OPERAND (expr, 3)(*((const_cast<tree*> (tree_operand_check ((expr), (3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3207, __FUNCTION__))))) | |||
3208 | && !is_gimple_val (TREE_OPERAND (expr, 3)(*((const_cast<tree*> (tree_operand_check ((expr), (3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3208, __FUNCTION__)))))))) | |||
3209 | { | |||
3210 | error ("invalid operands to %qs", code_name); | |||
3211 | debug_generic_stmt (expr); | |||
3212 | return true; | |||
3213 | } | |||
3214 | } | |||
3215 | ||||
3216 | /* Verify if the reference array element types are compatible. */ | |||
3217 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == ARRAY_REF | |||
3218 | && !useless_type_conversion_p (TREE_TYPE (expr)((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3218, __FUNCTION__))->typed.type), | |||
3219 | TREE_TYPE (TREE_TYPE (op))((contains_struct_check ((((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3219, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3219, __FUNCTION__))->typed.type))) | |||
3220 | { | |||
3221 | error ("type mismatch in %qs", code_name); | |||
3222 | debug_generic_stmt (TREE_TYPE (expr)((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3222, __FUNCTION__))->typed.type)); | |||
3223 | debug_generic_stmt (TREE_TYPE (TREE_TYPE (op))((contains_struct_check ((((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3223, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3223, __FUNCTION__))->typed.type)); | |||
3224 | return true; | |||
3225 | } | |||
3226 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == ARRAY_RANGE_REF | |||
3227 | && !useless_type_conversion_p (TREE_TYPE (TREE_TYPE (expr))((contains_struct_check ((((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3227, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3227, __FUNCTION__))->typed.type), | |||
3228 | TREE_TYPE (TREE_TYPE (op))((contains_struct_check ((((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3228, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3228, __FUNCTION__))->typed.type))) | |||
3229 | { | |||
3230 | error ("type mismatch in %qs", code_name); | |||
3231 | debug_generic_stmt (TREE_TYPE (TREE_TYPE (expr))((contains_struct_check ((((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3231, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3231, __FUNCTION__))->typed.type)); | |||
3232 | debug_generic_stmt (TREE_TYPE (TREE_TYPE (op))((contains_struct_check ((((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3232, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3232, __FUNCTION__))->typed.type)); | |||
3233 | return true; | |||
3234 | } | |||
3235 | ||||
3236 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == COMPONENT_REF) | |||
3237 | { | |||
3238 | if (TREE_OPERAND (expr, 2)(*((const_cast<tree*> (tree_operand_check ((expr), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3238, __FUNCTION__))))) | |||
3239 | && !is_gimple_val (TREE_OPERAND (expr, 2)(*((const_cast<tree*> (tree_operand_check ((expr), (2), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3239, __FUNCTION__))))))) | |||
3240 | { | |||
3241 | error ("invalid %qs offset operator", code_name); | |||
3242 | return true; | |||
3243 | } | |||
3244 | if (!useless_type_conversion_p (TREE_TYPE (expr)((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3244, __FUNCTION__))->typed.type), | |||
3245 | TREE_TYPE (TREE_OPERAND (expr, 1))((contains_struct_check (((*((const_cast<tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3245, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3245, __FUNCTION__))->typed.type))) | |||
3246 | { | |||
3247 | error ("type mismatch in %qs", code_name); | |||
3248 | debug_generic_stmt (TREE_TYPE (expr)((contains_struct_check ((expr), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3248, __FUNCTION__))->typed.type)); | |||
3249 | debug_generic_stmt (TREE_TYPE (TREE_OPERAND (expr, 1))((contains_struct_check (((*((const_cast<tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3249, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3249, __FUNCTION__))->typed.type)); | |||
3250 | return true; | |||
3251 | } | |||
3252 | } | |||
3253 | ||||
3254 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == VIEW_CONVERT_EXPR) | |||
3255 | { | |||
3256 | /* For VIEW_CONVERT_EXPRs which are allowed here too, we only check | |||
3257 | that their operand is not an SSA name or an invariant when | |||
3258 | requiring an lvalue (this usually means there is a SRA or IPA-SRA | |||
3259 | bug). Otherwise there is nothing to verify, gross mismatches at | |||
3260 | most invoke undefined behavior. */ | |||
3261 | if (require_lvalue | |||
3262 | && (TREE_CODE (op)((enum tree_code) (op)->base.code) == SSA_NAME | |||
3263 | || is_gimple_min_invariant (op))) | |||
3264 | { | |||
3265 | error ("conversion of %qs on the left hand side of %qs", | |||
3266 | get_tree_code_name (TREE_CODE (op)((enum tree_code) (op)->base.code)), code_name); | |||
3267 | debug_generic_stmt (expr); | |||
3268 | return true; | |||
3269 | } | |||
3270 | else if (TREE_CODE (op)((enum tree_code) (op)->base.code) == SSA_NAME | |||
3271 | && TYPE_SIZE (TREE_TYPE (expr))((tree_class_check ((((contains_struct_check ((expr), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3271, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3271, __FUNCTION__))->type_common.size) != TYPE_SIZE (TREE_TYPE (op))((tree_class_check ((((contains_struct_check ((op), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3271, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3271, __FUNCTION__))->type_common.size)) | |||
3272 | { | |||
3273 | error ("conversion of register to a different size in %qs", | |||
3274 | code_name); | |||
3275 | debug_generic_stmt (expr); | |||
3276 | return true; | |||
3277 | } | |||
3278 | else if (!handled_component_p (op)) | |||
3279 | return false; | |||
3280 | } | |||
3281 | ||||
3282 | expr = op; | |||
3283 | } | |||
3284 | ||||
3285 | code_name = get_tree_code_name (TREE_CODE (expr)((enum tree_code) (expr)->base.code)); | |||
3286 | ||||
3287 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == MEM_REF) | |||
3288 | { | |||
3289 | if (!is_gimple_mem_ref_addr (TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3289, __FUNCTION__)))))) | |||
3290 | || (TREE_CODE (TREE_OPERAND (expr, 0))((enum tree_code) ((*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3290, __FUNCTION__))))))->base.code) == ADDR_EXPR | |||
3291 | && verify_address (TREE_OPERAND (expr, 0)(*((const_cast<tree*> (tree_operand_check ((expr), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3291, __FUNCTION__))))), false))) | |||
3292 | { | |||
3293 | error ("invalid address operand in %qs", code_name); | |||
3294 | debug_generic_stmt (expr); | |||
3295 | return true; | |||
3296 | } | |||
3297 | if (!poly_int_tree_p (TREE_OPERAND (expr, 1)(*((const_cast<tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3297, __FUNCTION__)))))) | |||
3298 | || !POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 1)))(((enum tree_code) (((contains_struct_check (((*((const_cast< tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3298, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3298, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check (((*((const_cast <tree*> (tree_operand_check ((expr), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3298, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3298, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | |||
3299 | { | |||
3300 | error ("invalid offset operand in %qs", code_name); | |||
3301 | debug_generic_stmt (expr); | |||
3302 | return true; | |||
3303 | } | |||
3304 | if (MR_DEPENDENCE_CLIQUE (expr)((tree_check2 ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3304, __FUNCTION__, (MEM_REF), (TARGET_MEM_REF)))->base. u.dependence_info.clique) != 0 | |||
3305 | && MR_DEPENDENCE_CLIQUE (expr)((tree_check2 ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3305, __FUNCTION__, (MEM_REF), (TARGET_MEM_REF)))->base. u.dependence_info.clique) > cfun(cfun + 0)->last_clique) | |||
3306 | { | |||
3307 | error ("invalid clique in %qs", code_name); | |||
3308 | debug_generic_stmt (expr); | |||
3309 | return true; | |||
3310 | } | |||
3311 | } | |||
3312 | else if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == TARGET_MEM_REF) | |||
3313 | { | |||
3314 | if (!TMR_BASE (expr)((*((const_cast<tree*> (tree_operand_check (((tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3314, __FUNCTION__, (TARGET_MEM_REF)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3314, __FUNCTION__)))))) | |||
3315 | || !is_gimple_mem_ref_addr (TMR_BASE (expr)((*((const_cast<tree*> (tree_operand_check (((tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3315, __FUNCTION__, (TARGET_MEM_REF)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3315, __FUNCTION__))))))) | |||
3316 | || (TREE_CODE (TMR_BASE (expr))((enum tree_code) (((*((const_cast<tree*> (tree_operand_check (((tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3316, __FUNCTION__, (TARGET_MEM_REF)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3316, __FUNCTION__)))))))->base.code) == ADDR_EXPR | |||
3317 | && verify_address (TMR_BASE (expr)((*((const_cast<tree*> (tree_operand_check (((tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3317, __FUNCTION__, (TARGET_MEM_REF)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3317, __FUNCTION__)))))), false))) | |||
3318 | { | |||
3319 | error ("invalid address operand in %qs", code_name); | |||
3320 | return true; | |||
3321 | } | |||
3322 | if (!TMR_OFFSET (expr)((*((const_cast<tree*> (tree_operand_check (((tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3322, __FUNCTION__, (TARGET_MEM_REF)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3322, __FUNCTION__)))))) | |||
3323 | || !poly_int_tree_p (TMR_OFFSET (expr)((*((const_cast<tree*> (tree_operand_check (((tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3323, __FUNCTION__, (TARGET_MEM_REF)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3323, __FUNCTION__))))))) | |||
3324 | || !POINTER_TYPE_P (TREE_TYPE (TMR_OFFSET (expr)))(((enum tree_code) (((contains_struct_check ((((*((const_cast <tree*> (tree_operand_check (((tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3324, __FUNCTION__, (TARGET_MEM_REF)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3324, __FUNCTION__))))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3324, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((((*((const_cast <tree*> (tree_operand_check (((tree_check ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3324, __FUNCTION__, (TARGET_MEM_REF)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3324, __FUNCTION__))))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3324, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE )) | |||
3325 | { | |||
3326 | error ("invalid offset operand in %qs", code_name); | |||
3327 | debug_generic_stmt (expr); | |||
3328 | return true; | |||
3329 | } | |||
3330 | if (MR_DEPENDENCE_CLIQUE (expr)((tree_check2 ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3330, __FUNCTION__, (MEM_REF), (TARGET_MEM_REF)))->base. u.dependence_info.clique) != 0 | |||
3331 | && MR_DEPENDENCE_CLIQUE (expr)((tree_check2 ((expr), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3331, __FUNCTION__, (MEM_REF), (TARGET_MEM_REF)))->base. u.dependence_info.clique) > cfun(cfun + 0)->last_clique) | |||
3332 | { | |||
3333 | error ("invalid clique in %qs", code_name); | |||
3334 | debug_generic_stmt (expr); | |||
3335 | return true; | |||
3336 | } | |||
3337 | } | |||
3338 | else if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == INDIRECT_REF) | |||
3339 | { | |||
3340 | error ("%qs in gimple IL", code_name); | |||
3341 | debug_generic_stmt (expr); | |||
3342 | return true; | |||
3343 | } | |||
3344 | ||||
3345 | if (!require_lvalue | |||
3346 | && (TREE_CODE (expr)((enum tree_code) (expr)->base.code) == SSA_NAME || is_gimple_min_invariant (expr))) | |||
3347 | return false; | |||
3348 | ||||
3349 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) != SSA_NAME && is_gimple_id (expr)) | |||
3350 | return false; | |||
3351 | ||||
3352 | if (TREE_CODE (expr)((enum tree_code) (expr)->base.code) != TARGET_MEM_REF | |||
3353 | && TREE_CODE (expr)((enum tree_code) (expr)->base.code) != MEM_REF) | |||
3354 | { | |||
3355 | error ("invalid expression for min lvalue"); | |||
3356 | return true; | |||
3357 | } | |||
3358 | ||||
3359 | return false; | |||
3360 | } | |||
3361 | ||||
3362 | /* Returns true if there is one pointer type in TYPE_POINTER_TO (SRC_OBJ) | |||
3363 | list of pointer-to types that is trivially convertible to DEST. */ | |||
3364 | ||||
3365 | static bool | |||
3366 | one_pointer_to_useless_type_conversion_p (tree dest, tree src_obj) | |||
3367 | { | |||
3368 | tree src; | |||
3369 | ||||
3370 | if (!TYPE_POINTER_TO (src_obj)((tree_class_check ((src_obj), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3370, __FUNCTION__))->type_common.pointer_to)) | |||
3371 | return true; | |||
3372 | ||||
3373 | for (src = TYPE_POINTER_TO (src_obj)((tree_class_check ((src_obj), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3373, __FUNCTION__))->type_common.pointer_to); src; src = TYPE_NEXT_PTR_TO (src)((tree_check ((src), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3373, __FUNCTION__, (POINTER_TYPE)))->type_non_common.minval )) | |||
3374 | if (useless_type_conversion_p (dest, src)) | |||
3375 | return true; | |||
3376 | ||||
3377 | return false; | |||
3378 | } | |||
3379 | ||||
3380 | /* Return true if TYPE1 is a fixed-point type and if conversions to and | |||
3381 | from TYPE2 can be handled by FIXED_CONVERT_EXPR. */ | |||
3382 | ||||
3383 | static bool | |||
3384 | valid_fixed_convert_types_p (tree type1, tree type2) | |||
3385 | { | |||
3386 | return (FIXED_POINT_TYPE_P (type1)(((enum tree_code) (type1)->base.code) == FIXED_POINT_TYPE ) | |||
3387 | && (INTEGRAL_TYPE_P (type2)(((enum tree_code) (type2)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (type2)->base.code) == BOOLEAN_TYPE || ( (enum tree_code) (type2)->base.code) == INTEGER_TYPE) | |||
3388 | || SCALAR_FLOAT_TYPE_P (type2)(((enum tree_code) (type2)->base.code) == REAL_TYPE) | |||
3389 | || FIXED_POINT_TYPE_P (type2)(((enum tree_code) (type2)->base.code) == FIXED_POINT_TYPE ))); | |||
3390 | } | |||
3391 | ||||
3392 | /* Verify the contents of a GIMPLE_CALL STMT. Returns true when there | |||
3393 | is a problem, otherwise false. */ | |||
3394 | ||||
3395 | static bool | |||
3396 | verify_gimple_call (gcall *stmt) | |||
3397 | { | |||
3398 | tree fn = gimple_call_fn (stmt); | |||
3399 | tree fntype, fndecl; | |||
3400 | unsigned i; | |||
3401 | ||||
3402 | if (gimple_call_internal_p (stmt)) | |||
3403 | { | |||
3404 | if (fn) | |||
3405 | { | |||
3406 | error ("gimple call has two targets"); | |||
3407 | debug_generic_stmt (fn); | |||
3408 | return true; | |||
3409 | } | |||
3410 | } | |||
3411 | else | |||
3412 | { | |||
3413 | if (!fn) | |||
3414 | { | |||
3415 | error ("gimple call has no target"); | |||
3416 | return true; | |||
3417 | } | |||
3418 | } | |||
3419 | ||||
3420 | if (fn && !is_gimple_call_addr (fn)) | |||
3421 | { | |||
3422 | error ("invalid function in gimple call"); | |||
3423 | debug_generic_stmt (fn); | |||
3424 | return true; | |||
3425 | } | |||
3426 | ||||
3427 | if (fn | |||
3428 | && (!POINTER_TYPE_P (TREE_TYPE (fn))(((enum tree_code) (((contains_struct_check ((fn), (TS_TYPED) , "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3428, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((fn), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3428, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE ) | |||
3429 | || (TREE_CODE (TREE_TYPE (TREE_TYPE (fn)))((enum tree_code) (((contains_struct_check ((((contains_struct_check ((fn), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3429, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3429, __FUNCTION__))->typed.type))->base.code) != FUNCTION_TYPE | |||
3430 | && TREE_CODE (TREE_TYPE (TREE_TYPE (fn)))((enum tree_code) (((contains_struct_check ((((contains_struct_check ((fn), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3430, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3430, __FUNCTION__))->typed.type))->base.code) != METHOD_TYPE))) | |||
3431 | { | |||
3432 | error ("non-function in gimple call"); | |||
3433 | return true; | |||
3434 | } | |||
3435 | ||||
3436 | fndecl = gimple_call_fndecl (stmt); | |||
3437 | if (fndecl | |||
3438 | && TREE_CODE (fndecl)((enum tree_code) (fndecl)->base.code) == FUNCTION_DECL | |||
3439 | && DECL_LOOPING_CONST_OR_PURE_P (fndecl)((tree_check ((fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3439, __FUNCTION__, (FUNCTION_DECL)))->function_decl.looping_const_or_pure_flag ) | |||
3440 | && !DECL_PURE_P (fndecl)((tree_check ((fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3440, __FUNCTION__, (FUNCTION_DECL)))->function_decl.pure_flag ) | |||
3441 | && !TREE_READONLY (fndecl)((non_type_check ((fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3441, __FUNCTION__))->base.readonly_flag)) | |||
3442 | { | |||
3443 | error ("invalid pure const state for function"); | |||
3444 | return true; | |||
3445 | } | |||
3446 | ||||
3447 | tree lhs = gimple_call_lhs (stmt); | |||
3448 | if (lhs | |||
3449 | && (!is_gimple_reg (lhs) | |||
3450 | && (!is_gimple_lvalue (lhs) | |||
3451 | || verify_types_in_gimple_reference | |||
3452 | (TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) == WITH_SIZE_EXPR | |||
3453 | ? TREE_OPERAND (lhs, 0)(*((const_cast<tree*> (tree_operand_check ((lhs), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3453, __FUNCTION__))))) : lhs, true)))) | |||
3454 | { | |||
3455 | error ("invalid LHS in gimple call"); | |||
3456 | return true; | |||
3457 | } | |||
3458 | ||||
3459 | if (gimple_call_ctrl_altering_p (stmt) | |||
3460 | && gimple_call_noreturn_p (stmt) | |||
3461 | && should_remove_lhs_p (lhs)) | |||
3462 | { | |||
3463 | error ("LHS in %<noreturn%> call"); | |||
3464 | return true; | |||
3465 | } | |||
3466 | ||||
3467 | fntype = gimple_call_fntype (stmt); | |||
3468 | if (fntype | |||
3469 | && lhs | |||
3470 | && !useless_type_conversion_p (TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3470, __FUNCTION__))->typed.type), TREE_TYPE (fntype)((contains_struct_check ((fntype), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3470, __FUNCTION__))->typed.type)) | |||
3471 | /* ??? At least C++ misses conversions at assignments from | |||
3472 | void * call results. | |||
3473 | For now simply allow arbitrary pointer type conversions. */ | |||
3474 | && !(POINTER_TYPE_P (TREE_TYPE (lhs))(((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3474, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((lhs), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3474, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE ) | |||
3475 | && POINTER_TYPE_P (TREE_TYPE (fntype))(((enum tree_code) (((contains_struct_check ((fntype), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3475, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((fntype), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3475, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE ))) | |||
3476 | { | |||
3477 | error ("invalid conversion in gimple call"); | |||
3478 | debug_generic_stmt (TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3478, __FUNCTION__))->typed.type)); | |||
3479 | debug_generic_stmt (TREE_TYPE (fntype)((contains_struct_check ((fntype), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3479, __FUNCTION__))->typed.type)); | |||
3480 | return true; | |||
3481 | } | |||
3482 | ||||
3483 | if (gimple_call_chain (stmt) | |||
3484 | && !is_gimple_val (gimple_call_chain (stmt))) | |||
3485 | { | |||
3486 | error ("invalid static chain in gimple call"); | |||
3487 | debug_generic_stmt (gimple_call_chain (stmt)); | |||
3488 | return true; | |||
3489 | } | |||
3490 | ||||
3491 | /* If there is a static chain argument, the call should either be | |||
3492 | indirect, or the decl should have DECL_STATIC_CHAIN set. */ | |||
3493 | if (gimple_call_chain (stmt) | |||
3494 | && fndecl | |||
3495 | && !DECL_STATIC_CHAIN (fndecl)((tree_check ((fndecl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3495, __FUNCTION__, (FUNCTION_DECL)))->decl_with_vis.regdecl_flag )) | |||
3496 | { | |||
3497 | error ("static chain with function that doesn%'t use one"); | |||
3498 | return true; | |||
3499 | } | |||
3500 | ||||
3501 | if (fndecl && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL)) | |||
3502 | { | |||
3503 | switch (DECL_FUNCTION_CODE (fndecl)) | |||
3504 | { | |||
3505 | case BUILT_IN_UNREACHABLE: | |||
3506 | case BUILT_IN_UNREACHABLE_TRAP: | |||
3507 | case BUILT_IN_TRAP: | |||
3508 | if (gimple_call_num_args (stmt) > 0) | |||
3509 | { | |||
3510 | /* Built-in unreachable with parameters might not be caught by | |||
3511 | undefined behavior sanitizer. Front-ends do check users do not | |||
3512 | call them that way but we also produce calls to | |||
3513 | __builtin_unreachable internally, for example when IPA figures | |||
3514 | out a call cannot happen in a legal program. In such cases, | |||
3515 | we must make sure arguments are stripped off. */ | |||
3516 | error ("%<__builtin_unreachable%> or %<__builtin_trap%> call " | |||
3517 | "with arguments"); | |||
3518 | return true; | |||
3519 | } | |||
3520 | break; | |||
3521 | default: | |||
3522 | break; | |||
3523 | } | |||
3524 | } | |||
3525 | ||||
3526 | /* For a call to .DEFERRED_INIT, | |||
3527 | LHS = DEFERRED_INIT (SIZE of the DECL, INIT_TYPE, NAME of the DECL) | |||
3528 | we should guarantee that when the 1st argument is a constant, it should | |||
3529 | be the same as the size of the LHS. */ | |||
3530 | ||||
3531 | if (gimple_call_internal_p (stmt, IFN_DEFERRED_INIT)) | |||
3532 | { | |||
3533 | tree size_of_arg0 = gimple_call_arg (stmt, 0); | |||
3534 | tree size_of_lhs = TYPE_SIZE_UNIT (TREE_TYPE (lhs))((tree_class_check ((((contains_struct_check ((lhs), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3534, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3534, __FUNCTION__))->type_common.size_unit); | |||
3535 | ||||
3536 | if (TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) == SSA_NAME) | |||
3537 | lhs = SSA_NAME_VAR (lhs)((tree_check ((lhs), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3537, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((lhs)->ssa_name.var)->base .code) == IDENTIFIER_NODE ? (tree) nullptr : (lhs)->ssa_name .var); | |||
3538 | ||||
3539 | poly_uint64 size_from_arg0, size_from_lhs; | |||
3540 | bool is_constant_size_arg0 = poly_int_tree_p (size_of_arg0, | |||
3541 | &size_from_arg0); | |||
3542 | bool is_constant_size_lhs = poly_int_tree_p (size_of_lhs, | |||
3543 | &size_from_lhs); | |||
3544 | if (is_constant_size_arg0 && is_constant_size_lhs) | |||
3545 | if (maybe_ne (size_from_arg0, size_from_lhs)) | |||
3546 | { | |||
3547 | error ("%<DEFERRED_INIT%> calls should have same " | |||
3548 | "constant size for the first argument and LHS"); | |||
3549 | return true; | |||
3550 | } | |||
3551 | } | |||
3552 | ||||
3553 | /* ??? The C frontend passes unpromoted arguments in case it | |||
3554 | didn't see a function declaration before the call. So for now | |||
3555 | leave the call arguments mostly unverified. Once we gimplify | |||
3556 | unit-at-a-time we have a chance to fix this. */ | |||
3557 | for (i = 0; i < gimple_call_num_args (stmt); ++i) | |||
3558 | { | |||
3559 | tree arg = gimple_call_arg (stmt, i); | |||
3560 | if ((is_gimple_reg_type (TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3560, __FUNCTION__))->typed.type)) | |||
3561 | && !is_gimple_val (arg)) | |||
3562 | || (!is_gimple_reg_type (TREE_TYPE (arg)((contains_struct_check ((arg), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3562, __FUNCTION__))->typed.type)) | |||
3563 | && !is_gimple_lvalue (arg))) | |||
3564 | { | |||
3565 | error ("invalid argument to gimple call"); | |||
3566 | debug_generic_expr (arg); | |||
3567 | return true; | |||
3568 | } | |||
3569 | if (!is_gimple_reg (arg)) | |||
3570 | { | |||
3571 | if (TREE_CODE (arg)((enum tree_code) (arg)->base.code) == WITH_SIZE_EXPR) | |||
3572 | arg = TREE_OPERAND (arg, 0)(*((const_cast<tree*> (tree_operand_check ((arg), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3572, __FUNCTION__))))); | |||
3573 | if (verify_types_in_gimple_reference (arg, false)) | |||
3574 | return true; | |||
3575 | } | |||
3576 | } | |||
3577 | ||||
3578 | return false; | |||
3579 | } | |||
3580 | ||||
3581 | /* Verifies the gimple comparison with the result type TYPE and | |||
3582 | the operands OP0 and OP1, comparison code is CODE. */ | |||
3583 | ||||
3584 | static bool | |||
3585 | verify_gimple_comparison (tree type, tree op0, tree op1, enum tree_code code) | |||
3586 | { | |||
3587 | tree op0_type = TREE_TYPE (op0)((contains_struct_check ((op0), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3587, __FUNCTION__))->typed.type); | |||
3588 | tree op1_type = TREE_TYPE (op1)((contains_struct_check ((op1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3588, __FUNCTION__))->typed.type); | |||
3589 | ||||
3590 | if (!is_gimple_val (op0) || !is_gimple_val (op1)) | |||
3591 | { | |||
3592 | error ("invalid operands in gimple comparison"); | |||
3593 | return true; | |||
3594 | } | |||
3595 | ||||
3596 | /* For comparisons we do not have the operations type as the | |||
3597 | effective type the comparison is carried out in. Instead | |||
3598 | we require that either the first operand is trivially | |||
3599 | convertible into the second, or the other way around. */ | |||
3600 | if (!useless_type_conversion_p (op0_type, op1_type) | |||
3601 | && !useless_type_conversion_p (op1_type, op0_type)) | |||
3602 | { | |||
3603 | error ("mismatching comparison operand types"); | |||
3604 | debug_generic_expr (op0_type); | |||
3605 | debug_generic_expr (op1_type); | |||
3606 | return true; | |||
3607 | } | |||
3608 | ||||
3609 | /* The resulting type of a comparison may be an effective boolean type. */ | |||
3610 | if (INTEGRAL_TYPE_P (type)(((enum tree_code) (type)->base.code) == ENUMERAL_TYPE || ( (enum tree_code) (type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (type)->base.code) == INTEGER_TYPE) | |||
3611 | && (TREE_CODE (type)((enum tree_code) (type)->base.code) == BOOLEAN_TYPE | |||
3612 | || TYPE_PRECISION (type)((tree_class_check ((type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3612, __FUNCTION__))->type_common.precision) == 1)) | |||
3613 | { | |||
3614 | if ((TREE_CODE (op0_type)((enum tree_code) (op0_type)->base.code) == VECTOR_TYPE | |||
3615 | || TREE_CODE (op1_type)((enum tree_code) (op1_type)->base.code) == VECTOR_TYPE) | |||
3616 | && code != EQ_EXPR && code != NE_EXPR | |||
3617 | && !VECTOR_BOOLEAN_TYPE_P (op0_type)(((enum tree_code) (op0_type)->base.code) == VECTOR_TYPE && ((enum tree_code) (((contains_struct_check ((op0_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3617, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE ) | |||
3618 | && !VECTOR_INTEGER_TYPE_P (op0_type)((((enum tree_code) (op0_type)->base.code) == VECTOR_TYPE) && ((enum tree_code) (((contains_struct_check ((op0_type ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3618, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE )) | |||
3619 | { | |||
3620 | error ("unsupported operation or type for vector comparison" | |||
3621 | " returning a boolean"); | |||
3622 | debug_generic_expr (op0_type); | |||
3623 | debug_generic_expr (op1_type); | |||
3624 | return true; | |||
3625 | } | |||
3626 | } | |||
3627 | /* Or a boolean vector type with the same element count | |||
3628 | as the comparison operand types. */ | |||
3629 | else if (TREE_CODE (type)((enum tree_code) (type)->base.code) == VECTOR_TYPE | |||
3630 | && TREE_CODE (TREE_TYPE (type))((enum tree_code) (((contains_struct_check ((type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3630, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE) | |||
3631 | { | |||
3632 | if (TREE_CODE (op0_type)((enum tree_code) (op0_type)->base.code) != VECTOR_TYPE | |||
3633 | || TREE_CODE (op1_type)((enum tree_code) (op1_type)->base.code) != VECTOR_TYPE) | |||
3634 | { | |||
3635 | error ("non-vector operands in vector comparison"); | |||
3636 | debug_generic_expr (op0_type); | |||
3637 | debug_generic_expr (op1_type); | |||
3638 | return true; | |||
3639 | } | |||
3640 | ||||
3641 | if (maybe_ne (TYPE_VECTOR_SUBPARTS (type), | |||
3642 | TYPE_VECTOR_SUBPARTS (op0_type))) | |||
3643 | { | |||
3644 | error ("invalid vector comparison resulting type"); | |||
3645 | debug_generic_expr (type); | |||
3646 | return true; | |||
3647 | } | |||
3648 | } | |||
3649 | else | |||
3650 | { | |||
3651 | error ("bogus comparison result type"); | |||
3652 | debug_generic_expr (type); | |||
3653 | return true; | |||
3654 | } | |||
3655 | ||||
3656 | return false; | |||
3657 | } | |||
3658 | ||||
3659 | /* Verify a gimple assignment statement STMT with an unary rhs. | |||
3660 | Returns true if anything is wrong. */ | |||
3661 | ||||
3662 | static bool | |||
3663 | verify_gimple_assign_unary (gassign *stmt) | |||
3664 | { | |||
3665 | enum tree_code rhs_code = gimple_assign_rhs_code (stmt); | |||
3666 | tree lhs = gimple_assign_lhs (stmt); | |||
3667 | tree lhs_type = TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3667, __FUNCTION__))->typed.type); | |||
3668 | tree rhs1 = gimple_assign_rhs1 (stmt); | |||
3669 | tree rhs1_type = TREE_TYPE (rhs1)((contains_struct_check ((rhs1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3669, __FUNCTION__))->typed.type); | |||
3670 | ||||
3671 | if (!is_gimple_reg (lhs)) | |||
3672 | { | |||
3673 | error ("non-register as LHS of unary operation"); | |||
3674 | return true; | |||
3675 | } | |||
3676 | ||||
3677 | if (!is_gimple_val (rhs1)) | |||
3678 | { | |||
3679 | error ("invalid operand in unary operation"); | |||
3680 | return true; | |||
3681 | } | |||
3682 | ||||
3683 | const char* const code_name = get_tree_code_name (rhs_code); | |||
3684 | ||||
3685 | /* First handle conversions. */ | |||
3686 | switch (rhs_code) | |||
3687 | { | |||
3688 | CASE_CONVERTcase NOP_EXPR: case CONVERT_EXPR: | |||
3689 | { | |||
3690 | /* Allow conversions between vectors with the same number of elements, | |||
3691 | provided that the conversion is OK for the element types too. */ | |||
3692 | if (VECTOR_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == VECTOR_TYPE) | |||
3693 | && VECTOR_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE) | |||
3694 | && known_eq (TYPE_VECTOR_SUBPARTS (lhs_type),(!maybe_ne (TYPE_VECTOR_SUBPARTS (lhs_type), TYPE_VECTOR_SUBPARTS (rhs1_type))) | |||
3695 | TYPE_VECTOR_SUBPARTS (rhs1_type))(!maybe_ne (TYPE_VECTOR_SUBPARTS (lhs_type), TYPE_VECTOR_SUBPARTS (rhs1_type)))) | |||
3696 | { | |||
3697 | lhs_type = TREE_TYPE (lhs_type)((contains_struct_check ((lhs_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3697, __FUNCTION__))->typed.type); | |||
3698 | rhs1_type = TREE_TYPE (rhs1_type)((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3698, __FUNCTION__))->typed.type); | |||
3699 | } | |||
3700 | else if (VECTOR_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == VECTOR_TYPE) || VECTOR_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE)) | |||
3701 | { | |||
3702 | error ("invalid vector types in nop conversion"); | |||
3703 | debug_generic_expr (lhs_type); | |||
3704 | debug_generic_expr (rhs1_type); | |||
3705 | return true; | |||
3706 | } | |||
3707 | ||||
3708 | /* Allow conversions from pointer type to integral type only if | |||
3709 | there is no sign or zero extension involved. | |||
3710 | For targets were the precision of ptrofftype doesn't match that | |||
3711 | of pointers we allow conversions to types where | |||
3712 | POINTERS_EXTEND_UNSIGNED specifies how that works. */ | |||
3713 | if ((POINTER_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == POINTER_TYPE || ((enum tree_code) (lhs_type)->base.code) == REFERENCE_TYPE ) | |||
3714 | && INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE )) | |||
3715 | || (POINTER_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == POINTER_TYPE || ((enum tree_code) (rhs1_type)->base.code) == REFERENCE_TYPE ) | |||
3716 | && INTEGRAL_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (lhs_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (lhs_type)->base.code) == INTEGER_TYPE ) | |||
3717 | && (TYPE_PRECISION (rhs1_type)((tree_class_check ((rhs1_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3717, __FUNCTION__))->type_common.precision) >= TYPE_PRECISION (lhs_type)((tree_class_check ((lhs_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3717, __FUNCTION__))->type_common.precision) | |||
3718 | #if defined(POINTERS_EXTEND_UNSIGNED1) | |||
3719 | || (TYPE_MODE (rhs1_type)((((enum tree_code) ((tree_class_check ((rhs1_type), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3719, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (rhs1_type) : (rhs1_type)->type_common.mode) == ptr_mode | |||
3720 | && (TYPE_PRECISION (lhs_type)((tree_class_check ((lhs_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3720, __FUNCTION__))->type_common.precision) | |||
3721 | == BITS_PER_WORD((8) * (((global_options.x_ix86_isa_flags & (1UL << 1)) != 0) ? 8 : 4)) /* word_mode */ | |||
3722 | || (TYPE_PRECISION (lhs_type)((tree_class_check ((lhs_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3722, __FUNCTION__))->type_common.precision) | |||
3723 | == GET_MODE_PRECISION (Pmode(global_options.x_ix86_pmode == PMODE_DI ? (scalar_int_mode ( (scalar_int_mode::from_int) E_DImode)) : (scalar_int_mode ((scalar_int_mode ::from_int) E_SImode))))))) | |||
3724 | #endif | |||
3725 | ))) | |||
3726 | return false; | |||
3727 | ||||
3728 | /* Allow conversion from integral to offset type and vice versa. */ | |||
3729 | if ((TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) == OFFSET_TYPE | |||
3730 | && INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE )) | |||
3731 | || (INTEGRAL_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (lhs_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (lhs_type)->base.code) == INTEGER_TYPE ) | |||
3732 | && TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) == OFFSET_TYPE)) | |||
3733 | return false; | |||
3734 | ||||
3735 | /* Otherwise assert we are converting between types of the | |||
3736 | same kind. */ | |||
3737 | if (INTEGRAL_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (lhs_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (lhs_type)->base.code) == INTEGER_TYPE ) != INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE )) | |||
3738 | { | |||
3739 | error ("invalid types in nop conversion"); | |||
3740 | debug_generic_expr (lhs_type); | |||
3741 | debug_generic_expr (rhs1_type); | |||
3742 | return true; | |||
3743 | } | |||
3744 | ||||
3745 | return false; | |||
3746 | } | |||
3747 | ||||
3748 | case ADDR_SPACE_CONVERT_EXPR: | |||
3749 | { | |||
3750 | if (!POINTER_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == POINTER_TYPE || ((enum tree_code) (rhs1_type)->base.code) == REFERENCE_TYPE ) || !POINTER_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == POINTER_TYPE || ((enum tree_code) (lhs_type)->base.code) == REFERENCE_TYPE ) | |||
3751 | || (TYPE_ADDR_SPACE (TREE_TYPE (rhs1_type))((tree_class_check ((((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3751, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3751, __FUNCTION__))->base.u.bits.address_space) | |||
3752 | == TYPE_ADDR_SPACE (TREE_TYPE (lhs_type))((tree_class_check ((((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3752, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3752, __FUNCTION__))->base.u.bits.address_space))) | |||
3753 | { | |||
3754 | error ("invalid types in address space conversion"); | |||
3755 | debug_generic_expr (lhs_type); | |||
3756 | debug_generic_expr (rhs1_type); | |||
3757 | return true; | |||
3758 | } | |||
3759 | ||||
3760 | return false; | |||
3761 | } | |||
3762 | ||||
3763 | case FIXED_CONVERT_EXPR: | |||
3764 | { | |||
3765 | if (!valid_fixed_convert_types_p (lhs_type, rhs1_type) | |||
3766 | && !valid_fixed_convert_types_p (rhs1_type, lhs_type)) | |||
3767 | { | |||
3768 | error ("invalid types in fixed-point conversion"); | |||
3769 | debug_generic_expr (lhs_type); | |||
3770 | debug_generic_expr (rhs1_type); | |||
3771 | return true; | |||
3772 | } | |||
3773 | ||||
3774 | return false; | |||
3775 | } | |||
3776 | ||||
3777 | case FLOAT_EXPR: | |||
3778 | { | |||
3779 | if ((!INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE ) || !SCALAR_FLOAT_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == REAL_TYPE)) | |||
3780 | && (!VECTOR_INTEGER_TYPE_P (rhs1_type)((((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE ) && ((enum tree_code) (((contains_struct_check ((rhs1_type ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3780, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3781 | || !VECTOR_FLOAT_TYPE_P (lhs_type)((((enum tree_code) (lhs_type)->base.code) == VECTOR_TYPE) && ((enum tree_code) (((contains_struct_check ((lhs_type ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3781, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ))) | |||
3782 | { | |||
3783 | error ("invalid types in conversion to floating-point"); | |||
3784 | debug_generic_expr (lhs_type); | |||
3785 | debug_generic_expr (rhs1_type); | |||
3786 | return true; | |||
3787 | } | |||
3788 | ||||
3789 | return false; | |||
3790 | } | |||
3791 | ||||
3792 | case FIX_TRUNC_EXPR: | |||
3793 | { | |||
3794 | if ((!INTEGRAL_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (lhs_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (lhs_type)->base.code) == INTEGER_TYPE ) || !SCALAR_FLOAT_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == REAL_TYPE)) | |||
3795 | && (!VECTOR_INTEGER_TYPE_P (lhs_type)((((enum tree_code) (lhs_type)->base.code) == VECTOR_TYPE) && ((enum tree_code) (((contains_struct_check ((lhs_type ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3795, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3796 | || !VECTOR_FLOAT_TYPE_P (rhs1_type)((((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE ) && ((enum tree_code) (((contains_struct_check ((rhs1_type ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3796, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ))) | |||
3797 | { | |||
3798 | error ("invalid types in conversion to integer"); | |||
3799 | debug_generic_expr (lhs_type); | |||
3800 | debug_generic_expr (rhs1_type); | |||
3801 | return true; | |||
3802 | } | |||
3803 | ||||
3804 | return false; | |||
3805 | } | |||
3806 | ||||
3807 | case VEC_UNPACK_HI_EXPR: | |||
3808 | case VEC_UNPACK_LO_EXPR: | |||
3809 | case VEC_UNPACK_FLOAT_HI_EXPR: | |||
3810 | case VEC_UNPACK_FLOAT_LO_EXPR: | |||
3811 | case VEC_UNPACK_FIX_TRUNC_HI_EXPR: | |||
3812 | case VEC_UNPACK_FIX_TRUNC_LO_EXPR: | |||
3813 | if (TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) != VECTOR_TYPE | |||
3814 | || TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != VECTOR_TYPE | |||
3815 | || (!INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))(((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3815, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3815, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3815, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3816 | && !SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs_type))(((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3816, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE )) | |||
3817 | || (!INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3817, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3817, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3817, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3818 | && !SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3818, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE )) | |||
3819 | || ((rhs_code == VEC_UNPACK_HI_EXPR | |||
3820 | || rhs_code == VEC_UNPACK_LO_EXPR) | |||
3821 | && (INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))(((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3821, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3821, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3821, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3822 | != INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3822, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3822, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3822, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ))) | |||
3823 | || ((rhs_code == VEC_UNPACK_FLOAT_HI_EXPR | |||
3824 | || rhs_code == VEC_UNPACK_FLOAT_LO_EXPR) | |||
3825 | && (INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))(((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3825, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3825, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3825, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3826 | || SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3826, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ))) | |||
3827 | || ((rhs_code == VEC_UNPACK_FIX_TRUNC_HI_EXPR | |||
3828 | || rhs_code == VEC_UNPACK_FIX_TRUNC_LO_EXPR) | |||
3829 | && (INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3829, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3829, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3829, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3830 | || SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs_type))(((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3830, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ))) | |||
3831 | || (maybe_ne (GET_MODE_SIZE (element_mode (lhs_type)), | |||
3832 | 2 * GET_MODE_SIZE (element_mode (rhs1_type))) | |||
3833 | && (!VECTOR_BOOLEAN_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == VECTOR_TYPE && ((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3833, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE ) | |||
3834 | || !VECTOR_BOOLEAN_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE && ((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3834, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE ))) | |||
3835 | || maybe_ne (2 * TYPE_VECTOR_SUBPARTS (lhs_type), | |||
3836 | TYPE_VECTOR_SUBPARTS (rhs1_type))) | |||
3837 | { | |||
3838 | error ("type mismatch in %qs expression", code_name); | |||
3839 | debug_generic_expr (lhs_type); | |||
3840 | debug_generic_expr (rhs1_type); | |||
3841 | return true; | |||
3842 | } | |||
3843 | ||||
3844 | return false; | |||
3845 | ||||
3846 | case NEGATE_EXPR: | |||
3847 | case ABS_EXPR: | |||
3848 | case BIT_NOT_EXPR: | |||
3849 | case PAREN_EXPR: | |||
3850 | case CONJ_EXPR: | |||
3851 | /* Disallow pointer and offset types for many of the unary gimple. */ | |||
3852 | if (POINTER_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == POINTER_TYPE || ((enum tree_code) (lhs_type)->base.code) == REFERENCE_TYPE ) | |||
3853 | || TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) == OFFSET_TYPE) | |||
3854 | { | |||
3855 | error ("invalid types for %qs", code_name); | |||
3856 | debug_generic_expr (lhs_type); | |||
3857 | debug_generic_expr (rhs1_type); | |||
3858 | return true; | |||
3859 | } | |||
3860 | break; | |||
3861 | ||||
3862 | case ABSU_EXPR: | |||
3863 | if (!ANY_INTEGRAL_TYPE_P (lhs_type)((((enum tree_code) (lhs_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (lhs_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (lhs_type)->base.code) == INTEGER_TYPE ) || ((((enum tree_code) (lhs_type)->base.code) == COMPLEX_TYPE || (((enum tree_code) (lhs_type)->base.code) == VECTOR_TYPE )) && (((enum tree_code) (((contains_struct_check ((lhs_type ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3863, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3863, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3863, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ))) | |||
3864 | || !TYPE_UNSIGNED (lhs_type)((tree_class_check ((lhs_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3864, __FUNCTION__))->base.u.bits.unsigned_flag) | |||
3865 | || !ANY_INTEGRAL_TYPE_P (rhs1_type)((((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE ) || ((((enum tree_code) (rhs1_type)->base.code) == COMPLEX_TYPE || (((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE )) && (((enum tree_code) (((contains_struct_check ((rhs1_type ), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3865, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3865, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3865, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ))) | |||
3866 | || TYPE_UNSIGNED (rhs1_type)((tree_class_check ((rhs1_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3866, __FUNCTION__))->base.u.bits.unsigned_flag) | |||
3867 | || element_precision (lhs_type) != element_precision (rhs1_type)) | |||
3868 | { | |||
3869 | error ("invalid types for %qs", code_name); | |||
3870 | debug_generic_expr (lhs_type); | |||
3871 | debug_generic_expr (rhs1_type); | |||
3872 | return true; | |||
3873 | } | |||
3874 | return false; | |||
3875 | ||||
3876 | case VEC_DUPLICATE_EXPR: | |||
3877 | if (TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != VECTOR_TYPE | |||
3878 | || !useless_type_conversion_p (TREE_TYPE (lhs_type)((contains_struct_check ((lhs_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3878, __FUNCTION__))->typed.type), rhs1_type)) | |||
3879 | { | |||
3880 | error ("%qs should be from a scalar to a like vector", code_name); | |||
3881 | debug_generic_expr (lhs_type); | |||
3882 | debug_generic_expr (rhs1_type); | |||
3883 | return true; | |||
3884 | } | |||
3885 | return false; | |||
3886 | ||||
3887 | default: | |||
3888 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3888, __FUNCTION__)); | |||
3889 | } | |||
3890 | ||||
3891 | /* For the remaining codes assert there is no conversion involved. */ | |||
3892 | if (!useless_type_conversion_p (lhs_type, rhs1_type)) | |||
3893 | { | |||
3894 | error ("non-trivial conversion in unary operation"); | |||
3895 | debug_generic_expr (lhs_type); | |||
3896 | debug_generic_expr (rhs1_type); | |||
3897 | return true; | |||
3898 | } | |||
3899 | ||||
3900 | return false; | |||
3901 | } | |||
3902 | ||||
3903 | /* Verify a gimple assignment statement STMT with a binary rhs. | |||
3904 | Returns true if anything is wrong. */ | |||
3905 | ||||
3906 | static bool | |||
3907 | verify_gimple_assign_binary (gassign *stmt) | |||
3908 | { | |||
3909 | enum tree_code rhs_code = gimple_assign_rhs_code (stmt); | |||
3910 | tree lhs = gimple_assign_lhs (stmt); | |||
3911 | tree lhs_type = TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3911, __FUNCTION__))->typed.type); | |||
3912 | tree rhs1 = gimple_assign_rhs1 (stmt); | |||
3913 | tree rhs1_type = TREE_TYPE (rhs1)((contains_struct_check ((rhs1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3913, __FUNCTION__))->typed.type); | |||
3914 | tree rhs2 = gimple_assign_rhs2 (stmt); | |||
3915 | tree rhs2_type = TREE_TYPE (rhs2)((contains_struct_check ((rhs2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3915, __FUNCTION__))->typed.type); | |||
3916 | ||||
3917 | if (!is_gimple_reg (lhs)) | |||
3918 | { | |||
3919 | error ("non-register as LHS of binary operation"); | |||
3920 | return true; | |||
3921 | } | |||
3922 | ||||
3923 | if (!is_gimple_val (rhs1) | |||
3924 | || !is_gimple_val (rhs2)) | |||
3925 | { | |||
3926 | error ("invalid operands in binary operation"); | |||
3927 | return true; | |||
3928 | } | |||
3929 | ||||
3930 | const char* const code_name = get_tree_code_name (rhs_code); | |||
3931 | ||||
3932 | /* First handle operations that involve different types. */ | |||
3933 | switch (rhs_code) | |||
3934 | { | |||
3935 | case COMPLEX_EXPR: | |||
3936 | { | |||
3937 | if (TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != COMPLEX_TYPE | |||
3938 | || !(INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE ) | |||
3939 | || SCALAR_FLOAT_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == REAL_TYPE)) | |||
3940 | || !(INTEGRAL_TYPE_P (rhs2_type)(((enum tree_code) (rhs2_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs2_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs2_type)->base.code) == INTEGER_TYPE ) | |||
3941 | || SCALAR_FLOAT_TYPE_P (rhs2_type)(((enum tree_code) (rhs2_type)->base.code) == REAL_TYPE))) | |||
3942 | { | |||
3943 | error ("type mismatch in %qs", code_name); | |||
3944 | debug_generic_expr (lhs_type); | |||
3945 | debug_generic_expr (rhs1_type); | |||
3946 | debug_generic_expr (rhs2_type); | |||
3947 | return true; | |||
3948 | } | |||
3949 | ||||
3950 | return false; | |||
3951 | } | |||
3952 | ||||
3953 | case LSHIFT_EXPR: | |||
3954 | case RSHIFT_EXPR: | |||
3955 | case LROTATE_EXPR: | |||
3956 | case RROTATE_EXPR: | |||
3957 | { | |||
3958 | /* Shifts and rotates are ok on integral types, fixed point | |||
3959 | types and integer vector types. */ | |||
3960 | if ((!INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE ) | |||
3961 | && !FIXED_POINT_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == FIXED_POINT_TYPE ) | |||
3962 | && !(TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE | |||
3963 | && INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3963, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3963, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3963, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ))) | |||
3964 | || (!INTEGRAL_TYPE_P (rhs2_type)(((enum tree_code) (rhs2_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs2_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs2_type)->base.code) == INTEGER_TYPE ) | |||
3965 | /* Vector shifts of vectors are also ok. */ | |||
3966 | && !(TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE | |||
3967 | && INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3967, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3967, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3967, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
3968 | && TREE_CODE (rhs2_type)((enum tree_code) (rhs2_type)->base.code) == VECTOR_TYPE | |||
3969 | && INTEGRAL_TYPE_P (TREE_TYPE (rhs2_type))(((enum tree_code) (((contains_struct_check ((rhs2_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3969, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((rhs2_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3969, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((rhs2_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3969, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ))) | |||
3970 | || !useless_type_conversion_p (lhs_type, rhs1_type)) | |||
3971 | { | |||
3972 | error ("type mismatch in %qs", code_name); | |||
3973 | debug_generic_expr (lhs_type); | |||
3974 | debug_generic_expr (rhs1_type); | |||
3975 | debug_generic_expr (rhs2_type); | |||
3976 | return true; | |||
3977 | } | |||
3978 | ||||
3979 | return false; | |||
3980 | } | |||
3981 | ||||
3982 | case WIDEN_LSHIFT_EXPR: | |||
3983 | { | |||
3984 | if (!INTEGRAL_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (lhs_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (lhs_type)->base.code) == INTEGER_TYPE ) | |||
3985 | || !INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE ) | |||
3986 | || TREE_CODE (rhs2)((enum tree_code) (rhs2)->base.code) != INTEGER_CST | |||
3987 | || (2 * TYPE_PRECISION (rhs1_type)((tree_class_check ((rhs1_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3987, __FUNCTION__))->type_common.precision) > TYPE_PRECISION (lhs_type)((tree_class_check ((lhs_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 3987, __FUNCTION__))->type_common.precision))) | |||
3988 | { | |||
3989 | error ("type mismatch in %qs", code_name); | |||
3990 | debug_generic_expr (lhs_type); | |||
3991 | debug_generic_expr (rhs1_type); | |||
3992 | debug_generic_expr (rhs2_type); | |||
3993 | return true; | |||
3994 | } | |||
3995 | ||||
3996 | return false; | |||
3997 | } | |||
3998 | ||||
3999 | case VEC_WIDEN_LSHIFT_HI_EXPR: | |||
4000 | case VEC_WIDEN_LSHIFT_LO_EXPR: | |||
4001 | { | |||
4002 | if (TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) != VECTOR_TYPE | |||
4003 | || TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != VECTOR_TYPE | |||
4004 | || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4004, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4004, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4004, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
4005 | || !INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))(((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4005, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4005, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4005, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
4006 | || TREE_CODE (rhs2)((enum tree_code) (rhs2)->base.code) != INTEGER_CST | |||
4007 | || (2 * TYPE_PRECISION (TREE_TYPE (rhs1_type))((tree_class_check ((((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4007, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4007, __FUNCTION__))->type_common.precision) | |||
4008 | > TYPE_PRECISION (TREE_TYPE (lhs_type))((tree_class_check ((((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4008, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4008, __FUNCTION__))->type_common.precision))) | |||
4009 | { | |||
4010 | error ("type mismatch in %qs", code_name); | |||
4011 | debug_generic_expr (lhs_type); | |||
4012 | debug_generic_expr (rhs1_type); | |||
4013 | debug_generic_expr (rhs2_type); | |||
4014 | return true; | |||
4015 | } | |||
4016 | ||||
4017 | return false; | |||
4018 | } | |||
4019 | ||||
4020 | case WIDEN_PLUS_EXPR: | |||
4021 | case WIDEN_MINUS_EXPR: | |||
4022 | case PLUS_EXPR: | |||
4023 | case MINUS_EXPR: | |||
4024 | { | |||
4025 | tree lhs_etype = lhs_type; | |||
4026 | tree rhs1_etype = rhs1_type; | |||
4027 | tree rhs2_etype = rhs2_type; | |||
4028 | if (TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) == VECTOR_TYPE) | |||
4029 | { | |||
4030 | if (TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) != VECTOR_TYPE | |||
4031 | || TREE_CODE (rhs2_type)((enum tree_code) (rhs2_type)->base.code) != VECTOR_TYPE) | |||
4032 | { | |||
4033 | error ("invalid non-vector operands to %qs", code_name); | |||
4034 | return true; | |||
4035 | } | |||
4036 | lhs_etype = TREE_TYPE (lhs_type)((contains_struct_check ((lhs_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4036, __FUNCTION__))->typed.type); | |||
4037 | rhs1_etype = TREE_TYPE (rhs1_type)((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4037, __FUNCTION__))->typed.type); | |||
4038 | rhs2_etype = TREE_TYPE (rhs2_type)((contains_struct_check ((rhs2_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4038, __FUNCTION__))->typed.type); | |||
4039 | } | |||
4040 | if (POINTER_TYPE_P (lhs_etype)(((enum tree_code) (lhs_etype)->base.code) == POINTER_TYPE || ((enum tree_code) (lhs_etype)->base.code) == REFERENCE_TYPE ) | |||
4041 | || POINTER_TYPE_P (rhs1_etype)(((enum tree_code) (rhs1_etype)->base.code) == POINTER_TYPE || ((enum tree_code) (rhs1_etype)->base.code) == REFERENCE_TYPE ) | |||
4042 | || POINTER_TYPE_P (rhs2_etype)(((enum tree_code) (rhs2_etype)->base.code) == POINTER_TYPE || ((enum tree_code) (rhs2_etype)->base.code) == REFERENCE_TYPE )) | |||
4043 | { | |||
4044 | error ("invalid (pointer) operands %qs", code_name); | |||
4045 | return true; | |||
4046 | } | |||
4047 | ||||
4048 | /* Continue with generic binary expression handling. */ | |||
4049 | break; | |||
4050 | } | |||
4051 | ||||
4052 | case POINTER_PLUS_EXPR: | |||
4053 | { | |||
4054 | if (!POINTER_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == POINTER_TYPE || ((enum tree_code) (rhs1_type)->base.code) == REFERENCE_TYPE ) | |||
4055 | || !useless_type_conversion_p (lhs_type, rhs1_type) | |||
4056 | || !ptrofftype_p (rhs2_type)) | |||
4057 | { | |||
4058 | error ("type mismatch in %qs", code_name); | |||
4059 | debug_generic_stmt (lhs_type); | |||
4060 | debug_generic_stmt (rhs1_type); | |||
4061 | debug_generic_stmt (rhs2_type); | |||
4062 | return true; | |||
4063 | } | |||
4064 | ||||
4065 | return false; | |||
4066 | } | |||
4067 | ||||
4068 | case POINTER_DIFF_EXPR: | |||
4069 | { | |||
4070 | if (!POINTER_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == POINTER_TYPE || ((enum tree_code) (rhs1_type)->base.code) == REFERENCE_TYPE ) | |||
4071 | || !POINTER_TYPE_P (rhs2_type)(((enum tree_code) (rhs2_type)->base.code) == POINTER_TYPE || ((enum tree_code) (rhs2_type)->base.code) == REFERENCE_TYPE ) | |||
4072 | /* Because we special-case pointers to void we allow difference | |||
4073 | of arbitrary pointers with the same mode. */ | |||
4074 | || TYPE_MODE (rhs1_type)((((enum tree_code) ((tree_class_check ((rhs1_type), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4074, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (rhs1_type) : (rhs1_type)->type_common.mode) != TYPE_MODE (rhs2_type)((((enum tree_code) ((tree_class_check ((rhs2_type), (tcc_type ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4074, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (rhs2_type) : (rhs2_type)->type_common.mode) | |||
4075 | || !INTEGRAL_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (lhs_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (lhs_type)->base.code) == INTEGER_TYPE ) | |||
4076 | || TYPE_UNSIGNED (lhs_type)((tree_class_check ((lhs_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4076, __FUNCTION__))->base.u.bits.unsigned_flag) | |||
4077 | || TYPE_PRECISION (lhs_type)((tree_class_check ((lhs_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4077, __FUNCTION__))->type_common.precision) != TYPE_PRECISION (rhs1_type)((tree_class_check ((rhs1_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4077, __FUNCTION__))->type_common.precision)) | |||
4078 | { | |||
4079 | error ("type mismatch in %qs", code_name); | |||
4080 | debug_generic_stmt (lhs_type); | |||
4081 | debug_generic_stmt (rhs1_type); | |||
4082 | debug_generic_stmt (rhs2_type); | |||
4083 | return true; | |||
4084 | } | |||
4085 | ||||
4086 | return false; | |||
4087 | } | |||
4088 | ||||
4089 | case TRUTH_ANDIF_EXPR: | |||
4090 | case TRUTH_ORIF_EXPR: | |||
4091 | case TRUTH_AND_EXPR: | |||
4092 | case TRUTH_OR_EXPR: | |||
4093 | case TRUTH_XOR_EXPR: | |||
4094 | ||||
4095 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4095, __FUNCTION__)); | |||
4096 | ||||
4097 | case LT_EXPR: | |||
4098 | case LE_EXPR: | |||
4099 | case GT_EXPR: | |||
4100 | case GE_EXPR: | |||
4101 | case EQ_EXPR: | |||
4102 | case NE_EXPR: | |||
4103 | case UNORDERED_EXPR: | |||
4104 | case ORDERED_EXPR: | |||
4105 | case UNLT_EXPR: | |||
4106 | case UNLE_EXPR: | |||
4107 | case UNGT_EXPR: | |||
4108 | case UNGE_EXPR: | |||
4109 | case UNEQ_EXPR: | |||
4110 | case LTGT_EXPR: | |||
4111 | /* Comparisons are also binary, but the result type is not | |||
4112 | connected to the operand types. */ | |||
4113 | return verify_gimple_comparison (lhs_type, rhs1, rhs2, rhs_code); | |||
4114 | ||||
4115 | case WIDEN_MULT_EXPR: | |||
4116 | if (TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != INTEGER_TYPE) | |||
4117 | return true; | |||
4118 | return ((2 * TYPE_PRECISION (rhs1_type)((tree_class_check ((rhs1_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4118, __FUNCTION__))->type_common.precision) > TYPE_PRECISION (lhs_type)((tree_class_check ((lhs_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4118, __FUNCTION__))->type_common.precision)) | |||
4119 | || (TYPE_PRECISION (rhs1_type)((tree_class_check ((rhs1_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4119, __FUNCTION__))->type_common.precision) != TYPE_PRECISION (rhs2_type)((tree_class_check ((rhs2_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4119, __FUNCTION__))->type_common.precision))); | |||
4120 | ||||
4121 | case WIDEN_SUM_EXPR: | |||
4122 | { | |||
4123 | if (((TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) != VECTOR_TYPE | |||
4124 | || TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != VECTOR_TYPE) | |||
4125 | && ((!INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE ) | |||
4126 | && !SCALAR_FLOAT_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == REAL_TYPE)) | |||
4127 | || (!INTEGRAL_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (lhs_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (lhs_type)->base.code) == INTEGER_TYPE ) | |||
4128 | && !SCALAR_FLOAT_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == REAL_TYPE)))) | |||
4129 | || !useless_type_conversion_p (lhs_type, rhs2_type) | |||
4130 | || maybe_lt (GET_MODE_SIZE (element_mode (rhs2_type)), | |||
4131 | 2 * GET_MODE_SIZE (element_mode (rhs1_type)))) | |||
4132 | { | |||
4133 | error ("type mismatch in %qs", code_name); | |||
4134 | debug_generic_expr (lhs_type); | |||
4135 | debug_generic_expr (rhs1_type); | |||
4136 | debug_generic_expr (rhs2_type); | |||
4137 | return true; | |||
4138 | } | |||
4139 | return false; | |||
4140 | } | |||
4141 | ||||
4142 | case VEC_WIDEN_MINUS_HI_EXPR: | |||
4143 | case VEC_WIDEN_MINUS_LO_EXPR: | |||
4144 | case VEC_WIDEN_PLUS_HI_EXPR: | |||
4145 | case VEC_WIDEN_PLUS_LO_EXPR: | |||
4146 | case VEC_WIDEN_MULT_HI_EXPR: | |||
4147 | case VEC_WIDEN_MULT_LO_EXPR: | |||
4148 | case VEC_WIDEN_MULT_EVEN_EXPR: | |||
4149 | case VEC_WIDEN_MULT_ODD_EXPR: | |||
4150 | { | |||
4151 | if (TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) != VECTOR_TYPE | |||
4152 | || TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != VECTOR_TYPE | |||
4153 | || !types_compatible_p (rhs1_type, rhs2_type) | |||
4154 | || maybe_ne (GET_MODE_SIZE (element_mode (lhs_type)), | |||
4155 | 2 * GET_MODE_SIZE (element_mode (rhs1_type)))) | |||
4156 | { | |||
4157 | error ("type mismatch in %qs", code_name); | |||
4158 | debug_generic_expr (lhs_type); | |||
4159 | debug_generic_expr (rhs1_type); | |||
4160 | debug_generic_expr (rhs2_type); | |||
4161 | return true; | |||
4162 | } | |||
4163 | return false; | |||
4164 | } | |||
4165 | ||||
4166 | case VEC_PACK_TRUNC_EXPR: | |||
4167 | /* ??? We currently use VEC_PACK_TRUNC_EXPR to simply concat | |||
4168 | vector boolean types. */ | |||
4169 | if (VECTOR_BOOLEAN_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == VECTOR_TYPE && ((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4169, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE ) | |||
4170 | && VECTOR_BOOLEAN_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE && ((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4170, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE ) | |||
4171 | && types_compatible_p (rhs1_type, rhs2_type) | |||
4172 | && known_eq (TYPE_VECTOR_SUBPARTS (lhs_type),(!maybe_ne (TYPE_VECTOR_SUBPARTS (lhs_type), 2 * TYPE_VECTOR_SUBPARTS (rhs1_type))) | |||
4173 | 2 * TYPE_VECTOR_SUBPARTS (rhs1_type))(!maybe_ne (TYPE_VECTOR_SUBPARTS (lhs_type), 2 * TYPE_VECTOR_SUBPARTS (rhs1_type)))) | |||
4174 | return false; | |||
4175 | ||||
4176 | /* Fallthru. */ | |||
4177 | case VEC_PACK_SAT_EXPR: | |||
4178 | case VEC_PACK_FIX_TRUNC_EXPR: | |||
4179 | { | |||
4180 | if (TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) != VECTOR_TYPE | |||
4181 | || TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != VECTOR_TYPE | |||
4182 | || !((rhs_code == VEC_PACK_FIX_TRUNC_EXPR | |||
4183 | && SCALAR_FLOAT_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4183, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ) | |||
4184 | && INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))(((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4184, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4184, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4184, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE )) | |||
4185 | || (INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4185, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4185, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4185, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
4186 | == INTEGRAL_TYPE_P (TREE_TYPE (lhs_type))(((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4186, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4186, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((lhs_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4186, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ))) | |||
4187 | || !types_compatible_p (rhs1_type, rhs2_type) | |||
4188 | || maybe_ne (GET_MODE_SIZE (element_mode (rhs1_type)), | |||
4189 | 2 * GET_MODE_SIZE (element_mode (lhs_type))) | |||
4190 | || maybe_ne (2 * TYPE_VECTOR_SUBPARTS (rhs1_type), | |||
4191 | TYPE_VECTOR_SUBPARTS (lhs_type))) | |||
4192 | { | |||
4193 | error ("type mismatch in %qs", code_name); | |||
4194 | debug_generic_expr (lhs_type); | |||
4195 | debug_generic_expr (rhs1_type); | |||
4196 | debug_generic_expr (rhs2_type); | |||
4197 | return true; | |||
4198 | } | |||
4199 | ||||
4200 | return false; | |||
4201 | } | |||
4202 | ||||
4203 | case VEC_PACK_FLOAT_EXPR: | |||
4204 | if (TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) != VECTOR_TYPE | |||
4205 | || TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != VECTOR_TYPE | |||
4206 | || !INTEGRAL_TYPE_P (TREE_TYPE (rhs1_type))(((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4206, __FUNCTION__))->typed.type))->base.code) == ENUMERAL_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4206, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE || ((enum tree_code) (((contains_struct_check ((rhs1_type), ( TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4206, __FUNCTION__))->typed.type))->base.code) == INTEGER_TYPE ) | |||
4207 | || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs_type))(((enum tree_code) (((contains_struct_check ((lhs_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4207, __FUNCTION__))->typed.type))->base.code) == REAL_TYPE ) | |||
4208 | || !types_compatible_p (rhs1_type, rhs2_type) | |||
4209 | || maybe_ne (GET_MODE_SIZE (element_mode (rhs1_type)), | |||
4210 | 2 * GET_MODE_SIZE (element_mode (lhs_type))) | |||
4211 | || maybe_ne (2 * TYPE_VECTOR_SUBPARTS (rhs1_type), | |||
4212 | TYPE_VECTOR_SUBPARTS (lhs_type))) | |||
4213 | { | |||
4214 | error ("type mismatch in %qs", code_name); | |||
4215 | debug_generic_expr (lhs_type); | |||
4216 | debug_generic_expr (rhs1_type); | |||
4217 | debug_generic_expr (rhs2_type); | |||
4218 | return true; | |||
4219 | } | |||
4220 | ||||
4221 | return false; | |||
4222 | ||||
4223 | case MULT_EXPR: | |||
4224 | case MULT_HIGHPART_EXPR: | |||
4225 | case TRUNC_DIV_EXPR: | |||
4226 | case CEIL_DIV_EXPR: | |||
4227 | case FLOOR_DIV_EXPR: | |||
4228 | case ROUND_DIV_EXPR: | |||
4229 | case TRUNC_MOD_EXPR: | |||
4230 | case CEIL_MOD_EXPR: | |||
4231 | case FLOOR_MOD_EXPR: | |||
4232 | case ROUND_MOD_EXPR: | |||
4233 | case RDIV_EXPR: | |||
4234 | case EXACT_DIV_EXPR: | |||
4235 | case BIT_IOR_EXPR: | |||
4236 | case BIT_XOR_EXPR: | |||
4237 | /* Disallow pointer and offset types for many of the binary gimple. */ | |||
4238 | if (POINTER_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == POINTER_TYPE || ((enum tree_code) (lhs_type)->base.code) == REFERENCE_TYPE ) | |||
4239 | || TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) == OFFSET_TYPE) | |||
4240 | { | |||
4241 | error ("invalid types for %qs", code_name); | |||
4242 | debug_generic_expr (lhs_type); | |||
4243 | debug_generic_expr (rhs1_type); | |||
4244 | debug_generic_expr (rhs2_type); | |||
4245 | return true; | |||
4246 | } | |||
4247 | /* Continue with generic binary expression handling. */ | |||
4248 | break; | |||
4249 | ||||
4250 | case MIN_EXPR: | |||
4251 | case MAX_EXPR: | |||
4252 | /* Continue with generic binary expression handling. */ | |||
4253 | break; | |||
4254 | ||||
4255 | case BIT_AND_EXPR: | |||
4256 | if (POINTER_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == POINTER_TYPE || ((enum tree_code) (lhs_type)->base.code) == REFERENCE_TYPE ) | |||
4257 | && TREE_CODE (rhs2)((enum tree_code) (rhs2)->base.code) == INTEGER_CST) | |||
4258 | break; | |||
4259 | /* Disallow pointer and offset types for many of the binary gimple. */ | |||
4260 | if (POINTER_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == POINTER_TYPE || ((enum tree_code) (lhs_type)->base.code) == REFERENCE_TYPE ) | |||
4261 | || TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) == OFFSET_TYPE) | |||
4262 | { | |||
4263 | error ("invalid types for %qs", code_name); | |||
4264 | debug_generic_expr (lhs_type); | |||
4265 | debug_generic_expr (rhs1_type); | |||
4266 | debug_generic_expr (rhs2_type); | |||
4267 | return true; | |||
4268 | } | |||
4269 | /* Continue with generic binary expression handling. */ | |||
4270 | break; | |||
4271 | ||||
4272 | case VEC_SERIES_EXPR: | |||
4273 | if (!useless_type_conversion_p (rhs1_type, rhs2_type)) | |||
4274 | { | |||
4275 | error ("type mismatch in %qs", code_name); | |||
4276 | debug_generic_expr (rhs1_type); | |||
4277 | debug_generic_expr (rhs2_type); | |||
4278 | return true; | |||
4279 | } | |||
4280 | if (TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != VECTOR_TYPE | |||
4281 | || !useless_type_conversion_p (TREE_TYPE (lhs_type)((contains_struct_check ((lhs_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4281, __FUNCTION__))->typed.type), rhs1_type)) | |||
4282 | { | |||
4283 | error ("vector type expected in %qs", code_name); | |||
4284 | debug_generic_expr (lhs_type); | |||
4285 | return true; | |||
4286 | } | |||
4287 | return false; | |||
4288 | ||||
4289 | default: | |||
4290 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4290, __FUNCTION__)); | |||
4291 | } | |||
4292 | ||||
4293 | if (!useless_type_conversion_p (lhs_type, rhs1_type) | |||
4294 | || !useless_type_conversion_p (lhs_type, rhs2_type)) | |||
4295 | { | |||
4296 | error ("type mismatch in binary expression"); | |||
4297 | debug_generic_stmt (lhs_type); | |||
4298 | debug_generic_stmt (rhs1_type); | |||
4299 | debug_generic_stmt (rhs2_type); | |||
4300 | return true; | |||
4301 | } | |||
4302 | ||||
4303 | return false; | |||
4304 | } | |||
4305 | ||||
4306 | /* Verify a gimple assignment statement STMT with a ternary rhs. | |||
4307 | Returns true if anything is wrong. */ | |||
4308 | ||||
4309 | static bool | |||
4310 | verify_gimple_assign_ternary (gassign *stmt) | |||
4311 | { | |||
4312 | enum tree_code rhs_code = gimple_assign_rhs_code (stmt); | |||
4313 | tree lhs = gimple_assign_lhs (stmt); | |||
4314 | tree lhs_type = TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4314, __FUNCTION__))->typed.type); | |||
4315 | tree rhs1 = gimple_assign_rhs1 (stmt); | |||
4316 | tree rhs1_type = TREE_TYPE (rhs1)((contains_struct_check ((rhs1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4316, __FUNCTION__))->typed.type); | |||
4317 | tree rhs2 = gimple_assign_rhs2 (stmt); | |||
4318 | tree rhs2_type = TREE_TYPE (rhs2)((contains_struct_check ((rhs2), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4318, __FUNCTION__))->typed.type); | |||
4319 | tree rhs3 = gimple_assign_rhs3 (stmt); | |||
4320 | tree rhs3_type = TREE_TYPE (rhs3)((contains_struct_check ((rhs3), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4320, __FUNCTION__))->typed.type); | |||
4321 | ||||
4322 | if (!is_gimple_reg (lhs)) | |||
4323 | { | |||
4324 | error ("non-register as LHS of ternary operation"); | |||
4325 | return true; | |||
4326 | } | |||
4327 | ||||
4328 | if (!is_gimple_val (rhs1) | |||
4329 | || !is_gimple_val (rhs2) | |||
4330 | || !is_gimple_val (rhs3)) | |||
4331 | { | |||
4332 | error ("invalid operands in ternary operation"); | |||
4333 | return true; | |||
4334 | } | |||
4335 | ||||
4336 | const char* const code_name = get_tree_code_name (rhs_code); | |||
4337 | ||||
4338 | /* First handle operations that involve different types. */ | |||
4339 | switch (rhs_code) | |||
4340 | { | |||
4341 | case WIDEN_MULT_PLUS_EXPR: | |||
4342 | case WIDEN_MULT_MINUS_EXPR: | |||
4343 | if ((!INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE ) | |||
4344 | && !FIXED_POINT_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == FIXED_POINT_TYPE )) | |||
4345 | || !useless_type_conversion_p (rhs1_type, rhs2_type) | |||
4346 | || !useless_type_conversion_p (lhs_type, rhs3_type) | |||
4347 | || 2 * TYPE_PRECISION (rhs1_type)((tree_class_check ((rhs1_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4347, __FUNCTION__))->type_common.precision) > TYPE_PRECISION (lhs_type)((tree_class_check ((lhs_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4347, __FUNCTION__))->type_common.precision) | |||
4348 | || TYPE_PRECISION (rhs1_type)((tree_class_check ((rhs1_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4348, __FUNCTION__))->type_common.precision) != TYPE_PRECISION (rhs2_type)((tree_class_check ((rhs2_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4348, __FUNCTION__))->type_common.precision)) | |||
4349 | { | |||
4350 | error ("type mismatch in %qs", code_name); | |||
4351 | debug_generic_expr (lhs_type); | |||
4352 | debug_generic_expr (rhs1_type); | |||
4353 | debug_generic_expr (rhs2_type); | |||
4354 | debug_generic_expr (rhs3_type); | |||
4355 | return true; | |||
4356 | } | |||
4357 | break; | |||
4358 | ||||
4359 | case VEC_COND_EXPR: | |||
4360 | if (!VECTOR_BOOLEAN_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE && ((enum tree_code) (((contains_struct_check ((rhs1_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4360, __FUNCTION__))->typed.type))->base.code) == BOOLEAN_TYPE ) | |||
4361 | || maybe_ne (TYPE_VECTOR_SUBPARTS (rhs1_type), | |||
4362 | TYPE_VECTOR_SUBPARTS (lhs_type))) | |||
4363 | { | |||
4364 | error ("the first argument of a %qs must be of a " | |||
4365 | "boolean vector type of the same number of elements " | |||
4366 | "as the result", code_name); | |||
4367 | debug_generic_expr (lhs_type); | |||
4368 | debug_generic_expr (rhs1_type); | |||
4369 | return true; | |||
4370 | } | |||
4371 | /* Fallthrough. */ | |||
4372 | case COND_EXPR: | |||
4373 | if (!useless_type_conversion_p (lhs_type, rhs2_type) | |||
4374 | || !useless_type_conversion_p (lhs_type, rhs3_type)) | |||
4375 | { | |||
4376 | error ("type mismatch in %qs", code_name); | |||
4377 | debug_generic_expr (lhs_type); | |||
4378 | debug_generic_expr (rhs2_type); | |||
4379 | debug_generic_expr (rhs3_type); | |||
4380 | return true; | |||
4381 | } | |||
4382 | break; | |||
4383 | ||||
4384 | case VEC_PERM_EXPR: | |||
4385 | /* If permute is constant, then we allow for lhs and rhs | |||
4386 | to have different vector types, provided: | |||
4387 | (1) lhs, rhs1, rhs2 have same element type. | |||
4388 | (2) rhs3 vector is constant and has integer element type. | |||
4389 | (3) len(lhs) == len(rhs3) && len(rhs1) == len(rhs2). */ | |||
4390 | ||||
4391 | if (TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != VECTOR_TYPE | |||
4392 | || TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) != VECTOR_TYPE | |||
4393 | || TREE_CODE (rhs2_type)((enum tree_code) (rhs2_type)->base.code) != VECTOR_TYPE | |||
4394 | || TREE_CODE (rhs3_type)((enum tree_code) (rhs3_type)->base.code) != VECTOR_TYPE) | |||
4395 | { | |||
4396 | error ("vector types expected in %qs", code_name); | |||
4397 | debug_generic_expr (lhs_type); | |||
4398 | debug_generic_expr (rhs1_type); | |||
4399 | debug_generic_expr (rhs2_type); | |||
4400 | debug_generic_expr (rhs3_type); | |||
4401 | return true; | |||
4402 | } | |||
4403 | ||||
4404 | /* If rhs3 is constant, we allow lhs, rhs1 and rhs2 to be different vector types, | |||
4405 | as long as lhs, rhs1 and rhs2 have same element type. */ | |||
4406 | if (TREE_CONSTANT (rhs3)((non_type_check ((rhs3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4406, __FUNCTION__))->base.constant_flag) | |||
4407 | ? (!useless_type_conversion_p (TREE_TYPE (lhs_type)((contains_struct_check ((lhs_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4407, __FUNCTION__))->typed.type), TREE_TYPE (rhs1_type)((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4407, __FUNCTION__))->typed.type)) | |||
4408 | || !useless_type_conversion_p (TREE_TYPE (lhs_type)((contains_struct_check ((lhs_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4408, __FUNCTION__))->typed.type), TREE_TYPE (rhs2_type)((contains_struct_check ((rhs2_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4408, __FUNCTION__))->typed.type))) | |||
4409 | : (!useless_type_conversion_p (lhs_type, rhs1_type) | |||
4410 | || !useless_type_conversion_p (lhs_type, rhs2_type))) | |||
4411 | { | |||
4412 | error ("type mismatch in %qs", code_name); | |||
4413 | debug_generic_expr (lhs_type); | |||
4414 | debug_generic_expr (rhs1_type); | |||
4415 | debug_generic_expr (rhs2_type); | |||
4416 | debug_generic_expr (rhs3_type); | |||
4417 | return true; | |||
4418 | } | |||
4419 | ||||
4420 | /* If rhs3 is constant, relax the check len(rhs2) == len(rhs3). */ | |||
4421 | if (maybe_ne (TYPE_VECTOR_SUBPARTS (rhs1_type), | |||
4422 | TYPE_VECTOR_SUBPARTS (rhs2_type)) | |||
4423 | || (!TREE_CONSTANT(rhs3)((non_type_check ((rhs3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4423, __FUNCTION__))->base.constant_flag) | |||
4424 | && maybe_ne (TYPE_VECTOR_SUBPARTS (rhs2_type), | |||
4425 | TYPE_VECTOR_SUBPARTS (rhs3_type))) | |||
4426 | || maybe_ne (TYPE_VECTOR_SUBPARTS (rhs3_type), | |||
4427 | TYPE_VECTOR_SUBPARTS (lhs_type))) | |||
4428 | { | |||
4429 | error ("vectors with different element number found in %qs", | |||
4430 | code_name); | |||
4431 | debug_generic_expr (lhs_type); | |||
4432 | debug_generic_expr (rhs1_type); | |||
4433 | debug_generic_expr (rhs2_type); | |||
4434 | debug_generic_expr (rhs3_type); | |||
4435 | return true; | |||
4436 | } | |||
4437 | ||||
4438 | if (TREE_CODE (TREE_TYPE (rhs3_type))((enum tree_code) (((contains_struct_check ((rhs3_type), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4438, __FUNCTION__))->typed.type))->base.code) != INTEGER_TYPE | |||
4439 | || (TREE_CODE (rhs3)((enum tree_code) (rhs3)->base.code) != VECTOR_CST | |||
4440 | && (GET_MODE_BITSIZE (SCALAR_INT_TYPE_MODE(as_a <scalar_int_mode> ((tree_class_check ((((contains_struct_check ((rhs3_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4441, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4441, __FUNCTION__))->type_common.mode)) | |||
4441 | (TREE_TYPE (rhs3_type))(as_a <scalar_int_mode> ((tree_class_check ((((contains_struct_check ((rhs3_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4441, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4441, __FUNCTION__))->type_common.mode))) | |||
4442 | != GET_MODE_BITSIZE (SCALAR_TYPE_MODE(as_a <scalar_mode> ((tree_class_check ((((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4443, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4443, __FUNCTION__))->type_common.mode)) | |||
4443 | (TREE_TYPE (rhs1_type))(as_a <scalar_mode> ((tree_class_check ((((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4443, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4443, __FUNCTION__))->type_common.mode)))))) | |||
4444 | { | |||
4445 | error ("invalid mask type in %qs", code_name); | |||
4446 | debug_generic_expr (lhs_type); | |||
4447 | debug_generic_expr (rhs1_type); | |||
4448 | debug_generic_expr (rhs2_type); | |||
4449 | debug_generic_expr (rhs3_type); | |||
4450 | return true; | |||
4451 | } | |||
4452 | ||||
4453 | return false; | |||
4454 | ||||
4455 | case SAD_EXPR: | |||
4456 | if (!useless_type_conversion_p (rhs1_type, rhs2_type) | |||
4457 | || !useless_type_conversion_p (lhs_type, rhs3_type) | |||
4458 | || 2 * GET_MODE_UNIT_BITSIZE (TYPE_MODE (TREE_TYPE (rhs1_type)))((unsigned short) (mode_to_unit_size (((((enum tree_code) ((tree_class_check ((((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4458, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4458, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4458, __FUNCTION__))->typed.type)) : (((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4458, __FUNCTION__))->typed.type))->type_common.mode) ) * (8))) | |||
4459 | > GET_MODE_UNIT_BITSIZE (TYPE_MODE (TREE_TYPE (lhs_type)))((unsigned short) (mode_to_unit_size (((((enum tree_code) ((tree_class_check ((((contains_struct_check ((lhs_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4459, __FUNCTION__))->typed.type)), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4459, __FUNCTION__)))->base.code) == VECTOR_TYPE) ? vector_type_mode (((contains_struct_check ((lhs_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4459, __FUNCTION__))->typed.type)) : (((contains_struct_check ((lhs_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4459, __FUNCTION__))->typed.type))->type_common.mode) ) * (8)))) | |||
4460 | { | |||
4461 | error ("type mismatch in %qs", code_name); | |||
4462 | debug_generic_expr (lhs_type); | |||
4463 | debug_generic_expr (rhs1_type); | |||
4464 | debug_generic_expr (rhs2_type); | |||
4465 | debug_generic_expr (rhs3_type); | |||
4466 | return true; | |||
4467 | } | |||
4468 | ||||
4469 | if (TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) != VECTOR_TYPE | |||
4470 | || TREE_CODE (rhs2_type)((enum tree_code) (rhs2_type)->base.code) != VECTOR_TYPE | |||
4471 | || TREE_CODE (rhs3_type)((enum tree_code) (rhs3_type)->base.code) != VECTOR_TYPE) | |||
4472 | { | |||
4473 | error ("vector types expected in %qs", code_name); | |||
4474 | debug_generic_expr (lhs_type); | |||
4475 | debug_generic_expr (rhs1_type); | |||
4476 | debug_generic_expr (rhs2_type); | |||
4477 | debug_generic_expr (rhs3_type); | |||
4478 | return true; | |||
4479 | } | |||
4480 | ||||
4481 | return false; | |||
4482 | ||||
4483 | case BIT_INSERT_EXPR: | |||
4484 | if (! useless_type_conversion_p (lhs_type, rhs1_type)) | |||
4485 | { | |||
4486 | error ("type mismatch in %qs", code_name); | |||
4487 | debug_generic_expr (lhs_type); | |||
4488 | debug_generic_expr (rhs1_type); | |||
4489 | return true; | |||
4490 | } | |||
4491 | if (! ((INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE ) | |||
4492 | && INTEGRAL_TYPE_P (rhs2_type)(((enum tree_code) (rhs2_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs2_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs2_type)->base.code) == INTEGER_TYPE )) | |||
4493 | /* Vector element insert. */ | |||
4494 | || (VECTOR_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE) | |||
4495 | && types_compatible_p (TREE_TYPE (rhs1_type)((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4495, __FUNCTION__))->typed.type), rhs2_type)) | |||
4496 | /* Aligned sub-vector insert. */ | |||
4497 | || (VECTOR_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE) | |||
4498 | && VECTOR_TYPE_P (rhs2_type)(((enum tree_code) (rhs2_type)->base.code) == VECTOR_TYPE) | |||
4499 | && types_compatible_p (TREE_TYPE (rhs1_type)((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4499, __FUNCTION__))->typed.type), | |||
4500 | TREE_TYPE (rhs2_type)((contains_struct_check ((rhs2_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4500, __FUNCTION__))->typed.type)) | |||
4501 | && multiple_p (TYPE_VECTOR_SUBPARTS (rhs1_type), | |||
4502 | TYPE_VECTOR_SUBPARTS (rhs2_type)) | |||
4503 | && multiple_p (wi::to_poly_offset (rhs3), | |||
4504 | wi::to_poly_offset (TYPE_SIZE (rhs2_type)((tree_class_check ((rhs2_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4504, __FUNCTION__))->type_common.size)))))) | |||
4505 | { | |||
4506 | error ("not allowed type combination in %qs", code_name); | |||
4507 | debug_generic_expr (rhs1_type); | |||
4508 | debug_generic_expr (rhs2_type); | |||
4509 | return true; | |||
4510 | } | |||
4511 | if (! tree_fits_uhwi_p (rhs3) | |||
4512 | || ! types_compatible_p (bitsizetypesizetype_tab[(int) stk_bitsizetype], TREE_TYPE (rhs3)((contains_struct_check ((rhs3), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4512, __FUNCTION__))->typed.type)) | |||
4513 | || ! tree_fits_uhwi_p (TYPE_SIZE (rhs2_type)((tree_class_check ((rhs2_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4513, __FUNCTION__))->type_common.size))) | |||
4514 | { | |||
4515 | error ("invalid position or size in %qs", code_name); | |||
4516 | return true; | |||
4517 | } | |||
4518 | if (INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE ) | |||
4519 | && !type_has_mode_precision_p (rhs1_type)) | |||
4520 | { | |||
4521 | error ("%qs into non-mode-precision operand", code_name); | |||
4522 | return true; | |||
4523 | } | |||
4524 | if (INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE )) | |||
4525 | { | |||
4526 | unsigned HOST_WIDE_INTlong bitpos = tree_to_uhwi (rhs3); | |||
4527 | if (bitpos >= TYPE_PRECISION (rhs1_type)((tree_class_check ((rhs1_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4527, __FUNCTION__))->type_common.precision) | |||
4528 | || (bitpos + TYPE_PRECISION (rhs2_type)((tree_class_check ((rhs2_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4528, __FUNCTION__))->type_common.precision) | |||
4529 | > TYPE_PRECISION (rhs1_type)((tree_class_check ((rhs1_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4529, __FUNCTION__))->type_common.precision))) | |||
4530 | { | |||
4531 | error ("insertion out of range in %qs", code_name); | |||
4532 | return true; | |||
4533 | } | |||
4534 | } | |||
4535 | else if (VECTOR_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE)) | |||
4536 | { | |||
4537 | unsigned HOST_WIDE_INTlong bitpos = tree_to_uhwi (rhs3); | |||
4538 | unsigned HOST_WIDE_INTlong bitsize = tree_to_uhwi (TYPE_SIZE (rhs2_type)((tree_class_check ((rhs2_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4538, __FUNCTION__))->type_common.size)); | |||
4539 | if (bitpos % bitsize != 0) | |||
4540 | { | |||
4541 | error ("%qs not at element boundary", code_name); | |||
4542 | return true; | |||
4543 | } | |||
4544 | } | |||
4545 | return false; | |||
4546 | ||||
4547 | case DOT_PROD_EXPR: | |||
4548 | { | |||
4549 | if (((TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) != VECTOR_TYPE | |||
4550 | || TREE_CODE (lhs_type)((enum tree_code) (lhs_type)->base.code) != VECTOR_TYPE) | |||
4551 | && ((!INTEGRAL_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (rhs1_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (rhs1_type)->base.code) == INTEGER_TYPE ) | |||
4552 | && !SCALAR_FLOAT_TYPE_P (rhs1_type)(((enum tree_code) (rhs1_type)->base.code) == REAL_TYPE)) | |||
4553 | || (!INTEGRAL_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (lhs_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (lhs_type)->base.code) == INTEGER_TYPE ) | |||
4554 | && !SCALAR_FLOAT_TYPE_P (lhs_type)(((enum tree_code) (lhs_type)->base.code) == REAL_TYPE)))) | |||
4555 | /* rhs1_type and rhs2_type may differ in sign. */ | |||
4556 | || !tree_nop_conversion_p (rhs1_type, rhs2_type) | |||
4557 | || !useless_type_conversion_p (lhs_type, rhs3_type) | |||
4558 | || maybe_lt (GET_MODE_SIZE (element_mode (rhs3_type)), | |||
4559 | 2 * GET_MODE_SIZE (element_mode (rhs1_type)))) | |||
4560 | { | |||
4561 | error ("type mismatch in %qs", code_name); | |||
4562 | debug_generic_expr (lhs_type); | |||
4563 | debug_generic_expr (rhs1_type); | |||
4564 | debug_generic_expr (rhs2_type); | |||
4565 | return true; | |||
4566 | } | |||
4567 | return false; | |||
4568 | } | |||
4569 | ||||
4570 | case REALIGN_LOAD_EXPR: | |||
4571 | /* FIXME. */ | |||
4572 | return false; | |||
4573 | ||||
4574 | default: | |||
4575 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4575, __FUNCTION__)); | |||
4576 | } | |||
4577 | return false; | |||
4578 | } | |||
4579 | ||||
4580 | /* Verify a gimple assignment statement STMT with a single rhs. | |||
4581 | Returns true if anything is wrong. */ | |||
4582 | ||||
4583 | static bool | |||
4584 | verify_gimple_assign_single (gassign *stmt) | |||
4585 | { | |||
4586 | enum tree_code rhs_code = gimple_assign_rhs_code (stmt); | |||
4587 | tree lhs = gimple_assign_lhs (stmt); | |||
4588 | tree lhs_type = TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4588, __FUNCTION__))->typed.type); | |||
4589 | tree rhs1 = gimple_assign_rhs1 (stmt); | |||
4590 | tree rhs1_type = TREE_TYPE (rhs1)((contains_struct_check ((rhs1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4590, __FUNCTION__))->typed.type); | |||
4591 | bool res = false; | |||
4592 | ||||
4593 | const char* const code_name = get_tree_code_name (rhs_code); | |||
4594 | ||||
4595 | if (!useless_type_conversion_p (lhs_type, rhs1_type)) | |||
4596 | { | |||
4597 | error ("non-trivial conversion in %qs", code_name); | |||
4598 | debug_generic_expr (lhs_type); | |||
4599 | debug_generic_expr (rhs1_type); | |||
4600 | return true; | |||
4601 | } | |||
4602 | ||||
4603 | if (gimple_clobber_p (stmt) | |||
4604 | && !(DECL_P (lhs)(tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code ) (lhs)->base.code))] == tcc_declaration) || TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) == MEM_REF)) | |||
4605 | { | |||
4606 | error ("%qs LHS in clobber statement", | |||
4607 | get_tree_code_name (TREE_CODE (lhs)((enum tree_code) (lhs)->base.code))); | |||
4608 | debug_generic_expr (lhs); | |||
4609 | return true; | |||
4610 | } | |||
4611 | ||||
4612 | if (TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) == WITH_SIZE_EXPR) | |||
4613 | { | |||
4614 | error ("%qs LHS in assignment statement", | |||
4615 | get_tree_code_name (TREE_CODE (lhs)((enum tree_code) (lhs)->base.code))); | |||
4616 | debug_generic_expr (lhs); | |||
4617 | return true; | |||
4618 | } | |||
4619 | ||||
4620 | if (handled_component_p (lhs) | |||
4621 | || TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) == MEM_REF | |||
4622 | || TREE_CODE (lhs)((enum tree_code) (lhs)->base.code) == TARGET_MEM_REF) | |||
4623 | res |= verify_types_in_gimple_reference (lhs, true); | |||
4624 | ||||
4625 | /* Special codes we cannot handle via their class. */ | |||
4626 | switch (rhs_code) | |||
4627 | { | |||
4628 | case ADDR_EXPR: | |||
4629 | { | |||
4630 | tree op = TREE_OPERAND (rhs1, 0)(*((const_cast<tree*> (tree_operand_check ((rhs1), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4630, __FUNCTION__))))); | |||
4631 | if (!is_gimple_addressable (op)) | |||
4632 | { | |||
4633 | error ("invalid operand in %qs", code_name); | |||
4634 | return true; | |||
4635 | } | |||
4636 | ||||
4637 | /* Technically there is no longer a need for matching types, but | |||
4638 | gimple hygiene asks for this check. In LTO we can end up | |||
4639 | combining incompatible units and thus end up with addresses | |||
4640 | of globals that change their type to a common one. */ | |||
4641 | if (!in_lto_pglobal_options.x_in_lto_p | |||
4642 | && !types_compatible_p (TREE_TYPE (op)((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4642, __FUNCTION__))->typed.type), | |||
4643 | TREE_TYPE (TREE_TYPE (rhs1))((contains_struct_check ((((contains_struct_check ((rhs1), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4643, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4643, __FUNCTION__))->typed.type)) | |||
4644 | && !one_pointer_to_useless_type_conversion_p (TREE_TYPE (rhs1)((contains_struct_check ((rhs1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4644, __FUNCTION__))->typed.type), | |||
4645 | TREE_TYPE (op)((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4645, __FUNCTION__))->typed.type))) | |||
4646 | { | |||
4647 | error ("type mismatch in %qs", code_name); | |||
4648 | debug_generic_stmt (TREE_TYPE (rhs1)((contains_struct_check ((rhs1), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4648, __FUNCTION__))->typed.type)); | |||
4649 | debug_generic_stmt (TREE_TYPE (op)((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4649, __FUNCTION__))->typed.type)); | |||
4650 | return true; | |||
4651 | } | |||
4652 | ||||
4653 | return (verify_address (rhs1, true) | |||
4654 | || verify_types_in_gimple_reference (op, true)); | |||
4655 | } | |||
4656 | ||||
4657 | /* tcc_reference */ | |||
4658 | case INDIRECT_REF: | |||
4659 | error ("%qs in gimple IL", code_name); | |||
4660 | return true; | |||
4661 | ||||
4662 | case COMPONENT_REF: | |||
4663 | case BIT_FIELD_REF: | |||
4664 | case ARRAY_REF: | |||
4665 | case ARRAY_RANGE_REF: | |||
4666 | case VIEW_CONVERT_EXPR: | |||
4667 | case REALPART_EXPR: | |||
4668 | case IMAGPART_EXPR: | |||
4669 | case TARGET_MEM_REF: | |||
4670 | case MEM_REF: | |||
4671 | if (!is_gimple_reg (lhs) | |||
4672 | && is_gimple_reg_type (TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4672, __FUNCTION__))->typed.type))) | |||
4673 | { | |||
4674 | error ("invalid RHS for gimple memory store: %qs", code_name); | |||
4675 | debug_generic_stmt (lhs); | |||
4676 | debug_generic_stmt (rhs1); | |||
4677 | return true; | |||
4678 | } | |||
4679 | return res || verify_types_in_gimple_reference (rhs1, false); | |||
4680 | ||||
4681 | /* tcc_constant */ | |||
4682 | case SSA_NAME: | |||
4683 | case INTEGER_CST: | |||
4684 | case REAL_CST: | |||
4685 | case FIXED_CST: | |||
4686 | case COMPLEX_CST: | |||
4687 | case VECTOR_CST: | |||
4688 | case STRING_CST: | |||
4689 | return res; | |||
4690 | ||||
4691 | /* tcc_declaration */ | |||
4692 | case CONST_DECL: | |||
4693 | return res; | |||
4694 | case VAR_DECL: | |||
4695 | case PARM_DECL: | |||
4696 | if (!is_gimple_reg (lhs) | |||
4697 | && !is_gimple_reg (rhs1) | |||
4698 | && is_gimple_reg_type (TREE_TYPE (lhs)((contains_struct_check ((lhs), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4698, __FUNCTION__))->typed.type))) | |||
4699 | { | |||
4700 | error ("invalid RHS for gimple memory store: %qs", code_name); | |||
4701 | debug_generic_stmt (lhs); | |||
4702 | debug_generic_stmt (rhs1); | |||
4703 | return true; | |||
4704 | } | |||
4705 | return res; | |||
4706 | ||||
4707 | case CONSTRUCTOR: | |||
4708 | if (TREE_CODE (rhs1_type)((enum tree_code) (rhs1_type)->base.code) == VECTOR_TYPE) | |||
4709 | { | |||
4710 | unsigned int i; | |||
4711 | tree elt_i, elt_v, elt_t = NULL_TREE(tree) nullptr; | |||
4712 | ||||
4713 | if (CONSTRUCTOR_NELTS (rhs1)(vec_safe_length (((tree_check ((rhs1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4713, __FUNCTION__, (CONSTRUCTOR)))->constructor.elts))) == 0) | |||
4714 | return res; | |||
4715 | /* For vector CONSTRUCTORs we require that either it is empty | |||
4716 | CONSTRUCTOR, or it is a CONSTRUCTOR of smaller vector elements | |||
4717 | (then the element count must be correct to cover the whole | |||
4718 | outer vector and index must be NULL on all elements, or it is | |||
4719 | a CONSTRUCTOR of scalar elements, where we as an exception allow | |||
4720 | smaller number of elements (assuming zero filling) and | |||
4721 | consecutive indexes as compared to NULL indexes (such | |||
4722 | CONSTRUCTORs can appear in the IL from FEs). */ | |||
4723 | FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (rhs1), i, elt_i, elt_v)for (i = 0; (i >= vec_safe_length (((tree_check ((rhs1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4723, __FUNCTION__, (CONSTRUCTOR)))->constructor.elts))) ? false : (((void) (elt_v = (*((tree_check ((rhs1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4723, __FUNCTION__, (CONSTRUCTOR)))->constructor.elts))[ i].value)), (elt_i = (*((tree_check ((rhs1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4723, __FUNCTION__, (CONSTRUCTOR)))->constructor.elts))[ i].index), true); (i)++) | |||
4724 | { | |||
4725 | if (elt_t == NULL_TREE(tree) nullptr) | |||
4726 | { | |||
4727 | elt_t = TREE_TYPE (elt_v)((contains_struct_check ((elt_v), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4727, __FUNCTION__))->typed.type); | |||
4728 | if (TREE_CODE (elt_t)((enum tree_code) (elt_t)->base.code) == VECTOR_TYPE) | |||
4729 | { | |||
4730 | tree elt_t = TREE_TYPE (elt_v)((contains_struct_check ((elt_v), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4730, __FUNCTION__))->typed.type); | |||
4731 | if (!useless_type_conversion_p (TREE_TYPE (rhs1_type)((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4731, __FUNCTION__))->typed.type), | |||
4732 | TREE_TYPE (elt_t)((contains_struct_check ((elt_t), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4732, __FUNCTION__))->typed.type))) | |||
4733 | { | |||
4734 | error ("incorrect type of vector %qs elements", | |||
4735 | code_name); | |||
4736 | debug_generic_stmt (rhs1); | |||
4737 | return true; | |||
4738 | } | |||
4739 | else if (maybe_ne (CONSTRUCTOR_NELTS (rhs1)(vec_safe_length (((tree_check ((rhs1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4739, __FUNCTION__, (CONSTRUCTOR)))->constructor.elts))) | |||
4740 | * TYPE_VECTOR_SUBPARTS (elt_t), | |||
4741 | TYPE_VECTOR_SUBPARTS (rhs1_type))) | |||
4742 | { | |||
4743 | error ("incorrect number of vector %qs elements", | |||
4744 | code_name); | |||
4745 | debug_generic_stmt (rhs1); | |||
4746 | return true; | |||
4747 | } | |||
4748 | } | |||
4749 | else if (!useless_type_conversion_p (TREE_TYPE (rhs1_type)((contains_struct_check ((rhs1_type), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4749, __FUNCTION__))->typed.type), | |||
4750 | elt_t)) | |||
4751 | { | |||
4752 | error ("incorrect type of vector %qs elements", | |||
4753 | code_name); | |||
4754 | debug_generic_stmt (rhs1); | |||
4755 | return true; | |||
4756 | } | |||
4757 | else if (maybe_gt (CONSTRUCTOR_NELTS (rhs1),maybe_lt (TYPE_VECTOR_SUBPARTS (rhs1_type), (vec_safe_length ( ((tree_check ((rhs1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4757, __FUNCTION__, (CONSTRUCTOR)))->constructor.elts))) ) | |||
4758 | TYPE_VECTOR_SUBPARTS (rhs1_type))maybe_lt (TYPE_VECTOR_SUBPARTS (rhs1_type), (vec_safe_length ( ((tree_check ((rhs1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4757, __FUNCTION__, (CONSTRUCTOR)))->constructor.elts))) )) | |||
4759 | { | |||
4760 | error ("incorrect number of vector %qs elements", | |||
4761 | code_name); | |||
4762 | debug_generic_stmt (rhs1); | |||
4763 | return true; | |||
4764 | } | |||
4765 | } | |||
4766 | else if (!useless_type_conversion_p (elt_t, TREE_TYPE (elt_v)((contains_struct_check ((elt_v), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4766, __FUNCTION__))->typed.type))) | |||
4767 | { | |||
4768 | error ("incorrect type of vector CONSTRUCTOR elements"); | |||
4769 | debug_generic_stmt (rhs1); | |||
4770 | return true; | |||
4771 | } | |||
4772 | if (elt_i != NULL_TREE(tree) nullptr | |||
4773 | && (TREE_CODE (elt_t)((enum tree_code) (elt_t)->base.code) == VECTOR_TYPE | |||
4774 | || TREE_CODE (elt_i)((enum tree_code) (elt_i)->base.code) != INTEGER_CST | |||
4775 | || compare_tree_int (elt_i, i) != 0)) | |||
4776 | { | |||
4777 | error ("vector %qs with non-NULL element index", | |||
4778 | code_name); | |||
4779 | debug_generic_stmt (rhs1); | |||
4780 | return true; | |||
4781 | } | |||
4782 | if (!is_gimple_val (elt_v)) | |||
4783 | { | |||
4784 | error ("vector %qs element is not a GIMPLE value", | |||
4785 | code_name); | |||
4786 | debug_generic_stmt (rhs1); | |||
4787 | return true; | |||
4788 | } | |||
4789 | } | |||
4790 | } | |||
4791 | else if (CONSTRUCTOR_NELTS (rhs1)(vec_safe_length (((tree_check ((rhs1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4791, __FUNCTION__, (CONSTRUCTOR)))->constructor.elts))) != 0) | |||
4792 | { | |||
4793 | error ("non-vector %qs with elements", code_name); | |||
4794 | debug_generic_stmt (rhs1); | |||
4795 | return true; | |||
4796 | } | |||
4797 | return res; | |||
4798 | ||||
4799 | case WITH_SIZE_EXPR: | |||
4800 | error ("%qs RHS in assignment statement", | |||
4801 | get_tree_code_name (rhs_code)); | |||
4802 | debug_generic_expr (rhs1); | |||
4803 | return true; | |||
4804 | ||||
4805 | case OBJ_TYPE_REF: | |||
4806 | /* FIXME. */ | |||
4807 | return res; | |||
4808 | ||||
4809 | default:; | |||
4810 | } | |||
4811 | ||||
4812 | return res; | |||
4813 | } | |||
4814 | ||||
4815 | /* Verify the contents of a GIMPLE_ASSIGN STMT. Returns true when there | |||
4816 | is a problem, otherwise false. */ | |||
4817 | ||||
4818 | static bool | |||
4819 | verify_gimple_assign (gassign *stmt) | |||
4820 | { | |||
4821 | switch (gimple_assign_rhs_class (stmt)) | |||
4822 | { | |||
4823 | case GIMPLE_SINGLE_RHS: | |||
4824 | return verify_gimple_assign_single (stmt); | |||
4825 | ||||
4826 | case GIMPLE_UNARY_RHS: | |||
4827 | return verify_gimple_assign_unary (stmt); | |||
4828 | ||||
4829 | case GIMPLE_BINARY_RHS: | |||
4830 | return verify_gimple_assign_binary (stmt); | |||
4831 | ||||
4832 | case GIMPLE_TERNARY_RHS: | |||
4833 | return verify_gimple_assign_ternary (stmt); | |||
4834 | ||||
4835 | default: | |||
4836 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4836, __FUNCTION__)); | |||
4837 | } | |||
4838 | } | |||
4839 | ||||
4840 | /* Verify the contents of a GIMPLE_RETURN STMT. Returns true when there | |||
4841 | is a problem, otherwise false. */ | |||
4842 | ||||
4843 | static bool | |||
4844 | verify_gimple_return (greturn *stmt) | |||
4845 | { | |||
4846 | tree op = gimple_return_retval (stmt); | |||
4847 | tree restype = TREE_TYPE (TREE_TYPE (cfun->decl))((contains_struct_check ((((contains_struct_check (((cfun + 0 )->decl), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4847, __FUNCTION__))->typed.type)), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4847, __FUNCTION__))->typed.type); | |||
4848 | ||||
4849 | /* We cannot test for present return values as we do not fix up missing | |||
4850 | return values from the original source. */ | |||
4851 | if (op == NULLnullptr) | |||
4852 | return false; | |||
4853 | ||||
4854 | if (!is_gimple_val (op) | |||
4855 | && TREE_CODE (op)((enum tree_code) (op)->base.code) != RESULT_DECL) | |||
4856 | { | |||
4857 | error ("invalid operand in return statement"); | |||
4858 | debug_generic_stmt (op); | |||
4859 | return true; | |||
4860 | } | |||
4861 | ||||
4862 | if ((TREE_CODE (op)((enum tree_code) (op)->base.code) == RESULT_DECL | |||
4863 | && DECL_BY_REFERENCE (op)((tree_check3 ((op), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4863, __FUNCTION__, (VAR_DECL), (PARM_DECL), (RESULT_DECL)) )->decl_common.decl_by_reference_flag)) | |||
4864 | || (TREE_CODE (op)((enum tree_code) (op)->base.code) == SSA_NAME | |||
4865 | && SSA_NAME_VAR (op)((tree_check ((op), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4865, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((op)->ssa_name.var)->base .code) == IDENTIFIER_NODE ? (tree) nullptr : (op)->ssa_name .var) | |||
4866 | && TREE_CODE (SSA_NAME_VAR (op))((enum tree_code) (((tree_check ((op), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4866, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((op)->ssa_name.var)->base .code) == IDENTIFIER_NODE ? (tree) nullptr : (op)->ssa_name .var))->base.code) == RESULT_DECL | |||
4867 | && DECL_BY_REFERENCE (SSA_NAME_VAR (op))((tree_check3 ((((tree_check ((op), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4867, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((op)->ssa_name.var)->base .code) == IDENTIFIER_NODE ? (tree) nullptr : (op)->ssa_name .var)), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4867, __FUNCTION__, (VAR_DECL), (PARM_DECL), (RESULT_DECL)) )->decl_common.decl_by_reference_flag))) | |||
4868 | op = TREE_TYPE (op)((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4868, __FUNCTION__))->typed.type); | |||
4869 | ||||
4870 | if (!useless_type_conversion_p (restype, TREE_TYPE (op)((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4870, __FUNCTION__))->typed.type))) | |||
4871 | { | |||
4872 | error ("invalid conversion in return statement"); | |||
4873 | debug_generic_stmt (restype); | |||
4874 | debug_generic_stmt (TREE_TYPE (op)((contains_struct_check ((op), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4874, __FUNCTION__))->typed.type)); | |||
4875 | return true; | |||
4876 | } | |||
4877 | ||||
4878 | return false; | |||
4879 | } | |||
4880 | ||||
4881 | ||||
4882 | /* Verify the contents of a GIMPLE_GOTO STMT. Returns true when there | |||
4883 | is a problem, otherwise false. */ | |||
4884 | ||||
4885 | static bool | |||
4886 | verify_gimple_goto (ggoto *stmt) | |||
4887 | { | |||
4888 | tree dest = gimple_goto_dest (stmt); | |||
4889 | ||||
4890 | /* ??? We have two canonical forms of direct goto destinations, a | |||
4891 | bare LABEL_DECL and an ADDR_EXPR of a LABEL_DECL. */ | |||
4892 | if (TREE_CODE (dest)((enum tree_code) (dest)->base.code) != LABEL_DECL | |||
4893 | && (!is_gimple_val (dest) | |||
4894 | || !POINTER_TYPE_P (TREE_TYPE (dest))(((enum tree_code) (((contains_struct_check ((dest), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4894, __FUNCTION__))->typed.type))->base.code) == POINTER_TYPE || ((enum tree_code) (((contains_struct_check ((dest), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4894, __FUNCTION__))->typed.type))->base.code) == REFERENCE_TYPE ))) | |||
4895 | { | |||
4896 | error ("goto destination is neither a label nor a pointer"); | |||
4897 | return true; | |||
4898 | } | |||
4899 | ||||
4900 | return false; | |||
4901 | } | |||
4902 | ||||
4903 | /* Verify the contents of a GIMPLE_SWITCH STMT. Returns true when there | |||
4904 | is a problem, otherwise false. */ | |||
4905 | ||||
4906 | static bool | |||
4907 | verify_gimple_switch (gswitch *stmt) | |||
4908 | { | |||
4909 | unsigned int i, n; | |||
4910 | tree elt, prev_upper_bound = NULL_TREE(tree) nullptr; | |||
4911 | tree index_type, elt_type = NULL_TREE(tree) nullptr; | |||
4912 | ||||
4913 | if (!is_gimple_val (gimple_switch_index (stmt))) | |||
4914 | { | |||
4915 | error ("invalid operand to switch statement"); | |||
4916 | debug_generic_stmt (gimple_switch_index (stmt)); | |||
4917 | return true; | |||
4918 | } | |||
4919 | ||||
4920 | index_type = TREE_TYPE (gimple_switch_index (stmt))((contains_struct_check ((gimple_switch_index (stmt)), (TS_TYPED ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4920, __FUNCTION__))->typed.type); | |||
4921 | if (! INTEGRAL_TYPE_P (index_type)(((enum tree_code) (index_type)->base.code) == ENUMERAL_TYPE || ((enum tree_code) (index_type)->base.code) == BOOLEAN_TYPE || ((enum tree_code) (index_type)->base.code) == INTEGER_TYPE )) | |||
4922 | { | |||
4923 | error ("non-integral type switch statement"); | |||
4924 | debug_generic_expr (index_type); | |||
4925 | return true; | |||
4926 | } | |||
4927 | ||||
4928 | elt = gimple_switch_label (stmt, 0); | |||
4929 | if (CASE_LOW (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4929, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4929, __FUNCTION__))))) != NULL_TREE(tree) nullptr | |||
4930 | || CASE_HIGH (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4930, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4930, __FUNCTION__))))) != NULL_TREE(tree) nullptr | |||
4931 | || CASE_CHAIN (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4931, __FUNCTION__, (CASE_LABEL_EXPR)))), (3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4931, __FUNCTION__))))) != NULL_TREE(tree) nullptr) | |||
4932 | { | |||
4933 | error ("invalid default case label in switch statement"); | |||
4934 | debug_generic_expr (elt); | |||
4935 | return true; | |||
4936 | } | |||
4937 | ||||
4938 | n = gimple_switch_num_labels (stmt); | |||
4939 | for (i = 1; i < n; i++) | |||
4940 | { | |||
4941 | elt = gimple_switch_label (stmt, i); | |||
4942 | ||||
4943 | if (CASE_CHAIN (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4943, __FUNCTION__, (CASE_LABEL_EXPR)))), (3), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4943, __FUNCTION__)))))) | |||
4944 | { | |||
4945 | error ("invalid %<CASE_CHAIN%>"); | |||
4946 | debug_generic_expr (elt); | |||
4947 | return true; | |||
4948 | } | |||
4949 | if (! CASE_LOW (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4949, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4949, __FUNCTION__)))))) | |||
4950 | { | |||
4951 | error ("invalid case label in switch statement"); | |||
4952 | debug_generic_expr (elt); | |||
4953 | return true; | |||
4954 | } | |||
4955 | if (CASE_HIGH (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4955, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4955, __FUNCTION__))))) | |||
4956 | && ! tree_int_cst_lt (CASE_LOW (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4956, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4956, __FUNCTION__))))), CASE_HIGH (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4956, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4956, __FUNCTION__))))))) | |||
4957 | { | |||
4958 | error ("invalid case range in switch statement"); | |||
4959 | debug_generic_expr (elt); | |||
4960 | return true; | |||
4961 | } | |||
4962 | ||||
4963 | if (! elt_type) | |||
4964 | { | |||
4965 | elt_type = TREE_TYPE (CASE_LOW (elt))((contains_struct_check (((*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4965, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4965, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4965, __FUNCTION__))->typed.type); | |||
4966 | if (TYPE_PRECISION (index_type)((tree_class_check ((index_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4966, __FUNCTION__))->type_common.precision) < TYPE_PRECISION (elt_type)((tree_class_check ((elt_type), (tcc_type), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4966, __FUNCTION__))->type_common.precision)) | |||
4967 | { | |||
4968 | error ("type precision mismatch in switch statement"); | |||
4969 | return true; | |||
4970 | } | |||
4971 | } | |||
4972 | if (TREE_TYPE (CASE_LOW (elt))((contains_struct_check (((*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4972, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4972, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4972, __FUNCTION__))->typed.type) != elt_type | |||
4973 | || (CASE_HIGH (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4973, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4973, __FUNCTION__))))) && TREE_TYPE (CASE_HIGH (elt))((contains_struct_check (((*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4973, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4973, __FUNCTION__)))))), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4973, __FUNCTION__))->typed.type) != elt_type)) | |||
4974 | { | |||
4975 | error ("type mismatch for case label in switch statement"); | |||
4976 | debug_generic_expr (elt); | |||
4977 | return true; | |||
4978 | } | |||
4979 | ||||
4980 | if (prev_upper_bound) | |||
4981 | { | |||
4982 | if (! tree_int_cst_lt (prev_upper_bound, CASE_LOW (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4982, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4982, __FUNCTION__))))))) | |||
4983 | { | |||
4984 | error ("case labels not sorted in switch statement"); | |||
4985 | return true; | |||
4986 | } | |||
4987 | } | |||
4988 | ||||
4989 | prev_upper_bound = CASE_HIGH (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4989, __FUNCTION__, (CASE_LABEL_EXPR)))), (1), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4989, __FUNCTION__))))); | |||
4990 | if (! prev_upper_bound) | |||
4991 | prev_upper_bound = CASE_LOW (elt)(*((const_cast<tree*> (tree_operand_check (((tree_check ((elt), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4991, __FUNCTION__, (CASE_LABEL_EXPR)))), (0), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 4991, __FUNCTION__))))); | |||
4992 | } | |||
4993 | ||||
4994 | return false; | |||
4995 | } | |||
4996 | ||||
4997 | /* Verify a gimple debug statement STMT. | |||
4998 | Returns true if anything is wrong. */ | |||
4999 | ||||
5000 | static bool | |||
5001 | verify_gimple_debug (gimple *stmt ATTRIBUTE_UNUSED__attribute__ ((__unused__))) | |||
5002 | { | |||
5003 | /* There isn't much that could be wrong in a gimple debug stmt. A | |||
5004 | gimple debug bind stmt, for example, maps a tree, that's usually | |||
5005 | a VAR_DECL or a PARM_DECL, but that could also be some scalarized | |||
5006 | component or member of an aggregate type, to another tree, that | |||
5007 | can be an arbitrary expression. These stmts expand into debug | |||
5008 | insns, and are converted to debug notes by var-tracking.cc. */ | |||
5009 | return false; | |||
5010 | } | |||
5011 | ||||
5012 | /* Verify a gimple label statement STMT. | |||
5013 | Returns true if anything is wrong. */ | |||
5014 | ||||
5015 | static bool | |||
5016 | verify_gimple_label (glabel *stmt) | |||
5017 | { | |||
5018 | tree decl = gimple_label_label (stmt); | |||
5019 | int uid; | |||
5020 | bool err = false; | |||
5021 | ||||
5022 | if (TREE_CODE (decl)((enum tree_code) (decl)->base.code) != LABEL_DECL) | |||
5023 | return true; | |||
5024 | if (!DECL_NONLOCAL (decl)((contains_struct_check ((decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5024, __FUNCTION__))->decl_common.nonlocal_flag) && !FORCED_LABEL (decl)((tree_check ((decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5024, __FUNCTION__, (LABEL_DECL)))->base.side_effects_flag ) | |||
5025 | && DECL_CONTEXT (decl)((contains_struct_check ((decl), (TS_DECL_MINIMAL), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5025, __FUNCTION__))->decl_minimal.context) != current_function_decl) | |||
5026 | { | |||
5027 | error ("label context is not the current function declaration"); | |||
5028 | err |= true; | |||
5029 | } | |||
5030 | ||||
5031 | uid = LABEL_DECL_UID (decl)((tree_check ((decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5031, __FUNCTION__, (LABEL_DECL)))->label_decl.label_decl_uid ); | |||
5032 | if (cfun(cfun + 0)->cfg | |||
5033 | && (uid == -1 | |||
5034 | || (*label_to_block_map_for_fn (cfun)(((cfun + 0))->cfg->x_label_to_block_map))[uid] != gimple_bb (stmt))) | |||
5035 | { | |||
5036 | error ("incorrect entry in %<label_to_block_map%>"); | |||
5037 | err |= true; | |||
5038 | } | |||
5039 | ||||
5040 | uid = EH_LANDING_PAD_NR (decl)((tree_check ((decl), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5040, __FUNCTION__, (LABEL_DECL)))->label_decl.eh_landing_pad_nr ); | |||
5041 | if (uid) | |||
5042 | { | |||
5043 | eh_landing_pad lp = get_eh_landing_pad_from_number (uid); | |||
5044 | if (decl != lp->post_landing_pad) | |||
5045 | { | |||
5046 | error ("incorrect setting of landing pad number"); | |||
5047 | err |= true; | |||
5048 | } | |||
5049 | } | |||
5050 | ||||
5051 | return err; | |||
5052 | } | |||
5053 | ||||
5054 | /* Verify a gimple cond statement STMT. | |||
5055 | Returns true if anything is wrong. */ | |||
5056 | ||||
5057 | static bool | |||
5058 | verify_gimple_cond (gcond *stmt) | |||
5059 | { | |||
5060 | if (TREE_CODE_CLASS (gimple_cond_code (stmt))tree_code_type_tmpl <0>::tree_code_type[(int) (gimple_cond_code (stmt))] != tcc_comparison) | |||
5061 | { | |||
5062 | error ("invalid comparison code in gimple cond"); | |||
5063 | return true; | |||
5064 | } | |||
5065 | if (!(!gimple_cond_true_label (stmt) | |||
5066 | || TREE_CODE (gimple_cond_true_label (stmt))((enum tree_code) (gimple_cond_true_label (stmt))->base.code ) == LABEL_DECL) | |||
5067 | || !(!gimple_cond_false_label (stmt) | |||
5068 | || TREE_CODE (gimple_cond_false_label (stmt))((enum tree_code) (gimple_cond_false_label (stmt))->base.code ) == LABEL_DECL)) | |||
5069 | { | |||
5070 | error ("invalid labels in gimple cond"); | |||
5071 | return true; | |||
5072 | } | |||
5073 | ||||
5074 | return verify_gimple_comparison (boolean_type_nodeglobal_trees[TI_BOOLEAN_TYPE], | |||
5075 | gimple_cond_lhs (stmt), | |||
5076 | gimple_cond_rhs (stmt), | |||
5077 | gimple_cond_code (stmt)); | |||
5078 | } | |||
5079 | ||||
5080 | /* Verify the GIMPLE statement STMT. Returns true if there is an | |||
5081 | error, otherwise false. */ | |||
5082 | ||||
5083 | static bool | |||
5084 | verify_gimple_stmt (gimple *stmt) | |||
5085 | { | |||
5086 | switch (gimple_code (stmt)) | |||
5087 | { | |||
5088 | case GIMPLE_ASSIGN: | |||
5089 | return verify_gimple_assign (as_a <gassign *> (stmt)); | |||
5090 | ||||
5091 | case GIMPLE_LABEL: | |||
5092 | return verify_gimple_label (as_a <glabel *> (stmt)); | |||
5093 | ||||
5094 | case GIMPLE_CALL: | |||
5095 | return verify_gimple_call (as_a <gcall *> (stmt)); | |||
5096 | ||||
5097 | case GIMPLE_COND: | |||
5098 | return verify_gimple_cond (as_a <gcond *> (stmt)); | |||
5099 | ||||
5100 | case GIMPLE_GOTO: | |||
5101 | return verify_gimple_goto (as_a <ggoto *> (stmt)); | |||
5102 | ||||
5103 | case GIMPLE_SWITCH: | |||
5104 | return verify_gimple_switch (as_a <gswitch *> (stmt)); | |||
5105 | ||||
5106 | case GIMPLE_RETURN: | |||
5107 | return verify_gimple_return (as_a <greturn *> (stmt)); | |||
5108 | ||||
5109 | case GIMPLE_ASM: | |||
5110 | return false; | |||
5111 | ||||
5112 | case GIMPLE_TRANSACTION: | |||
5113 | return verify_gimple_transaction (as_a <gtransaction *> (stmt)); | |||
5114 | ||||
5115 | /* Tuples that do not have tree operands. */ | |||
5116 | case GIMPLE_NOP: | |||
5117 | case GIMPLE_PREDICT: | |||
5118 | case GIMPLE_RESX: | |||
5119 | case GIMPLE_EH_DISPATCH: | |||
5120 | case GIMPLE_EH_MUST_NOT_THROW: | |||
5121 | return false; | |||
5122 | ||||
5123 | CASE_GIMPLE_OMPcase GIMPLE_OMP_PARALLEL: case GIMPLE_OMP_TASK: case GIMPLE_OMP_FOR : case GIMPLE_OMP_SECTIONS: case GIMPLE_OMP_SECTIONS_SWITCH: case GIMPLE_OMP_SINGLE: case GIMPLE_OMP_TARGET: case GIMPLE_OMP_TEAMS : case GIMPLE_OMP_SCOPE: case GIMPLE_OMP_SECTION: case GIMPLE_OMP_MASTER : case GIMPLE_OMP_MASKED: case GIMPLE_OMP_TASKGROUP: case GIMPLE_OMP_ORDERED : case GIMPLE_OMP_CRITICAL: case GIMPLE_OMP_SCAN: case GIMPLE_OMP_RETURN : case GIMPLE_OMP_ATOMIC_LOAD: case GIMPLE_OMP_ATOMIC_STORE: case GIMPLE_OMP_CONTINUE: | |||
5124 | /* OpenMP directives are validated by the FE and never operated | |||
5125 | on by the optimizers. Furthermore, GIMPLE_OMP_FOR may contain | |||
5126 | non-gimple expressions when the main index variable has had | |||
5127 | its address taken. This does not affect the loop itself | |||
5128 | because the header of an GIMPLE_OMP_FOR is merely used to determine | |||
5129 | how to setup the parallel iteration. */ | |||
5130 | return false; | |||
5131 | ||||
5132 | case GIMPLE_ASSUME: | |||
5133 | return false; | |||
5134 | ||||
5135 | case GIMPLE_DEBUG: | |||
5136 | return verify_gimple_debug (stmt); | |||
5137 | ||||
5138 | default: | |||
5139 | gcc_unreachable ()(fancy_abort ("/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5139, __FUNCTION__)); | |||
5140 | } | |||
5141 | } | |||
5142 | ||||
5143 | /* Verify the contents of a GIMPLE_PHI. Returns true if there is a problem, | |||
5144 | and false otherwise. */ | |||
5145 | ||||
5146 | static bool | |||
5147 | verify_gimple_phi (gphi *phi) | |||
5148 | { | |||
5149 | bool err = false; | |||
5150 | unsigned i; | |||
5151 | tree phi_result = gimple_phi_result (phi); | |||
5152 | bool virtual_p; | |||
5153 | ||||
5154 | if (!phi_result) | |||
5155 | { | |||
5156 | error ("invalid %<PHI%> result"); | |||
5157 | return true; | |||
5158 | } | |||
5159 | ||||
5160 | virtual_p = virtual_operand_p (phi_result); | |||
5161 | if (TREE_CODE (phi_result)((enum tree_code) (phi_result)->base.code) != SSA_NAME | |||
5162 | || (virtual_p | |||
5163 | && SSA_NAME_VAR (phi_result)((tree_check ((phi_result), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5163, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((phi_result)->ssa_name.var) ->base.code) == IDENTIFIER_NODE ? (tree) nullptr : (phi_result )->ssa_name.var) != gimple_vop (cfun(cfun + 0)))) | |||
5164 | { | |||
5165 | error ("invalid %<PHI%> result"); | |||
5166 | err = true; | |||
5167 | } | |||
5168 | ||||
5169 | for (i = 0; i < gimple_phi_num_args (phi); i++) | |||
5170 | { | |||
5171 | tree t = gimple_phi_arg_def (phi, i); | |||
5172 | ||||
5173 | if (!t) | |||
5174 | { | |||
5175 | error ("missing %<PHI%> def"); | |||
5176 | err |= true; | |||
5177 | continue; | |||
5178 | } | |||
5179 | /* Addressable variables do have SSA_NAMEs but they | |||
5180 | are not considered gimple values. */ | |||
5181 | else if ((TREE_CODE (t)((enum tree_code) (t)->base.code) == SSA_NAME | |||
5182 | && virtual_p != virtual_operand_p (t)) | |||
5183 | || (virtual_p | |||
5184 | && (TREE_CODE (t)((enum tree_code) (t)->base.code) != SSA_NAME | |||
5185 | || SSA_NAME_VAR (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5185, __FUNCTION__, (SSA_NAME)))->ssa_name.var == (tree) nullptr || ((enum tree_code) ((t)->ssa_name.var)->base .code) == IDENTIFIER_NODE ? (tree) nullptr : (t)->ssa_name .var) != gimple_vop (cfun(cfun + 0)))) | |||
5186 | || (!virtual_p | |||
5187 | && !is_gimple_val (t))) | |||
5188 | { | |||
5189 | error ("invalid %<PHI%> argument"); | |||
5190 | debug_generic_expr (t); | |||
5191 | err |= true; | |||
5192 | } | |||
5193 | #ifdef ENABLE_TYPES_CHECKING1 | |||
5194 | if (!useless_type_conversion_p (TREE_TYPE (phi_result)((contains_struct_check ((phi_result), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5194, __FUNCTION__))->typed.type), TREE_TYPE (t)((contains_struct_check ((t), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5194, __FUNCTION__))->typed.type))) | |||
5195 | { | |||
5196 | error ("incompatible types in %<PHI%> argument %u", i); | |||
5197 | debug_generic_stmt (TREE_TYPE (phi_result)((contains_struct_check ((phi_result), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5197, __FUNCTION__))->typed.type)); | |||
5198 | debug_generic_stmt (TREE_TYPE (t)((contains_struct_check ((t), (TS_TYPED), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5198, __FUNCTION__))->typed.type)); | |||
5199 | err |= true; | |||
5200 | } | |||
5201 | #endif | |||
5202 | } | |||
5203 | ||||
5204 | return err; | |||
5205 | } | |||
5206 | ||||
5207 | /* Verify the GIMPLE statements inside the sequence STMTS. */ | |||
5208 | ||||
5209 | static bool | |||
5210 | verify_gimple_in_seq_2 (gimple_seq stmts) | |||
5211 | { | |||
5212 | gimple_stmt_iterator ittr; | |||
5213 | bool err = false; | |||
5214 | ||||
5215 | for (ittr = gsi_start (stmts); !gsi_end_p (ittr); gsi_next (&ittr)) | |||
5216 | { | |||
5217 | gimple *stmt = gsi_stmt (ittr); | |||
5218 | ||||
5219 | switch (gimple_code (stmt)) | |||
5220 | { | |||
5221 | case GIMPLE_BIND: | |||
5222 | err |= verify_gimple_in_seq_2 ( | |||
5223 | gimple_bind_body (as_a <gbind *> (stmt))); | |||
5224 | break; | |||
5225 | ||||
5226 | case GIMPLE_TRY: | |||
5227 | err |= verify_gimple_in_seq_2 (gimple_try_eval (stmt)); | |||
5228 | err |= verify_gimple_in_seq_2 (gimple_try_cleanup (stmt)); | |||
5229 | break; | |||
5230 | ||||
5231 | case GIMPLE_EH_FILTER: | |||
5232 | err |= verify_gimple_in_seq_2 (gimple_eh_filter_failure (stmt)); | |||
5233 | break; | |||
5234 | ||||
5235 | case GIMPLE_EH_ELSE: | |||
5236 | { | |||
5237 | geh_else *eh_else = as_a <geh_else *> (stmt); | |||
5238 | err |= verify_gimple_in_seq_2 (gimple_eh_else_n_body (eh_else)); | |||
5239 | err |= verify_gimple_in_seq_2 (gimple_eh_else_e_body (eh_else)); | |||
5240 | } | |||
5241 | break; | |||
5242 | ||||
5243 | case GIMPLE_CATCH: | |||
5244 | err |= verify_gimple_in_seq_2 (gimple_catch_handler ( | |||
5245 | as_a <gcatch *> (stmt))); | |||
5246 | break; | |||
5247 | ||||
5248 | case GIMPLE_ASSUME: | |||
5249 | err |= verify_gimple_in_seq_2 (gimple_assume_body (stmt)); | |||
5250 | break; | |||
5251 | ||||
5252 | case GIMPLE_TRANSACTION: | |||
5253 | err |= verify_gimple_transaction (as_a <gtransaction *> (stmt)); | |||
5254 | break; | |||
5255 | ||||
5256 | default: | |||
5257 | { | |||
5258 | bool err2 = verify_gimple_stmt (stmt); | |||
5259 | if (err2) | |||
5260 | debug_gimple_stmt (stmt); | |||
5261 | err |= err2; | |||
5262 | } | |||
5263 | } | |||
5264 | } | |||
5265 | ||||
5266 | return err; | |||
5267 | } | |||
5268 | ||||
5269 | /* Verify the contents of a GIMPLE_TRANSACTION. Returns true if there | |||
5270 | is a problem, otherwise false. */ | |||
5271 | ||||
5272 | static bool | |||
5273 | verify_gimple_transaction (gtransaction *stmt) | |||
5274 | { | |||
5275 | tree lab; | |||
5276 | ||||
5277 | lab = gimple_transaction_label_norm (stmt); | |||
5278 | if (lab != NULLnullptr && TREE_CODE (lab)((enum tree_code) (lab)->base.code) != LABEL_DECL) | |||
5279 | return true; | |||
5280 | lab = gimple_transaction_label_uninst (stmt); | |||
5281 | if (lab != NULLnullptr && TREE_CODE (lab)((enum tree_code) (lab)->base.code) != LABEL_DECL) | |||
5282 | return true; | |||
5283 | lab = gimple_transaction_label_over (stmt); | |||
5284 | if (lab != NULLnullptr && TREE_CODE (lab)((enum tree_code) (lab)->base.code) != LABEL_DECL) | |||
5285 | return true; | |||
5286 | ||||
5287 | return verify_gimple_in_seq_2 (gimple_transaction_body (stmt)); | |||
5288 | } | |||
5289 | ||||
5290 | ||||
5291 | /* Verify the GIMPLE statements inside the statement list STMTS. */ | |||
5292 | ||||
5293 | DEBUG_FUNCTION__attribute__ ((__used__)) bool | |||
5294 | verify_gimple_in_seq (gimple_seq stmts, bool ice) | |||
5295 | { | |||
5296 | timevar_push (TV_TREE_STMT_VERIFY); | |||
5297 | bool res = verify_gimple_in_seq_2 (stmts); | |||
5298 | if (res && ice) | |||
5299 | internal_error ("%<verify_gimple%> failed"); | |||
5300 | timevar_pop (TV_TREE_STMT_VERIFY); | |||
5301 | return res; | |||
5302 | } | |||
5303 | ||||
5304 | /* Return true when the T can be shared. */ | |||
5305 | ||||
5306 | static bool | |||
5307 | tree_node_can_be_shared (tree t) | |||
5308 | { | |||
5309 | if (IS_TYPE_OR_DECL_P (t)((tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) (t)->base.code))] == tcc_type) || (tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) (t)->base .code))] == tcc_declaration)) | |||
5310 | || TREE_CODE (t)((enum tree_code) (t)->base.code) == SSA_NAME | |||
5311 | || TREE_CODE (t)((enum tree_code) (t)->base.code) == IDENTIFIER_NODE | |||
5312 | || TREE_CODE (t)((enum tree_code) (t)->base.code) == CASE_LABEL_EXPR | |||
5313 | || is_gimple_min_invariant (t)) | |||
5314 | return true; | |||
5315 | ||||
5316 | if (t == error_mark_nodeglobal_trees[TI_ERROR_MARK]) | |||
5317 | return true; | |||
5318 | ||||
5319 | return false; | |||
5320 | } | |||
5321 | ||||
5322 | /* Called via walk_tree. Verify tree sharing. */ | |||
5323 | ||||
5324 | static tree | |||
5325 | verify_node_sharing_1 (tree *tp, int *walk_subtrees, void *data) | |||
5326 | { | |||
5327 | hash_set<void *> *visited = (hash_set<void *> *) data; | |||
5328 | ||||
5329 | if (tree_node_can_be_shared (*tp)) | |||
5330 | { | |||
5331 | *walk_subtrees = false; | |||
5332 | return NULLnullptr; | |||
5333 | } | |||
5334 | ||||
5335 | if (visited->add (*tp)) | |||
5336 | return *tp; | |||
5337 | ||||
5338 | return NULLnullptr; | |||
5339 | } | |||
5340 | ||||
5341 | /* Called via walk_gimple_stmt. Verify tree sharing. */ | |||
5342 | ||||
5343 | static tree | |||
5344 | verify_node_sharing (tree *tp, int *walk_subtrees, void *data) | |||
5345 | { | |||
5346 | struct walk_stmt_info *wi = (struct walk_stmt_info *) data; | |||
5347 | return verify_node_sharing_1 (tp, walk_subtrees, wi->info); | |||
5348 | } | |||
5349 | ||||
5350 | static bool eh_error_found; | |||
5351 | bool | |||
5352 | verify_eh_throw_stmt_node (gimple *const &stmt, const int &, | |||
5353 | hash_set<gimple *> *visited) | |||
5354 | { | |||
5355 | if (!visited->contains (stmt)) | |||
5356 | { | |||
5357 | error ("dead statement in EH table"); | |||
5358 | debug_gimple_stmt (stmt); | |||
5359 | eh_error_found = true; | |||
5360 | } | |||
5361 | return true; | |||
5362 | } | |||
5363 | ||||
5364 | /* Verify if the location LOCs block is in BLOCKS. */ | |||
5365 | ||||
5366 | static bool | |||
5367 | verify_location (hash_set<tree> *blocks, location_t loc) | |||
5368 | { | |||
5369 | tree block = LOCATION_BLOCK (loc)((tree) ((IS_ADHOC_LOC (loc)) ? get_data_from_adhoc_loc (line_table , (loc)) : nullptr)); | |||
5370 | if (block != NULL_TREE(tree) nullptr | |||
5371 | && !blocks->contains (block)) | |||
5372 | { | |||
5373 | error ("location references block not in block tree"); | |||
5374 | return true; | |||
5375 | } | |||
5376 | if (block != NULL_TREE(tree) nullptr) | |||
5377 | return verify_location (blocks, BLOCK_SOURCE_LOCATION (block)((tree_check ((block), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5377, __FUNCTION__, (BLOCK)))->block.locus)); | |||
5378 | return false; | |||
5379 | } | |||
5380 | ||||
5381 | /* Called via walk_tree. Verify that expressions have no blocks. */ | |||
5382 | ||||
5383 | static tree | |||
5384 | verify_expr_no_block (tree *tp, int *walk_subtrees, void *) | |||
5385 | { | |||
5386 | if (!EXPR_P (*tp)((tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) (*tp)->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) (*tp)->base.code))]) <= tcc_expression)) | |||
5387 | { | |||
5388 | *walk_subtrees = false; | |||
5389 | return NULLnullptr; | |||
5390 | } | |||
5391 | ||||
5392 | location_t loc = EXPR_LOCATION (*tp)((((*tp)) && ((tree_code_type_tmpl <0>::tree_code_type [(int) (((enum tree_code) ((*tp))->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type[(int ) (((enum tree_code) ((*tp))->base.code))]) <= tcc_expression )) ? (*tp)->exp.locus : ((location_t) 0)); | |||
5393 | if (LOCATION_BLOCK (loc)((tree) ((IS_ADHOC_LOC (loc)) ? get_data_from_adhoc_loc (line_table , (loc)) : nullptr)) != NULLnullptr) | |||
5394 | return *tp; | |||
5395 | ||||
5396 | return NULLnullptr; | |||
5397 | } | |||
5398 | ||||
5399 | /* Called via walk_tree. Verify locations of expressions. */ | |||
5400 | ||||
5401 | static tree | |||
5402 | verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data) | |||
5403 | { | |||
5404 | hash_set<tree> *blocks = (hash_set<tree> *) data; | |||
5405 | tree t = *tp; | |||
5406 | ||||
5407 | /* ??? This doesn't really belong here but there's no good place to | |||
5408 | stick this remainder of old verify_expr. */ | |||
5409 | /* ??? This barfs on debug stmts which contain binds to vars with | |||
5410 | different function context. */ | |||
5411 | #if 0 | |||
5412 | if (VAR_P (t)(((enum tree_code) (t)->base.code) == VAR_DECL) | |||
5413 | || TREE_CODE (t)((enum tree_code) (t)->base.code) == PARM_DECL | |||
5414 | || TREE_CODE (t)((enum tree_code) (t)->base.code) == RESULT_DECL) | |||
5415 | { | |||
5416 | tree context = decl_function_context (t); | |||
5417 | if (context != cfun(cfun + 0)->decl | |||
5418 | && !SCOPE_FILE_SCOPE_P (context)(! (context) || ((enum tree_code) (context)->base.code) == TRANSLATION_UNIT_DECL) | |||
5419 | && !TREE_STATIC (t)((t)->base.static_flag) | |||
5420 | && !DECL_EXTERNAL (t)((contains_struct_check ((t), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5420, __FUNCTION__))->decl_common.decl_flag_1)) | |||
5421 | { | |||
5422 | error ("local declaration from a different function"); | |||
5423 | return t; | |||
5424 | } | |||
5425 | } | |||
5426 | #endif | |||
5427 | ||||
5428 | if (VAR_P (t)(((enum tree_code) (t)->base.code) == VAR_DECL) && DECL_HAS_DEBUG_EXPR_P (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5428, __FUNCTION__, (VAR_DECL)))->decl_common.debug_expr_is_from )) | |||
5429 | { | |||
5430 | tree x = DECL_DEBUG_EXPR (t)(decl_debug_expr_lookup ((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5430, __FUNCTION__, (VAR_DECL))))); | |||
5431 | tree addr = walk_tree (&x, verify_expr_no_block, NULL, NULL)walk_tree_1 (&x, verify_expr_no_block, nullptr, nullptr, nullptr ); | |||
5432 | if (addr) | |||
5433 | return addr; | |||
5434 | } | |||
5435 | if ((VAR_P (t)(((enum tree_code) (t)->base.code) == VAR_DECL) | |||
5436 | || TREE_CODE (t)((enum tree_code) (t)->base.code) == PARM_DECL | |||
5437 | || TREE_CODE (t)((enum tree_code) (t)->base.code) == RESULT_DECL) | |||
5438 | && DECL_HAS_VALUE_EXPR_P (t)((tree_check3 ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5438, __FUNCTION__, (VAR_DECL), (PARM_DECL), (RESULT_DECL)) ) ->decl_common.decl_flag_2)) | |||
5439 | { | |||
5440 | tree x = DECL_VALUE_EXPR (t)(decl_value_expr_lookup ((contains_struct_check ((t), (TS_DECL_WRTL ), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5440, __FUNCTION__)))); | |||
5441 | tree addr = walk_tree (&x, verify_expr_no_block, NULL, NULL)walk_tree_1 (&x, verify_expr_no_block, nullptr, nullptr, nullptr ); | |||
5442 | if (addr) | |||
5443 | return addr; | |||
5444 | } | |||
5445 | ||||
5446 | if (!EXPR_P (t)((tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) (t)->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type[(int) (((enum tree_code) (t)->base.code))]) <= tcc_expression)) | |||
5447 | { | |||
5448 | *walk_subtrees = false; | |||
5449 | return NULLnullptr; | |||
5450 | } | |||
5451 | ||||
5452 | location_t loc = EXPR_LOCATION (t)((((t)) && ((tree_code_type_tmpl <0>::tree_code_type [(int) (((enum tree_code) ((t))->base.code))]) >= tcc_reference && (tree_code_type_tmpl <0>::tree_code_type[(int ) (((enum tree_code) ((t))->base.code))]) <= tcc_expression )) ? (t)->exp.locus : ((location_t) 0)); | |||
5453 | if (verify_location (blocks, loc)) | |||
5454 | return t; | |||
5455 | ||||
5456 | return NULLnullptr; | |||
5457 | } | |||
5458 | ||||
5459 | /* Called via walk_gimple_op. Verify locations of expressions. */ | |||
5460 | ||||
5461 | static tree | |||
5462 | verify_expr_location (tree *tp, int *walk_subtrees, void *data) | |||
5463 | { | |||
5464 | struct walk_stmt_info *wi = (struct walk_stmt_info *) data; | |||
5465 | return verify_expr_location_1 (tp, walk_subtrees, wi->info); | |||
5466 | } | |||
5467 | ||||
5468 | /* Insert all subblocks of BLOCK into BLOCKS and recurse. */ | |||
5469 | ||||
5470 | static void | |||
5471 | collect_subblocks (hash_set<tree> *blocks, tree block) | |||
5472 | { | |||
5473 | tree t; | |||
5474 | for (t = BLOCK_SUBBLOCKS (block)((tree_check ((block), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5474, __FUNCTION__, (BLOCK)))->block.subblocks); t; t = BLOCK_CHAIN (t)((tree_check ((t), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5474, __FUNCTION__, (BLOCK)))->block.chain)) | |||
5475 | { | |||
5476 | blocks->add (t); | |||
5477 | collect_subblocks (blocks, t); | |||
5478 | } | |||
5479 | } | |||
5480 | ||||
5481 | /* Disable warnings about missing quoting in GCC diagnostics for | |||
5482 | the verification errors. Their format strings don't follow | |||
5483 | GCC diagnostic conventions and trigger an ICE in the end. */ | |||
5484 | #if __GNUC__4 >= 10 | |||
5485 | # pragma GCC diagnostic push | |||
5486 | # pragma GCC diagnostic ignored "-Wformat-diag" | |||
5487 | #endif | |||
5488 | ||||
5489 | /* Verify the GIMPLE statements in the CFG of FN. */ | |||
5490 | ||||
5491 | DEBUG_FUNCTION__attribute__ ((__used__)) bool | |||
5492 | verify_gimple_in_cfg (struct function *fn, bool verify_nothrow, bool ice) | |||
5493 | { | |||
5494 | basic_block bb; | |||
5495 | bool err = false; | |||
5496 | ||||
5497 | timevar_push (TV_TREE_STMT_VERIFY); | |||
5498 | hash_set<void *> visited; | |||
5499 | hash_set<gimple *> visited_throwing_stmts; | |||
5500 | ||||
5501 | /* Collect all BLOCKs referenced by the BLOCK tree of FN. */ | |||
5502 | hash_set<tree> blocks; | |||
5503 | if (DECL_INITIAL (fn->decl)((contains_struct_check ((fn->decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5503, __FUNCTION__))->decl_common.initial)) | |||
5504 | { | |||
5505 | blocks.add (DECL_INITIAL (fn->decl)((contains_struct_check ((fn->decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5505, __FUNCTION__))->decl_common.initial)); | |||
5506 | collect_subblocks (&blocks, DECL_INITIAL (fn->decl)((contains_struct_check ((fn->decl), (TS_DECL_COMMON), "/buildworker/marxinbox-gcc-clang-static-analyzer/build/gcc/tree-cfg.cc" , 5506, __FUNCTION__))->decl_common.initial)); | |||
5507 | } | |||
5508 | ||||
5509 | FOR_EACH_BB_FN (bb, fn)for (bb = (fn)->cfg->x_entry_block_ptr->next_bb; bb != (fn)->cfg->x_exit_block_ptr; bb = bb->next_bb) | |||
5510 | { | |||
5511 | gimple_stmt_iterator gsi; | |||
5512 | edge_iterator ei; | |||
5513 | edge e; | |||
5514 | ||||
5515 | for (gphi_iterator gpi = gsi_start_phis (bb); | |||
5516 | !gsi_end_p (gpi); | |||
5517 | gsi_next (&gpi)) | |||
5518 | { | |||
5519 | gphi *phi = gpi.phi (); | |||
5520 | bool err2 = false; | |||
5521 | unsigned i; | |||
5522 | ||||
5523 | if (gimple_bb (phi) != bb) | |||
5524 | { | |||
5525 | error ("gimple_bb (phi) is set to a wrong basic block"); | |||
5526 | err2 = true; | |||
5527 | } | |||
5528 | ||||
5529 | err2 |= verify_gimple_phi (phi); | |||
5530 | ||||
5531 | /* Only PHI arguments have locations. */ | |||
5532 | if (gimple_location (phi) != UNKNOWN_LOCATION((location_t) 0)) | |||
5533 | { | |||
5534 | error ("PHI node with location"); | |||
5535 | err2 = true; | |||
5536 | } | |||
5537 | ||||
5538 | for (i = 0; i < gimple_phi_num_args (phi); i++) | |||
5539 | { | |||
5540 | tree arg = gimple_phi_arg_def (phi, i); | |||
5541 | tree addr = walk_tree (&arg, verify_node_sharing_1,walk_tree_1 (&arg, verify_node_sharing_1, &visited, nullptr , nullptr) | |||
5542 | &visited, NULL)walk_tree_1 (&arg, verify_node_sharing_1, &visited, nullptr , nullptr); | |||
5543 | if (addr) | |||
5544 | { | |||
5545 | error ("incorrect sharing of tree nodes"); | |||
5546 | debug_generic_expr (addr); | |||
5547 | err2 |= true; | |||
5548 | } | |||
5549 | location_t loc = gimple_phi_arg_location (phi, i); | |||
5550 | if (virtual_operand_p (gimple_phi_result (phi)) | |||
5551 | && loc != UNKNOWN_LOCATION((location_t) 0)) | |||
5552 | { | |||
5553 | error ("virtual PHI with argument locations"); | |||
5554 | err2 = true; | |||
5555 | } | |||
5556 | addr = walk_tree (&arg, verify_expr_location_1, &blocks, NULL)walk_tree_1 (&arg, verify_expr_location_1, &blocks, nullptr , nullptr); | |||
5557 | if (addr) | |||
5558 | { | |||
5559 | debug_generic_expr (addr); | |||
5560 | err2 = true; | |||
5561 | } | |||
5562 | err2 |= verify_location (&blocks, loc); | |||
5563 | } | |||
5564 | ||||
5565 | if (err2) | |||
5566 | debug_gimple_stmt (phi); | |||
5567 | err |= err2; | |||
5568 | } | |||
5569 | ||||
5570 | for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) | |||
5571 | { | |||
5572 | gimple *stmt = gsi_stmt (gsi); | |||
5573 | bool err2 = false; | |||
5574 | struct walk_stmt_info wi; | |||
5575 | tree addr; | |||
557 |