File: | build/gcc/tree-cfg.cc |
Warning: | line 3537, column 2 Value stored to 'lhs' is never read |
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); |
Value stored to 'lhs' is never read | |
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; |
5576 | int lp_nr; |
5577 | |
5578 | if (gimple_bb (stmt) != bb) |
5579 | { |
5580 | error ("gimple_bb (stmt) is set to a wrong basic block"); |
5581 | err2 = true; |
5582 | } |
5583 | |
5584 | err2 |= verify_gimple_stmt (stmt); |
5585 | err2 |= verify_location (&blocks, gimple_location (stmt)); |
5586 | |
5587 | memset (&wi, 0, sizeof (wi)); |
5588 | wi.info = (void *) &visited; |
5589 | addr = walk_gimple_op (stmt, verify_node_sharing, &wi); |
5590 | if (addr) |
5591 | { |
5592 | error ("incorrect sharing of tree nodes"); |
5593 | debug_generic_expr (addr); |
5594 | err2 |= true; |
5595 | } |
5596 | |
5597 | memset (&wi, 0, sizeof (wi)); |
5598 | wi.info = (void *) &blocks; |
5599 | addr = walk_gimple_op (stmt, verify_expr_location, &wi); |
5600 | if (addr) |
5601 | { |
5602 | debug_generic_expr (addr); |
5603 | err2 |= true; |
5604 | } |
5605 | |
5606 | /* If the statement is marked as part of an EH region, then it is |
5607 | expected that the statement could throw. Verify that when we |
5608 | have optimizations that simplify statements such that we prove |
5609 | that they cannot throw, that we update other data structures |
5610 | to match. */ |
5611 | lp_nr = lookup_stmt_eh_lp (stmt); |
5612 | if (lp_nr != 0) |
5613 | visited_throwing_stmts.add (stmt); |
5614 | if (lp_nr > 0) |
5615 | { |
5616 | if (!stmt_could_throw_p (cfun(cfun + 0), stmt)) |
5617 | { |
5618 | if (verify_nothrow) |
5619 | { |
5620 | error ("statement marked for throw, but doesn%'t"); |
5621 | err2 |= true; |
5622 | } |
5623 | } |
5624 | else if (!gsi_one_before_end_p (gsi)) |
5625 | { |
5626 | error ("statement marked for throw in middle of block"); |
5627 | err2 |= true; |
5628 | } |
5629 | } |
5630 | |
5631 | if (err2) |
5632 | debug_gimple_stmt (stmt); |
5633 | err |= err2; |
5634 | } |
5635 | |
5636 | FOR_EACH_EDGE (e, ei, bb->succs)for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei) , &(e)); ei_next (&(ei))) |
5637 | if (e->goto_locus != UNKNOWN_LOCATION((location_t) 0)) |
5638 | err |= verify_location (&blocks, e->goto_locus); |
5639 | } |
5640 | |
5641 | hash_map<gimple *, int> *eh_table = get_eh_throw_stmt_table (cfun(cfun + 0)); |
5642 | eh_error_found = false; |
5643 | if (eh_table) |
5644 | eh_table->traverse<hash_set<gimple *> *, verify_eh_throw_stmt_node> |
5645 | (&visited_throwing_stmts); |
5646 | |
5647 | if (ice && (err || eh_error_found)) |
5648 | internal_error ("verify_gimple failed"); |
5649 | |
5650 | verify_histograms (); |
5651 | timevar_pop (TV_TREE_STMT_VERIFY); |