Mercurial > hg > CbC > CbC_gcc
comparison gcc/cp/cp-gimplify.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* C++-specific tree lowering bits; see also c-gimplify.c and tree-gimple.c. | |
2 | |
3 Copyright (C) 2002-2017 Free Software Foundation, Inc. | |
4 Contributed by Jason Merrill <jason@redhat.com> | |
5 | |
6 This file is part of GCC. | |
7 | |
8 GCC is free software; you can redistribute it and/or modify it under | |
9 the terms of the GNU General Public License as published by the Free | |
10 Software Foundation; either version 3, or (at your option) any later | |
11 version. | |
12 | |
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
16 for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with GCC; see the file COPYING3. If not see | |
20 <http://www.gnu.org/licenses/>. */ | |
21 | |
22 #include "config.h" | |
23 #include "system.h" | |
24 #include "coretypes.h" | |
25 #include "target.h" | |
26 #include "basic-block.h" | |
27 #include "cp-tree.h" | |
28 #include "gimple.h" | |
29 #include "predict.h" | |
30 #include "stor-layout.h" | |
31 #include "tree-iterator.h" | |
32 #include "gimplify.h" | |
33 #include "c-family/c-ubsan.h" | |
34 #include "cilk.h" | |
35 #include "cp-cilkplus.h" | |
36 #include "stringpool.h" | |
37 #include "attribs.h" | |
38 #include "asan.h" | |
39 | |
40 /* Forward declarations. */ | |
41 | |
42 static tree cp_genericize_r (tree *, int *, void *); | |
43 static tree cp_fold_r (tree *, int *, void *); | |
44 static void cp_genericize_tree (tree*, bool); | |
45 static tree cp_fold (tree); | |
46 | |
47 /* Local declarations. */ | |
48 | |
49 enum bc_t { bc_break = 0, bc_continue = 1 }; | |
50 | |
51 /* Stack of labels which are targets for "break" or "continue", | |
52 linked through TREE_CHAIN. */ | |
53 static tree bc_label[2]; | |
54 | |
55 /* Begin a scope which can be exited by a break or continue statement. BC | |
56 indicates which. | |
57 | |
58 Just creates a label with location LOCATION and pushes it into the current | |
59 context. */ | |
60 | |
61 static tree | |
62 begin_bc_block (enum bc_t bc, location_t location) | |
63 { | |
64 tree label = create_artificial_label (location); | |
65 DECL_CHAIN (label) = bc_label[bc]; | |
66 bc_label[bc] = label; | |
67 if (bc == bc_break) | |
68 LABEL_DECL_BREAK (label) = true; | |
69 else | |
70 LABEL_DECL_CONTINUE (label) = true; | |
71 return label; | |
72 } | |
73 | |
74 /* Finish a scope which can be exited by a break or continue statement. | |
75 LABEL was returned from the most recent call to begin_bc_block. BLOCK is | |
76 an expression for the contents of the scope. | |
77 | |
78 If we saw a break (or continue) in the scope, append a LABEL_EXPR to | |
79 BLOCK. Otherwise, just forget the label. */ | |
80 | |
81 static void | |
82 finish_bc_block (tree *block, enum bc_t bc, tree label) | |
83 { | |
84 gcc_assert (label == bc_label[bc]); | |
85 | |
86 if (TREE_USED (label)) | |
87 append_to_statement_list (build1 (LABEL_EXPR, void_type_node, label), | |
88 block); | |
89 | |
90 bc_label[bc] = DECL_CHAIN (label); | |
91 DECL_CHAIN (label) = NULL_TREE; | |
92 } | |
93 | |
94 /* Get the LABEL_EXPR to represent a break or continue statement | |
95 in the current block scope. BC indicates which. */ | |
96 | |
97 static tree | |
98 get_bc_label (enum bc_t bc) | |
99 { | |
100 tree label = bc_label[bc]; | |
101 | |
102 /* Mark the label used for finish_bc_block. */ | |
103 TREE_USED (label) = 1; | |
104 return label; | |
105 } | |
106 | |
107 /* Genericize a TRY_BLOCK. */ | |
108 | |
109 static void | |
110 genericize_try_block (tree *stmt_p) | |
111 { | |
112 tree body = TRY_STMTS (*stmt_p); | |
113 tree cleanup = TRY_HANDLERS (*stmt_p); | |
114 | |
115 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup); | |
116 } | |
117 | |
118 /* Genericize a HANDLER by converting to a CATCH_EXPR. */ | |
119 | |
120 static void | |
121 genericize_catch_block (tree *stmt_p) | |
122 { | |
123 tree type = HANDLER_TYPE (*stmt_p); | |
124 tree body = HANDLER_BODY (*stmt_p); | |
125 | |
126 /* FIXME should the caught type go in TREE_TYPE? */ | |
127 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body); | |
128 } | |
129 | |
130 /* A terser interface for building a representation of an exception | |
131 specification. */ | |
132 | |
133 static tree | |
134 build_gimple_eh_filter_tree (tree body, tree allowed, tree failure) | |
135 { | |
136 tree t; | |
137 | |
138 /* FIXME should the allowed types go in TREE_TYPE? */ | |
139 t = build2 (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE); | |
140 append_to_statement_list (failure, &EH_FILTER_FAILURE (t)); | |
141 | |
142 t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t); | |
143 append_to_statement_list (body, &TREE_OPERAND (t, 0)); | |
144 | |
145 return t; | |
146 } | |
147 | |
148 /* Genericize an EH_SPEC_BLOCK by converting it to a | |
149 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */ | |
150 | |
151 static void | |
152 genericize_eh_spec_block (tree *stmt_p) | |
153 { | |
154 tree body = EH_SPEC_STMTS (*stmt_p); | |
155 tree allowed = EH_SPEC_RAISES (*stmt_p); | |
156 tree failure = build_call_n (call_unexpected_fn, 1, build_exc_ptr ()); | |
157 | |
158 *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure); | |
159 TREE_NO_WARNING (*stmt_p) = true; | |
160 TREE_NO_WARNING (TREE_OPERAND (*stmt_p, 1)) = true; | |
161 } | |
162 | |
163 /* Genericize an IF_STMT by turning it into a COND_EXPR. */ | |
164 | |
165 static void | |
166 genericize_if_stmt (tree *stmt_p) | |
167 { | |
168 tree stmt, cond, then_, else_; | |
169 location_t locus = EXPR_LOCATION (*stmt_p); | |
170 | |
171 stmt = *stmt_p; | |
172 cond = IF_COND (stmt); | |
173 then_ = THEN_CLAUSE (stmt); | |
174 else_ = ELSE_CLAUSE (stmt); | |
175 | |
176 if (!then_) | |
177 then_ = build_empty_stmt (locus); | |
178 if (!else_) | |
179 else_ = build_empty_stmt (locus); | |
180 | |
181 if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_)) | |
182 stmt = then_; | |
183 else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_)) | |
184 stmt = else_; | |
185 else | |
186 stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_); | |
187 if (!EXPR_HAS_LOCATION (stmt)) | |
188 protected_set_expr_location (stmt, locus); | |
189 *stmt_p = stmt; | |
190 } | |
191 | |
192 /* Build a generic representation of one of the C loop forms. COND is the | |
193 loop condition or NULL_TREE. BODY is the (possibly compound) statement | |
194 controlled by the loop. INCR is the increment expression of a for-loop, | |
195 or NULL_TREE. COND_IS_FIRST indicates whether the condition is | |
196 evaluated before the loop body as in while and for loops, or after the | |
197 loop body as in do-while loops. */ | |
198 | |
199 static void | |
200 genericize_cp_loop (tree *stmt_p, location_t start_locus, tree cond, tree body, | |
201 tree incr, bool cond_is_first, int *walk_subtrees, | |
202 void *data) | |
203 { | |
204 tree blab, clab; | |
205 tree exit = NULL; | |
206 tree stmt_list = NULL; | |
207 | |
208 blab = begin_bc_block (bc_break, start_locus); | |
209 clab = begin_bc_block (bc_continue, start_locus); | |
210 | |
211 protected_set_expr_location (incr, start_locus); | |
212 | |
213 cp_walk_tree (&cond, cp_genericize_r, data, NULL); | |
214 cp_walk_tree (&body, cp_genericize_r, data, NULL); | |
215 cp_walk_tree (&incr, cp_genericize_r, data, NULL); | |
216 *walk_subtrees = 0; | |
217 | |
218 if (cond && TREE_CODE (cond) != INTEGER_CST) | |
219 { | |
220 /* If COND is constant, don't bother building an exit. If it's false, | |
221 we won't build a loop. If it's true, any exits are in the body. */ | |
222 location_t cloc = EXPR_LOC_OR_LOC (cond, start_locus); | |
223 exit = build1_loc (cloc, GOTO_EXPR, void_type_node, | |
224 get_bc_label (bc_break)); | |
225 exit = fold_build3_loc (cloc, COND_EXPR, void_type_node, cond, | |
226 build_empty_stmt (cloc), exit); | |
227 } | |
228 | |
229 if (exit && cond_is_first) | |
230 append_to_statement_list (exit, &stmt_list); | |
231 append_to_statement_list (body, &stmt_list); | |
232 finish_bc_block (&stmt_list, bc_continue, clab); | |
233 append_to_statement_list (incr, &stmt_list); | |
234 if (exit && !cond_is_first) | |
235 append_to_statement_list (exit, &stmt_list); | |
236 | |
237 if (!stmt_list) | |
238 stmt_list = build_empty_stmt (start_locus); | |
239 | |
240 tree loop; | |
241 if (cond && integer_zerop (cond)) | |
242 { | |
243 if (cond_is_first) | |
244 loop = fold_build3_loc (start_locus, COND_EXPR, | |
245 void_type_node, cond, stmt_list, | |
246 build_empty_stmt (start_locus)); | |
247 else | |
248 loop = stmt_list; | |
249 } | |
250 else | |
251 { | |
252 location_t loc = start_locus; | |
253 if (!cond || integer_nonzerop (cond)) | |
254 loc = EXPR_LOCATION (expr_first (body)); | |
255 if (loc == UNKNOWN_LOCATION) | |
256 loc = start_locus; | |
257 loop = build1_loc (loc, LOOP_EXPR, void_type_node, stmt_list); | |
258 } | |
259 | |
260 stmt_list = NULL; | |
261 append_to_statement_list (loop, &stmt_list); | |
262 finish_bc_block (&stmt_list, bc_break, blab); | |
263 if (!stmt_list) | |
264 stmt_list = build_empty_stmt (start_locus); | |
265 | |
266 *stmt_p = stmt_list; | |
267 } | |
268 | |
269 /* Genericize a FOR_STMT node *STMT_P. */ | |
270 | |
271 static void | |
272 genericize_for_stmt (tree *stmt_p, int *walk_subtrees, void *data) | |
273 { | |
274 tree stmt = *stmt_p; | |
275 tree expr = NULL; | |
276 tree loop; | |
277 tree init = FOR_INIT_STMT (stmt); | |
278 | |
279 if (init) | |
280 { | |
281 cp_walk_tree (&init, cp_genericize_r, data, NULL); | |
282 append_to_statement_list (init, &expr); | |
283 } | |
284 | |
285 genericize_cp_loop (&loop, EXPR_LOCATION (stmt), FOR_COND (stmt), | |
286 FOR_BODY (stmt), FOR_EXPR (stmt), 1, walk_subtrees, data); | |
287 append_to_statement_list (loop, &expr); | |
288 if (expr == NULL_TREE) | |
289 expr = loop; | |
290 *stmt_p = expr; | |
291 } | |
292 | |
293 /* Genericize a WHILE_STMT node *STMT_P. */ | |
294 | |
295 static void | |
296 genericize_while_stmt (tree *stmt_p, int *walk_subtrees, void *data) | |
297 { | |
298 tree stmt = *stmt_p; | |
299 genericize_cp_loop (stmt_p, EXPR_LOCATION (stmt), WHILE_COND (stmt), | |
300 WHILE_BODY (stmt), NULL_TREE, 1, walk_subtrees, data); | |
301 } | |
302 | |
303 /* Genericize a DO_STMT node *STMT_P. */ | |
304 | |
305 static void | |
306 genericize_do_stmt (tree *stmt_p, int *walk_subtrees, void *data) | |
307 { | |
308 tree stmt = *stmt_p; | |
309 genericize_cp_loop (stmt_p, EXPR_LOCATION (stmt), DO_COND (stmt), | |
310 DO_BODY (stmt), NULL_TREE, 0, walk_subtrees, data); | |
311 } | |
312 | |
313 /* Genericize a SWITCH_STMT node *STMT_P by turning it into a SWITCH_EXPR. */ | |
314 | |
315 static void | |
316 genericize_switch_stmt (tree *stmt_p, int *walk_subtrees, void *data) | |
317 { | |
318 tree stmt = *stmt_p; | |
319 tree break_block, body, cond, type; | |
320 location_t stmt_locus = EXPR_LOCATION (stmt); | |
321 | |
322 break_block = begin_bc_block (bc_break, stmt_locus); | |
323 | |
324 body = SWITCH_STMT_BODY (stmt); | |
325 if (!body) | |
326 body = build_empty_stmt (stmt_locus); | |
327 cond = SWITCH_STMT_COND (stmt); | |
328 type = SWITCH_STMT_TYPE (stmt); | |
329 | |
330 cp_walk_tree (&body, cp_genericize_r, data, NULL); | |
331 cp_walk_tree (&cond, cp_genericize_r, data, NULL); | |
332 cp_walk_tree (&type, cp_genericize_r, data, NULL); | |
333 *walk_subtrees = 0; | |
334 | |
335 *stmt_p = build3_loc (stmt_locus, SWITCH_EXPR, type, cond, body, NULL_TREE); | |
336 finish_bc_block (stmt_p, bc_break, break_block); | |
337 } | |
338 | |
339 /* Genericize a CONTINUE_STMT node *STMT_P. */ | |
340 | |
341 static void | |
342 genericize_continue_stmt (tree *stmt_p) | |
343 { | |
344 tree stmt_list = NULL; | |
345 tree pred = build_predict_expr (PRED_CONTINUE, NOT_TAKEN); | |
346 tree label = get_bc_label (bc_continue); | |
347 location_t location = EXPR_LOCATION (*stmt_p); | |
348 tree jump = build1_loc (location, GOTO_EXPR, void_type_node, label); | |
349 append_to_statement_list_force (pred, &stmt_list); | |
350 append_to_statement_list (jump, &stmt_list); | |
351 *stmt_p = stmt_list; | |
352 } | |
353 | |
354 /* Genericize a BREAK_STMT node *STMT_P. */ | |
355 | |
356 static void | |
357 genericize_break_stmt (tree *stmt_p) | |
358 { | |
359 tree label = get_bc_label (bc_break); | |
360 location_t location = EXPR_LOCATION (*stmt_p); | |
361 *stmt_p = build1_loc (location, GOTO_EXPR, void_type_node, label); | |
362 } | |
363 | |
364 /* Genericize a OMP_FOR node *STMT_P. */ | |
365 | |
366 static void | |
367 genericize_omp_for_stmt (tree *stmt_p, int *walk_subtrees, void *data) | |
368 { | |
369 tree stmt = *stmt_p; | |
370 location_t locus = EXPR_LOCATION (stmt); | |
371 tree clab = begin_bc_block (bc_continue, locus); | |
372 | |
373 cp_walk_tree (&OMP_FOR_BODY (stmt), cp_genericize_r, data, NULL); | |
374 if (TREE_CODE (stmt) != OMP_TASKLOOP) | |
375 cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_genericize_r, data, NULL); | |
376 cp_walk_tree (&OMP_FOR_INIT (stmt), cp_genericize_r, data, NULL); | |
377 cp_walk_tree (&OMP_FOR_COND (stmt), cp_genericize_r, data, NULL); | |
378 cp_walk_tree (&OMP_FOR_INCR (stmt), cp_genericize_r, data, NULL); | |
379 cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_genericize_r, data, NULL); | |
380 *walk_subtrees = 0; | |
381 | |
382 finish_bc_block (&OMP_FOR_BODY (stmt), bc_continue, clab); | |
383 } | |
384 | |
385 /* Hook into the middle of gimplifying an OMP_FOR node. */ | |
386 | |
387 static enum gimplify_status | |
388 cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p) | |
389 { | |
390 tree for_stmt = *expr_p; | |
391 gimple_seq seq = NULL; | |
392 | |
393 /* Protect ourselves from recursion. */ | |
394 if (OMP_FOR_GIMPLIFYING_P (for_stmt)) | |
395 return GS_UNHANDLED; | |
396 OMP_FOR_GIMPLIFYING_P (for_stmt) = 1; | |
397 | |
398 gimplify_and_add (for_stmt, &seq); | |
399 gimple_seq_add_seq (pre_p, seq); | |
400 | |
401 OMP_FOR_GIMPLIFYING_P (for_stmt) = 0; | |
402 | |
403 return GS_ALL_DONE; | |
404 } | |
405 | |
406 /* Gimplify an EXPR_STMT node. */ | |
407 | |
408 static void | |
409 gimplify_expr_stmt (tree *stmt_p) | |
410 { | |
411 tree stmt = EXPR_STMT_EXPR (*stmt_p); | |
412 | |
413 if (stmt == error_mark_node) | |
414 stmt = NULL; | |
415 | |
416 /* Gimplification of a statement expression will nullify the | |
417 statement if all its side effects are moved to *PRE_P and *POST_P. | |
418 | |
419 In this case we will not want to emit the gimplified statement. | |
420 However, we may still want to emit a warning, so we do that before | |
421 gimplification. */ | |
422 if (stmt && warn_unused_value) | |
423 { | |
424 if (!TREE_SIDE_EFFECTS (stmt)) | |
425 { | |
426 if (!IS_EMPTY_STMT (stmt) | |
427 && !VOID_TYPE_P (TREE_TYPE (stmt)) | |
428 && !TREE_NO_WARNING (stmt)) | |
429 warning (OPT_Wunused_value, "statement with no effect"); | |
430 } | |
431 else | |
432 warn_if_unused_value (stmt, input_location); | |
433 } | |
434 | |
435 if (stmt == NULL_TREE) | |
436 stmt = alloc_stmt_list (); | |
437 | |
438 *stmt_p = stmt; | |
439 } | |
440 | |
441 /* Gimplify initialization from an AGGR_INIT_EXPR. */ | |
442 | |
443 static void | |
444 cp_gimplify_init_expr (tree *expr_p) | |
445 { | |
446 tree from = TREE_OPERAND (*expr_p, 1); | |
447 tree to = TREE_OPERAND (*expr_p, 0); | |
448 tree t; | |
449 | |
450 /* What about code that pulls out the temp and uses it elsewhere? I | |
451 think that such code never uses the TARGET_EXPR as an initializer. If | |
452 I'm wrong, we'll abort because the temp won't have any RTL. In that | |
453 case, I guess we'll need to replace references somehow. */ | |
454 if (TREE_CODE (from) == TARGET_EXPR) | |
455 from = TARGET_EXPR_INITIAL (from); | |
456 | |
457 /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them | |
458 inside the TARGET_EXPR. */ | |
459 for (t = from; t; ) | |
460 { | |
461 tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t; | |
462 | |
463 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and | |
464 replace the slot operand with our target. | |
465 | |
466 Should we add a target parm to gimplify_expr instead? No, as in this | |
467 case we want to replace the INIT_EXPR. */ | |
468 if (TREE_CODE (sub) == AGGR_INIT_EXPR | |
469 || TREE_CODE (sub) == VEC_INIT_EXPR) | |
470 { | |
471 if (TREE_CODE (sub) == AGGR_INIT_EXPR) | |
472 AGGR_INIT_EXPR_SLOT (sub) = to; | |
473 else | |
474 VEC_INIT_EXPR_SLOT (sub) = to; | |
475 *expr_p = from; | |
476 | |
477 /* The initialization is now a side-effect, so the container can | |
478 become void. */ | |
479 if (from != sub) | |
480 TREE_TYPE (from) = void_type_node; | |
481 } | |
482 | |
483 /* Handle aggregate NSDMI. */ | |
484 replace_placeholders (sub, to); | |
485 | |
486 if (t == sub) | |
487 break; | |
488 else | |
489 t = TREE_OPERAND (t, 1); | |
490 } | |
491 | |
492 } | |
493 | |
494 /* Gimplify a MUST_NOT_THROW_EXPR. */ | |
495 | |
496 static enum gimplify_status | |
497 gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p) | |
498 { | |
499 tree stmt = *expr_p; | |
500 tree temp = voidify_wrapper_expr (stmt, NULL); | |
501 tree body = TREE_OPERAND (stmt, 0); | |
502 gimple_seq try_ = NULL; | |
503 gimple_seq catch_ = NULL; | |
504 gimple *mnt; | |
505 | |
506 gimplify_and_add (body, &try_); | |
507 mnt = gimple_build_eh_must_not_throw (terminate_fn); | |
508 gimple_seq_add_stmt_without_update (&catch_, mnt); | |
509 mnt = gimple_build_try (try_, catch_, GIMPLE_TRY_CATCH); | |
510 | |
511 gimple_seq_add_stmt_without_update (pre_p, mnt); | |
512 if (temp) | |
513 { | |
514 *expr_p = temp; | |
515 return GS_OK; | |
516 } | |
517 | |
518 *expr_p = NULL; | |
519 return GS_ALL_DONE; | |
520 } | |
521 | |
522 /* Return TRUE if an operand (OP) of a given TYPE being copied is | |
523 really just an empty class copy. | |
524 | |
525 Check that the operand has a simple form so that TARGET_EXPRs and | |
526 non-empty CONSTRUCTORs get reduced properly, and we leave the | |
527 return slot optimization alone because it isn't a copy. */ | |
528 | |
529 static bool | |
530 simple_empty_class_p (tree type, tree op) | |
531 { | |
532 return | |
533 ((TREE_CODE (op) == COMPOUND_EXPR | |
534 && simple_empty_class_p (type, TREE_OPERAND (op, 1))) | |
535 || TREE_CODE (op) == EMPTY_CLASS_EXPR | |
536 || is_gimple_lvalue (op) | |
537 || INDIRECT_REF_P (op) | |
538 || (TREE_CODE (op) == CONSTRUCTOR | |
539 && CONSTRUCTOR_NELTS (op) == 0 | |
540 && !TREE_CLOBBER_P (op)) | |
541 || (TREE_CODE (op) == CALL_EXPR | |
542 && !CALL_EXPR_RETURN_SLOT_OPT (op))) | |
543 && is_really_empty_class (type); | |
544 } | |
545 | |
546 /* Returns true if evaluating E as an lvalue has side-effects; | |
547 specifically, a volatile lvalue has TREE_SIDE_EFFECTS, but it doesn't really | |
548 have side-effects until there is a read or write through it. */ | |
549 | |
550 static bool | |
551 lvalue_has_side_effects (tree e) | |
552 { | |
553 if (!TREE_SIDE_EFFECTS (e)) | |
554 return false; | |
555 while (handled_component_p (e)) | |
556 { | |
557 if (TREE_CODE (e) == ARRAY_REF | |
558 && TREE_SIDE_EFFECTS (TREE_OPERAND (e, 1))) | |
559 return true; | |
560 e = TREE_OPERAND (e, 0); | |
561 } | |
562 if (DECL_P (e)) | |
563 /* Just naming a variable has no side-effects. */ | |
564 return false; | |
565 else if (INDIRECT_REF_P (e)) | |
566 /* Similarly, indirection has no side-effects. */ | |
567 return TREE_SIDE_EFFECTS (TREE_OPERAND (e, 0)); | |
568 else | |
569 /* For anything else, trust TREE_SIDE_EFFECTS. */ | |
570 return TREE_SIDE_EFFECTS (e); | |
571 } | |
572 | |
573 /* Do C++-specific gimplification. Args are as for gimplify_expr. */ | |
574 | |
575 int | |
576 cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p) | |
577 { | |
578 int saved_stmts_are_full_exprs_p = 0; | |
579 location_t loc = EXPR_LOC_OR_LOC (*expr_p, input_location); | |
580 enum tree_code code = TREE_CODE (*expr_p); | |
581 enum gimplify_status ret; | |
582 | |
583 if (STATEMENT_CODE_P (code)) | |
584 { | |
585 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p (); | |
586 current_stmt_tree ()->stmts_are_full_exprs_p | |
587 = STMT_IS_FULL_EXPR_P (*expr_p); | |
588 } | |
589 | |
590 switch (code) | |
591 { | |
592 case AGGR_INIT_EXPR: | |
593 simplify_aggr_init_expr (expr_p); | |
594 ret = GS_OK; | |
595 break; | |
596 | |
597 case VEC_INIT_EXPR: | |
598 { | |
599 location_t loc = input_location; | |
600 tree init = VEC_INIT_EXPR_INIT (*expr_p); | |
601 int from_array = (init && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE); | |
602 gcc_assert (EXPR_HAS_LOCATION (*expr_p)); | |
603 input_location = EXPR_LOCATION (*expr_p); | |
604 *expr_p = build_vec_init (VEC_INIT_EXPR_SLOT (*expr_p), NULL_TREE, | |
605 init, VEC_INIT_EXPR_VALUE_INIT (*expr_p), | |
606 from_array, | |
607 tf_warning_or_error); | |
608 hash_set<tree> pset; | |
609 cp_walk_tree (expr_p, cp_fold_r, &pset, NULL); | |
610 cp_genericize_tree (expr_p, false); | |
611 ret = GS_OK; | |
612 input_location = loc; | |
613 } | |
614 break; | |
615 | |
616 case THROW_EXPR: | |
617 /* FIXME communicate throw type to back end, probably by moving | |
618 THROW_EXPR into ../tree.def. */ | |
619 *expr_p = TREE_OPERAND (*expr_p, 0); | |
620 ret = GS_OK; | |
621 break; | |
622 | |
623 case MUST_NOT_THROW_EXPR: | |
624 ret = gimplify_must_not_throw_expr (expr_p, pre_p); | |
625 break; | |
626 | |
627 /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the | |
628 LHS of an assignment might also be involved in the RHS, as in bug | |
629 25979. */ | |
630 case INIT_EXPR: | |
631 if (fn_contains_cilk_spawn_p (cfun)) | |
632 { | |
633 if (cilk_cp_detect_spawn_and_unwrap (expr_p)) | |
634 return (enum gimplify_status) gimplify_cilk_spawn (expr_p); | |
635 if (seen_error () && contains_cilk_spawn_stmt (*expr_p)) | |
636 return GS_ERROR; | |
637 } | |
638 | |
639 cp_gimplify_init_expr (expr_p); | |
640 if (TREE_CODE (*expr_p) != INIT_EXPR) | |
641 return GS_OK; | |
642 /* Fall through. */ | |
643 case MODIFY_EXPR: | |
644 modify_expr_case: | |
645 { | |
646 if (fn_contains_cilk_spawn_p (cfun) | |
647 && cilk_cp_detect_spawn_and_unwrap (expr_p) | |
648 && !seen_error ()) | |
649 return (enum gimplify_status) gimplify_cilk_spawn (expr_p); | |
650 /* If the back end isn't clever enough to know that the lhs and rhs | |
651 types are the same, add an explicit conversion. */ | |
652 tree op0 = TREE_OPERAND (*expr_p, 0); | |
653 tree op1 = TREE_OPERAND (*expr_p, 1); | |
654 | |
655 if (!error_operand_p (op0) | |
656 && !error_operand_p (op1) | |
657 && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0)) | |
658 || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1))) | |
659 && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0))) | |
660 TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR, | |
661 TREE_TYPE (op0), op1); | |
662 | |
663 else if (simple_empty_class_p (TREE_TYPE (op0), op1)) | |
664 { | |
665 /* Remove any copies of empty classes. Also drop volatile | |
666 variables on the RHS to avoid infinite recursion from | |
667 gimplify_expr trying to load the value. */ | |
668 if (TREE_SIDE_EFFECTS (op1)) | |
669 { | |
670 if (TREE_THIS_VOLATILE (op1) | |
671 && (REFERENCE_CLASS_P (op1) || DECL_P (op1))) | |
672 op1 = build_fold_addr_expr (op1); | |
673 | |
674 gimplify_and_add (op1, pre_p); | |
675 } | |
676 gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p, | |
677 is_gimple_lvalue, fb_lvalue); | |
678 *expr_p = TREE_OPERAND (*expr_p, 0); | |
679 } | |
680 /* P0145 says that the RHS is sequenced before the LHS. | |
681 gimplify_modify_expr gimplifies the RHS before the LHS, but that | |
682 isn't quite strong enough in two cases: | |
683 | |
684 1) gimplify.c wants to leave a CALL_EXPR on the RHS, which would | |
685 mean it's evaluated after the LHS. | |
686 | |
687 2) the value calculation of the RHS is also sequenced before the | |
688 LHS, so for scalar assignment we need to preevaluate if the | |
689 RHS could be affected by LHS side-effects even if it has no | |
690 side-effects of its own. We don't need this for classes because | |
691 class assignment takes its RHS by reference. */ | |
692 else if (flag_strong_eval_order > 1 | |
693 && TREE_CODE (*expr_p) == MODIFY_EXPR | |
694 && lvalue_has_side_effects (op0) | |
695 && (TREE_CODE (op1) == CALL_EXPR | |
696 || (SCALAR_TYPE_P (TREE_TYPE (op1)) | |
697 && !TREE_CONSTANT (op1)))) | |
698 TREE_OPERAND (*expr_p, 1) = get_formal_tmp_var (op1, pre_p); | |
699 } | |
700 ret = GS_OK; | |
701 break; | |
702 | |
703 case EMPTY_CLASS_EXPR: | |
704 /* We create an empty CONSTRUCTOR with RECORD_TYPE. */ | |
705 *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL); | |
706 ret = GS_OK; | |
707 break; | |
708 | |
709 case BASELINK: | |
710 *expr_p = BASELINK_FUNCTIONS (*expr_p); | |
711 ret = GS_OK; | |
712 break; | |
713 | |
714 case TRY_BLOCK: | |
715 genericize_try_block (expr_p); | |
716 ret = GS_OK; | |
717 break; | |
718 | |
719 case HANDLER: | |
720 genericize_catch_block (expr_p); | |
721 ret = GS_OK; | |
722 break; | |
723 | |
724 case EH_SPEC_BLOCK: | |
725 genericize_eh_spec_block (expr_p); | |
726 ret = GS_OK; | |
727 break; | |
728 | |
729 case USING_STMT: | |
730 gcc_unreachable (); | |
731 | |
732 case FOR_STMT: | |
733 case WHILE_STMT: | |
734 case DO_STMT: | |
735 case SWITCH_STMT: | |
736 case CONTINUE_STMT: | |
737 case BREAK_STMT: | |
738 gcc_unreachable (); | |
739 | |
740 case OMP_FOR: | |
741 case OMP_SIMD: | |
742 case OMP_DISTRIBUTE: | |
743 case OMP_TASKLOOP: | |
744 ret = cp_gimplify_omp_for (expr_p, pre_p); | |
745 break; | |
746 | |
747 case EXPR_STMT: | |
748 gimplify_expr_stmt (expr_p); | |
749 ret = GS_OK; | |
750 break; | |
751 | |
752 case UNARY_PLUS_EXPR: | |
753 { | |
754 tree arg = TREE_OPERAND (*expr_p, 0); | |
755 tree type = TREE_TYPE (*expr_p); | |
756 *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg) | |
757 : arg; | |
758 ret = GS_OK; | |
759 } | |
760 break; | |
761 | |
762 case CILK_SPAWN_STMT: | |
763 gcc_assert(fn_contains_cilk_spawn_p (cfun) | |
764 && cilk_cp_detect_spawn_and_unwrap (expr_p)); | |
765 | |
766 if (!seen_error ()) | |
767 return (enum gimplify_status) gimplify_cilk_spawn (expr_p); | |
768 return GS_ERROR; | |
769 | |
770 case CALL_EXPR: | |
771 if (fn_contains_cilk_spawn_p (cfun) | |
772 && cilk_cp_detect_spawn_and_unwrap (expr_p) | |
773 && !seen_error ()) | |
774 return (enum gimplify_status) gimplify_cilk_spawn (expr_p); | |
775 ret = GS_OK; | |
776 if (!CALL_EXPR_FN (*expr_p)) | |
777 /* Internal function call. */; | |
778 else if (CALL_EXPR_REVERSE_ARGS (*expr_p)) | |
779 { | |
780 /* This is a call to a (compound) assignment operator that used | |
781 the operator syntax; gimplify the RHS first. */ | |
782 gcc_assert (call_expr_nargs (*expr_p) == 2); | |
783 gcc_assert (!CALL_EXPR_ORDERED_ARGS (*expr_p)); | |
784 enum gimplify_status t | |
785 = gimplify_arg (&CALL_EXPR_ARG (*expr_p, 1), pre_p, loc); | |
786 if (t == GS_ERROR) | |
787 ret = GS_ERROR; | |
788 } | |
789 else if (CALL_EXPR_ORDERED_ARGS (*expr_p)) | |
790 { | |
791 /* Leave the last argument for gimplify_call_expr, to avoid problems | |
792 with __builtin_va_arg_pack(). */ | |
793 int nargs = call_expr_nargs (*expr_p) - 1; | |
794 for (int i = 0; i < nargs; ++i) | |
795 { | |
796 enum gimplify_status t | |
797 = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p, loc); | |
798 if (t == GS_ERROR) | |
799 ret = GS_ERROR; | |
800 } | |
801 } | |
802 else if (flag_strong_eval_order | |
803 && !CALL_EXPR_OPERATOR_SYNTAX (*expr_p)) | |
804 { | |
805 /* If flag_strong_eval_order, evaluate the object argument first. */ | |
806 tree fntype = TREE_TYPE (CALL_EXPR_FN (*expr_p)); | |
807 if (POINTER_TYPE_P (fntype)) | |
808 fntype = TREE_TYPE (fntype); | |
809 if (TREE_CODE (fntype) == METHOD_TYPE) | |
810 { | |
811 enum gimplify_status t | |
812 = gimplify_arg (&CALL_EXPR_ARG (*expr_p, 0), pre_p, loc); | |
813 if (t == GS_ERROR) | |
814 ret = GS_ERROR; | |
815 } | |
816 } | |
817 break; | |
818 | |
819 case RETURN_EXPR: | |
820 if (TREE_OPERAND (*expr_p, 0) | |
821 && (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == INIT_EXPR | |
822 || TREE_CODE (TREE_OPERAND (*expr_p, 0)) == MODIFY_EXPR)) | |
823 { | |
824 expr_p = &TREE_OPERAND (*expr_p, 0); | |
825 code = TREE_CODE (*expr_p); | |
826 /* Avoid going through the INIT_EXPR case, which can | |
827 degrade INIT_EXPRs into AGGR_INIT_EXPRs. */ | |
828 goto modify_expr_case; | |
829 } | |
830 /* Fall through. */ | |
831 | |
832 default: | |
833 ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p); | |
834 break; | |
835 } | |
836 | |
837 /* Restore saved state. */ | |
838 if (STATEMENT_CODE_P (code)) | |
839 current_stmt_tree ()->stmts_are_full_exprs_p | |
840 = saved_stmts_are_full_exprs_p; | |
841 | |
842 return ret; | |
843 } | |
844 | |
845 static inline bool | |
846 is_invisiref_parm (const_tree t) | |
847 { | |
848 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL) | |
849 && DECL_BY_REFERENCE (t)); | |
850 } | |
851 | |
852 /* Return true if the uid in both int tree maps are equal. */ | |
853 | |
854 bool | |
855 cxx_int_tree_map_hasher::equal (cxx_int_tree_map *a, cxx_int_tree_map *b) | |
856 { | |
857 return (a->uid == b->uid); | |
858 } | |
859 | |
860 /* Hash a UID in a cxx_int_tree_map. */ | |
861 | |
862 unsigned int | |
863 cxx_int_tree_map_hasher::hash (cxx_int_tree_map *item) | |
864 { | |
865 return item->uid; | |
866 } | |
867 | |
868 /* A stable comparison routine for use with splay trees and DECLs. */ | |
869 | |
870 static int | |
871 splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb) | |
872 { | |
873 tree a = (tree) xa; | |
874 tree b = (tree) xb; | |
875 | |
876 return DECL_UID (a) - DECL_UID (b); | |
877 } | |
878 | |
879 /* OpenMP context during genericization. */ | |
880 | |
881 struct cp_genericize_omp_taskreg | |
882 { | |
883 bool is_parallel; | |
884 bool default_shared; | |
885 struct cp_genericize_omp_taskreg *outer; | |
886 splay_tree variables; | |
887 }; | |
888 | |
889 /* Return true if genericization should try to determine if | |
890 DECL is firstprivate or shared within task regions. */ | |
891 | |
892 static bool | |
893 omp_var_to_track (tree decl) | |
894 { | |
895 tree type = TREE_TYPE (decl); | |
896 if (is_invisiref_parm (decl)) | |
897 type = TREE_TYPE (type); | |
898 else if (TREE_CODE (type) == REFERENCE_TYPE) | |
899 type = TREE_TYPE (type); | |
900 while (TREE_CODE (type) == ARRAY_TYPE) | |
901 type = TREE_TYPE (type); | |
902 if (type == error_mark_node || !CLASS_TYPE_P (type)) | |
903 return false; | |
904 if (VAR_P (decl) && CP_DECL_THREAD_LOCAL_P (decl)) | |
905 return false; | |
906 if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED) | |
907 return false; | |
908 return true; | |
909 } | |
910 | |
911 /* Note DECL use in OpenMP region OMP_CTX during genericization. */ | |
912 | |
913 static void | |
914 omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl) | |
915 { | |
916 splay_tree_node n = splay_tree_lookup (omp_ctx->variables, | |
917 (splay_tree_key) decl); | |
918 if (n == NULL) | |
919 { | |
920 int flags = OMP_CLAUSE_DEFAULT_SHARED; | |
921 if (omp_ctx->outer) | |
922 omp_cxx_notice_variable (omp_ctx->outer, decl); | |
923 if (!omp_ctx->default_shared) | |
924 { | |
925 struct cp_genericize_omp_taskreg *octx; | |
926 | |
927 for (octx = omp_ctx->outer; octx; octx = octx->outer) | |
928 { | |
929 n = splay_tree_lookup (octx->variables, (splay_tree_key) decl); | |
930 if (n && n->value != OMP_CLAUSE_DEFAULT_SHARED) | |
931 { | |
932 flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; | |
933 break; | |
934 } | |
935 if (octx->is_parallel) | |
936 break; | |
937 } | |
938 if (octx == NULL | |
939 && (TREE_CODE (decl) == PARM_DECL | |
940 || (!(TREE_STATIC (decl) || DECL_EXTERNAL (decl)) | |
941 && DECL_CONTEXT (decl) == current_function_decl))) | |
942 flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE; | |
943 if (flags == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE) | |
944 { | |
945 /* DECL is implicitly determined firstprivate in | |
946 the current task construct. Ensure copy ctor and | |
947 dtor are instantiated, because during gimplification | |
948 it will be already too late. */ | |
949 tree type = TREE_TYPE (decl); | |
950 if (is_invisiref_parm (decl)) | |
951 type = TREE_TYPE (type); | |
952 else if (TREE_CODE (type) == REFERENCE_TYPE) | |
953 type = TREE_TYPE (type); | |
954 while (TREE_CODE (type) == ARRAY_TYPE) | |
955 type = TREE_TYPE (type); | |
956 get_copy_ctor (type, tf_none); | |
957 get_dtor (type, tf_none); | |
958 } | |
959 } | |
960 splay_tree_insert (omp_ctx->variables, (splay_tree_key) decl, flags); | |
961 } | |
962 } | |
963 | |
964 /* Genericization context. */ | |
965 | |
966 struct cp_genericize_data | |
967 { | |
968 hash_set<tree> *p_set; | |
969 vec<tree> bind_expr_stack; | |
970 struct cp_genericize_omp_taskreg *omp_ctx; | |
971 tree try_block; | |
972 bool no_sanitize_p; | |
973 bool handle_invisiref_parm_p; | |
974 }; | |
975 | |
976 /* Perform any pre-gimplification folding of C++ front end trees to | |
977 GENERIC. | |
978 Note: The folding of none-omp cases is something to move into | |
979 the middle-end. As for now we have most foldings only on GENERIC | |
980 in fold-const, we need to perform this before transformation to | |
981 GIMPLE-form. */ | |
982 | |
983 static tree | |
984 cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data) | |
985 { | |
986 tree stmt; | |
987 enum tree_code code; | |
988 | |
989 *stmt_p = stmt = cp_fold (*stmt_p); | |
990 | |
991 if (((hash_set<tree> *) data)->add (stmt)) | |
992 { | |
993 /* Don't walk subtrees of stmts we've already walked once, otherwise | |
994 we can have exponential complexity with e.g. lots of nested | |
995 SAVE_EXPRs or TARGET_EXPRs. cp_fold uses a cache and will return | |
996 always the same tree, which the first time cp_fold_r has been | |
997 called on it had the subtrees walked. */ | |
998 *walk_subtrees = 0; | |
999 return NULL; | |
1000 } | |
1001 | |
1002 code = TREE_CODE (stmt); | |
1003 if (code == OMP_FOR || code == OMP_SIMD || code == OMP_DISTRIBUTE | |
1004 || code == OMP_TASKLOOP || code == CILK_FOR || code == CILK_SIMD | |
1005 || code == OACC_LOOP) | |
1006 { | |
1007 tree x; | |
1008 int i, n; | |
1009 | |
1010 cp_walk_tree (&OMP_FOR_BODY (stmt), cp_fold_r, data, NULL); | |
1011 cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_fold_r, data, NULL); | |
1012 cp_walk_tree (&OMP_FOR_INIT (stmt), cp_fold_r, data, NULL); | |
1013 x = OMP_FOR_COND (stmt); | |
1014 if (x && TREE_CODE_CLASS (TREE_CODE (x)) == tcc_comparison) | |
1015 { | |
1016 cp_walk_tree (&TREE_OPERAND (x, 0), cp_fold_r, data, NULL); | |
1017 cp_walk_tree (&TREE_OPERAND (x, 1), cp_fold_r, data, NULL); | |
1018 } | |
1019 else if (x && TREE_CODE (x) == TREE_VEC) | |
1020 { | |
1021 n = TREE_VEC_LENGTH (x); | |
1022 for (i = 0; i < n; i++) | |
1023 { | |
1024 tree o = TREE_VEC_ELT (x, i); | |
1025 if (o && TREE_CODE_CLASS (TREE_CODE (o)) == tcc_comparison) | |
1026 cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL); | |
1027 } | |
1028 } | |
1029 x = OMP_FOR_INCR (stmt); | |
1030 if (x && TREE_CODE (x) == TREE_VEC) | |
1031 { | |
1032 n = TREE_VEC_LENGTH (x); | |
1033 for (i = 0; i < n; i++) | |
1034 { | |
1035 tree o = TREE_VEC_ELT (x, i); | |
1036 if (o && TREE_CODE (o) == MODIFY_EXPR) | |
1037 o = TREE_OPERAND (o, 1); | |
1038 if (o && (TREE_CODE (o) == PLUS_EXPR || TREE_CODE (o) == MINUS_EXPR | |
1039 || TREE_CODE (o) == POINTER_PLUS_EXPR)) | |
1040 { | |
1041 cp_walk_tree (&TREE_OPERAND (o, 0), cp_fold_r, data, NULL); | |
1042 cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL); | |
1043 } | |
1044 } | |
1045 } | |
1046 cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_fold_r, data, NULL); | |
1047 *walk_subtrees = 0; | |
1048 } | |
1049 | |
1050 return NULL; | |
1051 } | |
1052 | |
1053 /* Fold ALL the trees! FIXME we should be able to remove this, but | |
1054 apparently that still causes optimization regressions. */ | |
1055 | |
1056 void | |
1057 cp_fold_function (tree fndecl) | |
1058 { | |
1059 hash_set<tree> pset; | |
1060 cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_r, &pset, NULL); | |
1061 } | |
1062 | |
1063 /* Perform any pre-gimplification lowering of C++ front end trees to | |
1064 GENERIC. */ | |
1065 | |
1066 static tree | |
1067 cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data) | |
1068 { | |
1069 tree stmt = *stmt_p; | |
1070 struct cp_genericize_data *wtd = (struct cp_genericize_data *) data; | |
1071 hash_set<tree> *p_set = wtd->p_set; | |
1072 | |
1073 /* If in an OpenMP context, note var uses. */ | |
1074 if (__builtin_expect (wtd->omp_ctx != NULL, 0) | |
1075 && (VAR_P (stmt) | |
1076 || TREE_CODE (stmt) == PARM_DECL | |
1077 || TREE_CODE (stmt) == RESULT_DECL) | |
1078 && omp_var_to_track (stmt)) | |
1079 omp_cxx_notice_variable (wtd->omp_ctx, stmt); | |
1080 | |
1081 /* Dereference invisible reference parms. */ | |
1082 if (wtd->handle_invisiref_parm_p && is_invisiref_parm (stmt)) | |
1083 { | |
1084 *stmt_p = convert_from_reference (stmt); | |
1085 p_set->add (*stmt_p); | |
1086 *walk_subtrees = 0; | |
1087 return NULL; | |
1088 } | |
1089 | |
1090 /* Map block scope extern declarations to visible declarations with the | |
1091 same name and type in outer scopes if any. */ | |
1092 if (cp_function_chain->extern_decl_map | |
1093 && VAR_OR_FUNCTION_DECL_P (stmt) | |
1094 && DECL_EXTERNAL (stmt)) | |
1095 { | |
1096 struct cxx_int_tree_map *h, in; | |
1097 in.uid = DECL_UID (stmt); | |
1098 h = cp_function_chain->extern_decl_map->find_with_hash (&in, in.uid); | |
1099 if (h) | |
1100 { | |
1101 *stmt_p = h->to; | |
1102 *walk_subtrees = 0; | |
1103 return NULL; | |
1104 } | |
1105 } | |
1106 | |
1107 if (TREE_CODE (stmt) == INTEGER_CST | |
1108 && TREE_CODE (TREE_TYPE (stmt)) == REFERENCE_TYPE | |
1109 && (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT)) | |
1110 && !wtd->no_sanitize_p) | |
1111 { | |
1112 ubsan_maybe_instrument_reference (stmt_p); | |
1113 if (*stmt_p != stmt) | |
1114 { | |
1115 *walk_subtrees = 0; | |
1116 return NULL_TREE; | |
1117 } | |
1118 } | |
1119 | |
1120 /* Other than invisiref parms, don't walk the same tree twice. */ | |
1121 if (p_set->contains (stmt)) | |
1122 { | |
1123 *walk_subtrees = 0; | |
1124 return NULL_TREE; | |
1125 } | |
1126 | |
1127 switch (TREE_CODE (stmt)) | |
1128 { | |
1129 case ADDR_EXPR: | |
1130 if (is_invisiref_parm (TREE_OPERAND (stmt, 0))) | |
1131 { | |
1132 /* If in an OpenMP context, note var uses. */ | |
1133 if (__builtin_expect (wtd->omp_ctx != NULL, 0) | |
1134 && omp_var_to_track (TREE_OPERAND (stmt, 0))) | |
1135 omp_cxx_notice_variable (wtd->omp_ctx, TREE_OPERAND (stmt, 0)); | |
1136 *stmt_p = fold_convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0)); | |
1137 *walk_subtrees = 0; | |
1138 } | |
1139 break; | |
1140 | |
1141 case RETURN_EXPR: | |
1142 if (TREE_OPERAND (stmt, 0) && is_invisiref_parm (TREE_OPERAND (stmt, 0))) | |
1143 /* Don't dereference an invisiref RESULT_DECL inside a RETURN_EXPR. */ | |
1144 *walk_subtrees = 0; | |
1145 break; | |
1146 | |
1147 case OMP_CLAUSE: | |
1148 switch (OMP_CLAUSE_CODE (stmt)) | |
1149 { | |
1150 case OMP_CLAUSE_LASTPRIVATE: | |
1151 /* Don't dereference an invisiref in OpenMP clauses. */ | |
1152 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) | |
1153 { | |
1154 *walk_subtrees = 0; | |
1155 if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt)) | |
1156 cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt), | |
1157 cp_genericize_r, data, NULL); | |
1158 } | |
1159 break; | |
1160 case OMP_CLAUSE_PRIVATE: | |
1161 /* Don't dereference an invisiref in OpenMP clauses. */ | |
1162 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) | |
1163 *walk_subtrees = 0; | |
1164 else if (wtd->omp_ctx != NULL) | |
1165 { | |
1166 /* Private clause doesn't cause any references to the | |
1167 var in outer contexts, avoid calling | |
1168 omp_cxx_notice_variable for it. */ | |
1169 struct cp_genericize_omp_taskreg *old = wtd->omp_ctx; | |
1170 wtd->omp_ctx = NULL; | |
1171 cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r, | |
1172 data, NULL); | |
1173 wtd->omp_ctx = old; | |
1174 *walk_subtrees = 0; | |
1175 } | |
1176 break; | |
1177 case OMP_CLAUSE_SHARED: | |
1178 case OMP_CLAUSE_FIRSTPRIVATE: | |
1179 case OMP_CLAUSE_COPYIN: | |
1180 case OMP_CLAUSE_COPYPRIVATE: | |
1181 /* Don't dereference an invisiref in OpenMP clauses. */ | |
1182 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) | |
1183 *walk_subtrees = 0; | |
1184 break; | |
1185 case OMP_CLAUSE_REDUCTION: | |
1186 /* Don't dereference an invisiref in reduction clause's | |
1187 OMP_CLAUSE_DECL either. OMP_CLAUSE_REDUCTION_{INIT,MERGE} | |
1188 still needs to be genericized. */ | |
1189 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt))) | |
1190 { | |
1191 *walk_subtrees = 0; | |
1192 if (OMP_CLAUSE_REDUCTION_INIT (stmt)) | |
1193 cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (stmt), | |
1194 cp_genericize_r, data, NULL); | |
1195 if (OMP_CLAUSE_REDUCTION_MERGE (stmt)) | |
1196 cp_walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (stmt), | |
1197 cp_genericize_r, data, NULL); | |
1198 } | |
1199 break; | |
1200 default: | |
1201 break; | |
1202 } | |
1203 break; | |
1204 | |
1205 /* Due to the way voidify_wrapper_expr is written, we don't get a chance | |
1206 to lower this construct before scanning it, so we need to lower these | |
1207 before doing anything else. */ | |
1208 case CLEANUP_STMT: | |
1209 *stmt_p = build2_loc (EXPR_LOCATION (stmt), | |
1210 CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR | |
1211 : TRY_FINALLY_EXPR, | |
1212 void_type_node, | |
1213 CLEANUP_BODY (stmt), | |
1214 CLEANUP_EXPR (stmt)); | |
1215 break; | |
1216 | |
1217 case IF_STMT: | |
1218 genericize_if_stmt (stmt_p); | |
1219 /* *stmt_p has changed, tail recurse to handle it again. */ | |
1220 return cp_genericize_r (stmt_p, walk_subtrees, data); | |
1221 | |
1222 /* COND_EXPR might have incompatible types in branches if one or both | |
1223 arms are bitfields. Fix it up now. */ | |
1224 case COND_EXPR: | |
1225 { | |
1226 tree type_left | |
1227 = (TREE_OPERAND (stmt, 1) | |
1228 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1)) | |
1229 : NULL_TREE); | |
1230 tree type_right | |
1231 = (TREE_OPERAND (stmt, 2) | |
1232 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2)) | |
1233 : NULL_TREE); | |
1234 if (type_left | |
1235 && !useless_type_conversion_p (TREE_TYPE (stmt), | |
1236 TREE_TYPE (TREE_OPERAND (stmt, 1)))) | |
1237 { | |
1238 TREE_OPERAND (stmt, 1) | |
1239 = fold_convert (type_left, TREE_OPERAND (stmt, 1)); | |
1240 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), | |
1241 type_left)); | |
1242 } | |
1243 if (type_right | |
1244 && !useless_type_conversion_p (TREE_TYPE (stmt), | |
1245 TREE_TYPE (TREE_OPERAND (stmt, 2)))) | |
1246 { | |
1247 TREE_OPERAND (stmt, 2) | |
1248 = fold_convert (type_right, TREE_OPERAND (stmt, 2)); | |
1249 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt), | |
1250 type_right)); | |
1251 } | |
1252 } | |
1253 break; | |
1254 | |
1255 case BIND_EXPR: | |
1256 if (__builtin_expect (wtd->omp_ctx != NULL, 0)) | |
1257 { | |
1258 tree decl; | |
1259 for (decl = BIND_EXPR_VARS (stmt); decl; decl = DECL_CHAIN (decl)) | |
1260 if (VAR_P (decl) | |
1261 && !DECL_EXTERNAL (decl) | |
1262 && omp_var_to_track (decl)) | |
1263 { | |
1264 splay_tree_node n | |
1265 = splay_tree_lookup (wtd->omp_ctx->variables, | |
1266 (splay_tree_key) decl); | |
1267 if (n == NULL) | |
1268 splay_tree_insert (wtd->omp_ctx->variables, | |
1269 (splay_tree_key) decl, | |
1270 TREE_STATIC (decl) | |
1271 ? OMP_CLAUSE_DEFAULT_SHARED | |
1272 : OMP_CLAUSE_DEFAULT_PRIVATE); | |
1273 } | |
1274 } | |
1275 if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR)) | |
1276 { | |
1277 /* The point here is to not sanitize static initializers. */ | |
1278 bool no_sanitize_p = wtd->no_sanitize_p; | |
1279 wtd->no_sanitize_p = true; | |
1280 for (tree decl = BIND_EXPR_VARS (stmt); | |
1281 decl; | |
1282 decl = DECL_CHAIN (decl)) | |
1283 if (VAR_P (decl) | |
1284 && TREE_STATIC (decl) | |
1285 && DECL_INITIAL (decl)) | |
1286 cp_walk_tree (&DECL_INITIAL (decl), cp_genericize_r, data, NULL); | |
1287 wtd->no_sanitize_p = no_sanitize_p; | |
1288 } | |
1289 wtd->bind_expr_stack.safe_push (stmt); | |
1290 cp_walk_tree (&BIND_EXPR_BODY (stmt), | |
1291 cp_genericize_r, data, NULL); | |
1292 wtd->bind_expr_stack.pop (); | |
1293 break; | |
1294 | |
1295 case USING_STMT: | |
1296 { | |
1297 tree block = NULL_TREE; | |
1298 | |
1299 /* Get the innermost inclosing GIMPLE_BIND that has a non NULL | |
1300 BLOCK, and append an IMPORTED_DECL to its | |
1301 BLOCK_VARS chained list. */ | |
1302 if (wtd->bind_expr_stack.exists ()) | |
1303 { | |
1304 int i; | |
1305 for (i = wtd->bind_expr_stack.length () - 1; i >= 0; i--) | |
1306 if ((block = BIND_EXPR_BLOCK (wtd->bind_expr_stack[i]))) | |
1307 break; | |
1308 } | |
1309 if (block) | |
1310 { | |
1311 tree using_directive; | |
1312 gcc_assert (TREE_OPERAND (stmt, 0)); | |
1313 | |
1314 using_directive = make_node (IMPORTED_DECL); | |
1315 TREE_TYPE (using_directive) = void_type_node; | |
1316 | |
1317 IMPORTED_DECL_ASSOCIATED_DECL (using_directive) | |
1318 = TREE_OPERAND (stmt, 0); | |
1319 DECL_CHAIN (using_directive) = BLOCK_VARS (block); | |
1320 BLOCK_VARS (block) = using_directive; | |
1321 } | |
1322 /* The USING_STMT won't appear in GENERIC. */ | |
1323 *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node); | |
1324 *walk_subtrees = 0; | |
1325 } | |
1326 break; | |
1327 | |
1328 case DECL_EXPR: | |
1329 if (TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL) | |
1330 { | |
1331 /* Using decls inside DECL_EXPRs are just dropped on the floor. */ | |
1332 *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node); | |
1333 *walk_subtrees = 0; | |
1334 } | |
1335 else | |
1336 { | |
1337 tree d = DECL_EXPR_DECL (stmt); | |
1338 if (VAR_P (d)) | |
1339 gcc_assert (CP_DECL_THREAD_LOCAL_P (d) == DECL_THREAD_LOCAL_P (d)); | |
1340 } | |
1341 break; | |
1342 | |
1343 case OMP_PARALLEL: | |
1344 case OMP_TASK: | |
1345 case OMP_TASKLOOP: | |
1346 { | |
1347 struct cp_genericize_omp_taskreg omp_ctx; | |
1348 tree c, decl; | |
1349 splay_tree_node n; | |
1350 | |
1351 *walk_subtrees = 0; | |
1352 cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL); | |
1353 omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL; | |
1354 omp_ctx.default_shared = omp_ctx.is_parallel; | |
1355 omp_ctx.outer = wtd->omp_ctx; | |
1356 omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0); | |
1357 wtd->omp_ctx = &omp_ctx; | |
1358 for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c)) | |
1359 switch (OMP_CLAUSE_CODE (c)) | |
1360 { | |
1361 case OMP_CLAUSE_SHARED: | |
1362 case OMP_CLAUSE_PRIVATE: | |
1363 case OMP_CLAUSE_FIRSTPRIVATE: | |
1364 case OMP_CLAUSE_LASTPRIVATE: | |
1365 decl = OMP_CLAUSE_DECL (c); | |
1366 if (decl == error_mark_node || !omp_var_to_track (decl)) | |
1367 break; | |
1368 n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl); | |
1369 if (n != NULL) | |
1370 break; | |
1371 splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl, | |
1372 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED | |
1373 ? OMP_CLAUSE_DEFAULT_SHARED | |
1374 : OMP_CLAUSE_DEFAULT_PRIVATE); | |
1375 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE && omp_ctx.outer) | |
1376 omp_cxx_notice_variable (omp_ctx.outer, decl); | |
1377 break; | |
1378 case OMP_CLAUSE_DEFAULT: | |
1379 if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED) | |
1380 omp_ctx.default_shared = true; | |
1381 default: | |
1382 break; | |
1383 } | |
1384 if (TREE_CODE (stmt) == OMP_TASKLOOP) | |
1385 genericize_omp_for_stmt (stmt_p, walk_subtrees, data); | |
1386 else | |
1387 cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL); | |
1388 wtd->omp_ctx = omp_ctx.outer; | |
1389 splay_tree_delete (omp_ctx.variables); | |
1390 } | |
1391 break; | |
1392 | |
1393 case TRY_BLOCK: | |
1394 { | |
1395 *walk_subtrees = 0; | |
1396 tree try_block = wtd->try_block; | |
1397 wtd->try_block = stmt; | |
1398 cp_walk_tree (&TRY_STMTS (stmt), cp_genericize_r, data, NULL); | |
1399 wtd->try_block = try_block; | |
1400 cp_walk_tree (&TRY_HANDLERS (stmt), cp_genericize_r, data, NULL); | |
1401 } | |
1402 break; | |
1403 | |
1404 case MUST_NOT_THROW_EXPR: | |
1405 /* MUST_NOT_THROW_COND might be something else with TM. */ | |
1406 if (MUST_NOT_THROW_COND (stmt) == NULL_TREE) | |
1407 { | |
1408 *walk_subtrees = 0; | |
1409 tree try_block = wtd->try_block; | |
1410 wtd->try_block = stmt; | |
1411 cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_genericize_r, data, NULL); | |
1412 wtd->try_block = try_block; | |
1413 } | |
1414 break; | |
1415 | |
1416 case THROW_EXPR: | |
1417 { | |
1418 location_t loc = location_of (stmt); | |
1419 if (TREE_NO_WARNING (stmt)) | |
1420 /* Never mind. */; | |
1421 else if (wtd->try_block) | |
1422 { | |
1423 if (TREE_CODE (wtd->try_block) == MUST_NOT_THROW_EXPR | |
1424 && warning_at (loc, OPT_Wterminate, | |
1425 "throw will always call terminate()") | |
1426 && cxx_dialect >= cxx11 | |
1427 && DECL_DESTRUCTOR_P (current_function_decl)) | |
1428 inform (loc, "in C++11 destructors default to noexcept"); | |
1429 } | |
1430 else | |
1431 { | |
1432 if (warn_cxx11_compat && cxx_dialect < cxx11 | |
1433 && DECL_DESTRUCTOR_P (current_function_decl) | |
1434 && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)) | |
1435 == NULL_TREE) | |
1436 && (get_defaulted_eh_spec (current_function_decl) | |
1437 == empty_except_spec)) | |
1438 warning_at (loc, OPT_Wc__11_compat, | |
1439 "in C++11 this throw will terminate because " | |
1440 "destructors default to noexcept"); | |
1441 } | |
1442 } | |
1443 break; | |
1444 | |
1445 case CONVERT_EXPR: | |
1446 gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt)); | |
1447 break; | |
1448 | |
1449 case FOR_STMT: | |
1450 genericize_for_stmt (stmt_p, walk_subtrees, data); | |
1451 break; | |
1452 | |
1453 case WHILE_STMT: | |
1454 genericize_while_stmt (stmt_p, walk_subtrees, data); | |
1455 break; | |
1456 | |
1457 case DO_STMT: | |
1458 genericize_do_stmt (stmt_p, walk_subtrees, data); | |
1459 break; | |
1460 | |
1461 case SWITCH_STMT: | |
1462 genericize_switch_stmt (stmt_p, walk_subtrees, data); | |
1463 break; | |
1464 | |
1465 case CONTINUE_STMT: | |
1466 genericize_continue_stmt (stmt_p); | |
1467 break; | |
1468 | |
1469 case BREAK_STMT: | |
1470 genericize_break_stmt (stmt_p); | |
1471 break; | |
1472 | |
1473 case OMP_FOR: | |
1474 case OMP_SIMD: | |
1475 case OMP_DISTRIBUTE: | |
1476 genericize_omp_for_stmt (stmt_p, walk_subtrees, data); | |
1477 break; | |
1478 | |
1479 case PTRMEM_CST: | |
1480 /* By the time we get here we're handing off to the back end, so we don't | |
1481 need or want to preserve PTRMEM_CST anymore. */ | |
1482 *stmt_p = cplus_expand_constant (stmt); | |
1483 *walk_subtrees = 0; | |
1484 break; | |
1485 | |
1486 case MEM_REF: | |
1487 /* For MEM_REF, make sure not to sanitize the second operand even | |
1488 if it has reference type. It is just an offset with a type | |
1489 holding other information. There is no other processing we | |
1490 need to do for INTEGER_CSTs, so just ignore the second argument | |
1491 unconditionally. */ | |
1492 cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_genericize_r, data, NULL); | |
1493 *walk_subtrees = 0; | |
1494 break; | |
1495 | |
1496 case NOP_EXPR: | |
1497 if (!wtd->no_sanitize_p | |
1498 && sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT) | |
1499 && TREE_CODE (TREE_TYPE (stmt)) == REFERENCE_TYPE) | |
1500 ubsan_maybe_instrument_reference (stmt_p); | |
1501 break; | |
1502 | |
1503 case CALL_EXPR: | |
1504 if (!wtd->no_sanitize_p | |
1505 && sanitize_flags_p ((SANITIZE_NULL | |
1506 | SANITIZE_ALIGNMENT | SANITIZE_VPTR))) | |
1507 { | |
1508 tree fn = CALL_EXPR_FN (stmt); | |
1509 if (fn != NULL_TREE | |
1510 && !error_operand_p (fn) | |
1511 && POINTER_TYPE_P (TREE_TYPE (fn)) | |
1512 && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) == METHOD_TYPE) | |
1513 { | |
1514 bool is_ctor | |
1515 = TREE_CODE (fn) == ADDR_EXPR | |
1516 && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL | |
1517 && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0)); | |
1518 if (sanitize_flags_p (SANITIZE_NULL | SANITIZE_ALIGNMENT)) | |
1519 ubsan_maybe_instrument_member_call (stmt, is_ctor); | |
1520 if (sanitize_flags_p (SANITIZE_VPTR) && !is_ctor) | |
1521 cp_ubsan_maybe_instrument_member_call (stmt); | |
1522 } | |
1523 } | |
1524 break; | |
1525 | |
1526 default: | |
1527 if (IS_TYPE_OR_DECL_P (stmt)) | |
1528 *walk_subtrees = 0; | |
1529 break; | |
1530 } | |
1531 | |
1532 p_set->add (*stmt_p); | |
1533 | |
1534 return NULL; | |
1535 } | |
1536 | |
1537 /* Lower C++ front end trees to GENERIC in T_P. */ | |
1538 | |
1539 static void | |
1540 cp_genericize_tree (tree* t_p, bool handle_invisiref_parm_p) | |
1541 { | |
1542 struct cp_genericize_data wtd; | |
1543 | |
1544 wtd.p_set = new hash_set<tree>; | |
1545 wtd.bind_expr_stack.create (0); | |
1546 wtd.omp_ctx = NULL; | |
1547 wtd.try_block = NULL_TREE; | |
1548 wtd.no_sanitize_p = false; | |
1549 wtd.handle_invisiref_parm_p = handle_invisiref_parm_p; | |
1550 cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL); | |
1551 delete wtd.p_set; | |
1552 wtd.bind_expr_stack.release (); | |
1553 if (sanitize_flags_p (SANITIZE_VPTR)) | |
1554 cp_ubsan_instrument_member_accesses (t_p); | |
1555 } | |
1556 | |
1557 /* If a function that should end with a return in non-void | |
1558 function doesn't obviously end with return, add ubsan | |
1559 instrumentation code to verify it at runtime. */ | |
1560 | |
1561 static void | |
1562 cp_ubsan_maybe_instrument_return (tree fndecl) | |
1563 { | |
1564 if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))) | |
1565 || DECL_CONSTRUCTOR_P (fndecl) | |
1566 || DECL_DESTRUCTOR_P (fndecl) | |
1567 || !targetm.warn_func_return (fndecl)) | |
1568 return; | |
1569 | |
1570 tree t = DECL_SAVED_TREE (fndecl); | |
1571 while (t) | |
1572 { | |
1573 switch (TREE_CODE (t)) | |
1574 { | |
1575 case BIND_EXPR: | |
1576 t = BIND_EXPR_BODY (t); | |
1577 continue; | |
1578 case TRY_FINALLY_EXPR: | |
1579 t = TREE_OPERAND (t, 0); | |
1580 continue; | |
1581 case STATEMENT_LIST: | |
1582 { | |
1583 tree_stmt_iterator i = tsi_last (t); | |
1584 if (!tsi_end_p (i)) | |
1585 { | |
1586 t = tsi_stmt (i); | |
1587 continue; | |
1588 } | |
1589 } | |
1590 break; | |
1591 case RETURN_EXPR: | |
1592 return; | |
1593 default: | |
1594 break; | |
1595 } | |
1596 break; | |
1597 } | |
1598 if (t == NULL_TREE) | |
1599 return; | |
1600 tree *p = &DECL_SAVED_TREE (fndecl); | |
1601 if (TREE_CODE (*p) == BIND_EXPR) | |
1602 p = &BIND_EXPR_BODY (*p); | |
1603 t = ubsan_instrument_return (DECL_SOURCE_LOCATION (fndecl)); | |
1604 append_to_statement_list (t, p); | |
1605 } | |
1606 | |
1607 void | |
1608 cp_genericize (tree fndecl) | |
1609 { | |
1610 tree t; | |
1611 | |
1612 /* Fix up the types of parms passed by invisible reference. */ | |
1613 for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t)) | |
1614 if (TREE_ADDRESSABLE (TREE_TYPE (t))) | |
1615 { | |
1616 /* If a function's arguments are copied to create a thunk, | |
1617 then DECL_BY_REFERENCE will be set -- but the type of the | |
1618 argument will be a pointer type, so we will never get | |
1619 here. */ | |
1620 gcc_assert (!DECL_BY_REFERENCE (t)); | |
1621 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t)); | |
1622 TREE_TYPE (t) = DECL_ARG_TYPE (t); | |
1623 DECL_BY_REFERENCE (t) = 1; | |
1624 TREE_ADDRESSABLE (t) = 0; | |
1625 relayout_decl (t); | |
1626 } | |
1627 | |
1628 /* Do the same for the return value. */ | |
1629 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl)))) | |
1630 { | |
1631 t = DECL_RESULT (fndecl); | |
1632 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t)); | |
1633 DECL_BY_REFERENCE (t) = 1; | |
1634 TREE_ADDRESSABLE (t) = 0; | |
1635 relayout_decl (t); | |
1636 if (DECL_NAME (t)) | |
1637 { | |
1638 /* Adjust DECL_VALUE_EXPR of the original var. */ | |
1639 tree outer = outer_curly_brace_block (current_function_decl); | |
1640 tree var; | |
1641 | |
1642 if (outer) | |
1643 for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var)) | |
1644 if (VAR_P (var) | |
1645 && DECL_NAME (t) == DECL_NAME (var) | |
1646 && DECL_HAS_VALUE_EXPR_P (var) | |
1647 && DECL_VALUE_EXPR (var) == t) | |
1648 { | |
1649 tree val = convert_from_reference (t); | |
1650 SET_DECL_VALUE_EXPR (var, val); | |
1651 break; | |
1652 } | |
1653 } | |
1654 } | |
1655 | |
1656 /* If we're a clone, the body is already GIMPLE. */ | |
1657 if (DECL_CLONED_FUNCTION_P (fndecl)) | |
1658 return; | |
1659 | |
1660 /* Allow cp_genericize calls to be nested. */ | |
1661 tree save_bc_label[2]; | |
1662 save_bc_label[bc_break] = bc_label[bc_break]; | |
1663 save_bc_label[bc_continue] = bc_label[bc_continue]; | |
1664 bc_label[bc_break] = NULL_TREE; | |
1665 bc_label[bc_continue] = NULL_TREE; | |
1666 | |
1667 /* Expand all the array notations here. */ | |
1668 if (flag_cilkplus | |
1669 && contains_array_notation_expr (DECL_SAVED_TREE (fndecl))) | |
1670 DECL_SAVED_TREE (fndecl) | |
1671 = expand_array_notation_exprs (DECL_SAVED_TREE (fndecl)); | |
1672 | |
1673 /* We do want to see every occurrence of the parms, so we can't just use | |
1674 walk_tree's hash functionality. */ | |
1675 cp_genericize_tree (&DECL_SAVED_TREE (fndecl), true); | |
1676 | |
1677 if (sanitize_flags_p (SANITIZE_RETURN) | |
1678 && current_function_decl != NULL_TREE) | |
1679 cp_ubsan_maybe_instrument_return (fndecl); | |
1680 | |
1681 /* Do everything else. */ | |
1682 c_genericize (fndecl); | |
1683 | |
1684 gcc_assert (bc_label[bc_break] == NULL); | |
1685 gcc_assert (bc_label[bc_continue] == NULL); | |
1686 bc_label[bc_break] = save_bc_label[bc_break]; | |
1687 bc_label[bc_continue] = save_bc_label[bc_continue]; | |
1688 } | |
1689 | |
1690 /* Build code to apply FN to each member of ARG1 and ARG2. FN may be | |
1691 NULL if there is in fact nothing to do. ARG2 may be null if FN | |
1692 actually only takes one argument. */ | |
1693 | |
1694 static tree | |
1695 cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2) | |
1696 { | |
1697 tree defparm, parm, t; | |
1698 int i = 0; | |
1699 int nargs; | |
1700 tree *argarray; | |
1701 | |
1702 if (fn == NULL) | |
1703 return NULL; | |
1704 | |
1705 nargs = list_length (DECL_ARGUMENTS (fn)); | |
1706 argarray = XALLOCAVEC (tree, nargs); | |
1707 | |
1708 defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn))); | |
1709 if (arg2) | |
1710 defparm = TREE_CHAIN (defparm); | |
1711 | |
1712 if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE) | |
1713 { | |
1714 tree inner_type = TREE_TYPE (arg1); | |
1715 tree start1, end1, p1; | |
1716 tree start2 = NULL, p2 = NULL; | |
1717 tree ret = NULL, lab; | |
1718 | |
1719 start1 = arg1; | |
1720 start2 = arg2; | |
1721 do | |
1722 { | |
1723 inner_type = TREE_TYPE (inner_type); | |
1724 start1 = build4 (ARRAY_REF, inner_type, start1, | |
1725 size_zero_node, NULL, NULL); | |
1726 if (arg2) | |
1727 start2 = build4 (ARRAY_REF, inner_type, start2, | |
1728 size_zero_node, NULL, NULL); | |
1729 } | |
1730 while (TREE_CODE (inner_type) == ARRAY_TYPE); | |
1731 start1 = build_fold_addr_expr_loc (input_location, start1); | |
1732 if (arg2) | |
1733 start2 = build_fold_addr_expr_loc (input_location, start2); | |
1734 | |
1735 end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1)); | |
1736 end1 = fold_build_pointer_plus (start1, end1); | |
1737 | |
1738 p1 = create_tmp_var (TREE_TYPE (start1)); | |
1739 t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1); | |
1740 append_to_statement_list (t, &ret); | |
1741 | |
1742 if (arg2) | |
1743 { | |
1744 p2 = create_tmp_var (TREE_TYPE (start2)); | |
1745 t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2); | |
1746 append_to_statement_list (t, &ret); | |
1747 } | |
1748 | |
1749 lab = create_artificial_label (input_location); | |
1750 t = build1 (LABEL_EXPR, void_type_node, lab); | |
1751 append_to_statement_list (t, &ret); | |
1752 | |
1753 argarray[i++] = p1; | |
1754 if (arg2) | |
1755 argarray[i++] = p2; | |
1756 /* Handle default arguments. */ | |
1757 for (parm = defparm; parm && parm != void_list_node; | |
1758 parm = TREE_CHAIN (parm), i++) | |
1759 argarray[i] = convert_default_arg (TREE_VALUE (parm), | |
1760 TREE_PURPOSE (parm), fn, i, | |
1761 tf_warning_or_error); | |
1762 t = build_call_a (fn, i, argarray); | |
1763 t = fold_convert (void_type_node, t); | |
1764 t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); | |
1765 append_to_statement_list (t, &ret); | |
1766 | |
1767 t = fold_build_pointer_plus (p1, TYPE_SIZE_UNIT (inner_type)); | |
1768 t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t); | |
1769 append_to_statement_list (t, &ret); | |
1770 | |
1771 if (arg2) | |
1772 { | |
1773 t = fold_build_pointer_plus (p2, TYPE_SIZE_UNIT (inner_type)); | |
1774 t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t); | |
1775 append_to_statement_list (t, &ret); | |
1776 } | |
1777 | |
1778 t = build2 (NE_EXPR, boolean_type_node, p1, end1); | |
1779 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL); | |
1780 append_to_statement_list (t, &ret); | |
1781 | |
1782 return ret; | |
1783 } | |
1784 else | |
1785 { | |
1786 argarray[i++] = build_fold_addr_expr_loc (input_location, arg1); | |
1787 if (arg2) | |
1788 argarray[i++] = build_fold_addr_expr_loc (input_location, arg2); | |
1789 /* Handle default arguments. */ | |
1790 for (parm = defparm; parm && parm != void_list_node; | |
1791 parm = TREE_CHAIN (parm), i++) | |
1792 argarray[i] = convert_default_arg (TREE_VALUE (parm), | |
1793 TREE_PURPOSE (parm), | |
1794 fn, i, tf_warning_or_error); | |
1795 t = build_call_a (fn, i, argarray); | |
1796 t = fold_convert (void_type_node, t); | |
1797 return fold_build_cleanup_point_expr (TREE_TYPE (t), t); | |
1798 } | |
1799 } | |
1800 | |
1801 /* Return code to initialize DECL with its default constructor, or | |
1802 NULL if there's nothing to do. */ | |
1803 | |
1804 tree | |
1805 cxx_omp_clause_default_ctor (tree clause, tree decl, tree /*outer*/) | |
1806 { | |
1807 tree info = CP_OMP_CLAUSE_INFO (clause); | |
1808 tree ret = NULL; | |
1809 | |
1810 if (info) | |
1811 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), decl, NULL); | |
1812 | |
1813 return ret; | |
1814 } | |
1815 | |
1816 /* Return code to initialize DST with a copy constructor from SRC. */ | |
1817 | |
1818 tree | |
1819 cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src) | |
1820 { | |
1821 tree info = CP_OMP_CLAUSE_INFO (clause); | |
1822 tree ret = NULL; | |
1823 | |
1824 if (info) | |
1825 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), dst, src); | |
1826 if (ret == NULL) | |
1827 ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); | |
1828 | |
1829 return ret; | |
1830 } | |
1831 | |
1832 /* Similarly, except use an assignment operator instead. */ | |
1833 | |
1834 tree | |
1835 cxx_omp_clause_assign_op (tree clause, tree dst, tree src) | |
1836 { | |
1837 tree info = CP_OMP_CLAUSE_INFO (clause); | |
1838 tree ret = NULL; | |
1839 | |
1840 if (info) | |
1841 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), dst, src); | |
1842 if (ret == NULL) | |
1843 ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src); | |
1844 | |
1845 return ret; | |
1846 } | |
1847 | |
1848 /* Return code to destroy DECL. */ | |
1849 | |
1850 tree | |
1851 cxx_omp_clause_dtor (tree clause, tree decl) | |
1852 { | |
1853 tree info = CP_OMP_CLAUSE_INFO (clause); | |
1854 tree ret = NULL; | |
1855 | |
1856 if (info) | |
1857 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), decl, NULL); | |
1858 | |
1859 return ret; | |
1860 } | |
1861 | |
1862 /* True if OpenMP should privatize what this DECL points to rather | |
1863 than the DECL itself. */ | |
1864 | |
1865 bool | |
1866 cxx_omp_privatize_by_reference (const_tree decl) | |
1867 { | |
1868 return (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE | |
1869 || is_invisiref_parm (decl)); | |
1870 } | |
1871 | |
1872 /* Return true if DECL is const qualified var having no mutable member. */ | |
1873 bool | |
1874 cxx_omp_const_qual_no_mutable (tree decl) | |
1875 { | |
1876 tree type = TREE_TYPE (decl); | |
1877 if (TREE_CODE (type) == REFERENCE_TYPE) | |
1878 { | |
1879 if (!is_invisiref_parm (decl)) | |
1880 return false; | |
1881 type = TREE_TYPE (type); | |
1882 | |
1883 if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl)) | |
1884 { | |
1885 /* NVR doesn't preserve const qualification of the | |
1886 variable's type. */ | |
1887 tree outer = outer_curly_brace_block (current_function_decl); | |
1888 tree var; | |
1889 | |
1890 if (outer) | |
1891 for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var)) | |
1892 if (VAR_P (var) | |
1893 && DECL_NAME (decl) == DECL_NAME (var) | |
1894 && (TYPE_MAIN_VARIANT (type) | |
1895 == TYPE_MAIN_VARIANT (TREE_TYPE (var)))) | |
1896 { | |
1897 if (TYPE_READONLY (TREE_TYPE (var))) | |
1898 type = TREE_TYPE (var); | |
1899 break; | |
1900 } | |
1901 } | |
1902 } | |
1903 | |
1904 if (type == error_mark_node) | |
1905 return false; | |
1906 | |
1907 /* Variables with const-qualified type having no mutable member | |
1908 are predetermined shared. */ | |
1909 if (TYPE_READONLY (type) && !cp_has_mutable_p (type)) | |
1910 return true; | |
1911 | |
1912 return false; | |
1913 } | |
1914 | |
1915 /* True if OpenMP sharing attribute of DECL is predetermined. */ | |
1916 | |
1917 enum omp_clause_default_kind | |
1918 cxx_omp_predetermined_sharing (tree decl) | |
1919 { | |
1920 /* Static data members are predetermined shared. */ | |
1921 if (TREE_STATIC (decl)) | |
1922 { | |
1923 tree ctx = CP_DECL_CONTEXT (decl); | |
1924 if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx)) | |
1925 return OMP_CLAUSE_DEFAULT_SHARED; | |
1926 } | |
1927 | |
1928 /* Const qualified vars having no mutable member are predetermined | |
1929 shared. */ | |
1930 if (cxx_omp_const_qual_no_mutable (decl)) | |
1931 return OMP_CLAUSE_DEFAULT_SHARED; | |
1932 | |
1933 return OMP_CLAUSE_DEFAULT_UNSPECIFIED; | |
1934 } | |
1935 | |
1936 /* Finalize an implicitly determined clause. */ | |
1937 | |
1938 void | |
1939 cxx_omp_finish_clause (tree c, gimple_seq *) | |
1940 { | |
1941 tree decl, inner_type; | |
1942 bool make_shared = false; | |
1943 | |
1944 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE) | |
1945 return; | |
1946 | |
1947 decl = OMP_CLAUSE_DECL (c); | |
1948 decl = require_complete_type (decl); | |
1949 inner_type = TREE_TYPE (decl); | |
1950 if (decl == error_mark_node) | |
1951 make_shared = true; | |
1952 else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE) | |
1953 inner_type = TREE_TYPE (inner_type); | |
1954 | |
1955 /* We're interested in the base element, not arrays. */ | |
1956 while (TREE_CODE (inner_type) == ARRAY_TYPE) | |
1957 inner_type = TREE_TYPE (inner_type); | |
1958 | |
1959 /* Check for special function availability by building a call to one. | |
1960 Save the results, because later we won't be in the right context | |
1961 for making these queries. */ | |
1962 if (!make_shared | |
1963 && CLASS_TYPE_P (inner_type) | |
1964 && cxx_omp_create_clause_info (c, inner_type, false, true, false, true)) | |
1965 make_shared = true; | |
1966 | |
1967 if (make_shared) | |
1968 { | |
1969 OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED; | |
1970 OMP_CLAUSE_SHARED_FIRSTPRIVATE (c) = 0; | |
1971 OMP_CLAUSE_SHARED_READONLY (c) = 0; | |
1972 } | |
1973 } | |
1974 | |
1975 /* Return true if DECL's DECL_VALUE_EXPR (if any) should be | |
1976 disregarded in OpenMP construct, because it is going to be | |
1977 remapped during OpenMP lowering. SHARED is true if DECL | |
1978 is going to be shared, false if it is going to be privatized. */ | |
1979 | |
1980 bool | |
1981 cxx_omp_disregard_value_expr (tree decl, bool shared) | |
1982 { | |
1983 return !shared | |
1984 && VAR_P (decl) | |
1985 && DECL_HAS_VALUE_EXPR_P (decl) | |
1986 && DECL_ARTIFICIAL (decl) | |
1987 && DECL_LANG_SPECIFIC (decl) | |
1988 && DECL_OMP_PRIVATIZED_MEMBER (decl); | |
1989 } | |
1990 | |
1991 /* Fold expression X which is used as an rvalue if RVAL is true. */ | |
1992 | |
1993 static tree | |
1994 cp_fold_maybe_rvalue (tree x, bool rval) | |
1995 { | |
1996 while (true) | |
1997 { | |
1998 x = cp_fold (x); | |
1999 if (rval && DECL_P (x) | |
2000 && TREE_CODE (TREE_TYPE (x)) != REFERENCE_TYPE) | |
2001 { | |
2002 tree v = decl_constant_value (x); | |
2003 if (v != x && v != error_mark_node) | |
2004 { | |
2005 x = v; | |
2006 continue; | |
2007 } | |
2008 } | |
2009 break; | |
2010 } | |
2011 return x; | |
2012 } | |
2013 | |
2014 /* Fold expression X which is used as an rvalue. */ | |
2015 | |
2016 static tree | |
2017 cp_fold_rvalue (tree x) | |
2018 { | |
2019 return cp_fold_maybe_rvalue (x, true); | |
2020 } | |
2021 | |
2022 /* Perform folding on expression X. */ | |
2023 | |
2024 tree | |
2025 cp_fully_fold (tree x) | |
2026 { | |
2027 if (processing_template_decl) | |
2028 return x; | |
2029 /* FIXME cp_fold ought to be a superset of maybe_constant_value so we don't | |
2030 have to call both. */ | |
2031 if (cxx_dialect >= cxx11) | |
2032 x = maybe_constant_value (x); | |
2033 return cp_fold_rvalue (x); | |
2034 } | |
2035 | |
2036 /* c-common interface to cp_fold. If IN_INIT, this is in a static initializer | |
2037 and certain changes are made to the folding done. Or should be (FIXME). We | |
2038 never touch maybe_const, as it is only used for the C front-end | |
2039 C_MAYBE_CONST_EXPR. */ | |
2040 | |
2041 tree | |
2042 c_fully_fold (tree x, bool /*in_init*/, bool */*maybe_const*/) | |
2043 { | |
2044 /* c_fully_fold is only used on rvalues, and we need to fold CONST_DECL to | |
2045 INTEGER_CST. */ | |
2046 return cp_fold_rvalue (x); | |
2047 } | |
2048 | |
2049 static GTY((deletable)) hash_map<tree, tree> *fold_cache; | |
2050 | |
2051 /* Dispose of the whole FOLD_CACHE. */ | |
2052 | |
2053 void | |
2054 clear_fold_cache (void) | |
2055 { | |
2056 if (fold_cache != NULL) | |
2057 fold_cache->empty (); | |
2058 } | |
2059 | |
2060 /* This function tries to fold an expression X. | |
2061 To avoid combinatorial explosion, folding results are kept in fold_cache. | |
2062 If we are processing a template or X is invalid, we don't fold at all. | |
2063 For performance reasons we don't cache expressions representing a | |
2064 declaration or constant. | |
2065 Function returns X or its folded variant. */ | |
2066 | |
2067 static tree | |
2068 cp_fold (tree x) | |
2069 { | |
2070 tree op0, op1, op2, op3; | |
2071 tree org_x = x, r = NULL_TREE; | |
2072 enum tree_code code; | |
2073 location_t loc; | |
2074 bool rval_ops = true; | |
2075 | |
2076 if (!x || x == error_mark_node) | |
2077 return x; | |
2078 | |
2079 if (processing_template_decl | |
2080 || (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node))) | |
2081 return x; | |
2082 | |
2083 /* Don't bother to cache DECLs or constants. */ | |
2084 if (DECL_P (x) || CONSTANT_CLASS_P (x)) | |
2085 return x; | |
2086 | |
2087 if (fold_cache == NULL) | |
2088 fold_cache = hash_map<tree, tree>::create_ggc (101); | |
2089 | |
2090 if (tree *cached = fold_cache->get (x)) | |
2091 return *cached; | |
2092 | |
2093 code = TREE_CODE (x); | |
2094 switch (code) | |
2095 { | |
2096 case CLEANUP_POINT_EXPR: | |
2097 /* Strip CLEANUP_POINT_EXPR if the expression doesn't have side | |
2098 effects. */ | |
2099 r = cp_fold_rvalue (TREE_OPERAND (x, 0)); | |
2100 if (!TREE_SIDE_EFFECTS (r)) | |
2101 x = r; | |
2102 break; | |
2103 | |
2104 case SIZEOF_EXPR: | |
2105 x = fold_sizeof_expr (x); | |
2106 break; | |
2107 | |
2108 case VIEW_CONVERT_EXPR: | |
2109 rval_ops = false; | |
2110 /* FALLTHRU */ | |
2111 case CONVERT_EXPR: | |
2112 case NOP_EXPR: | |
2113 case NON_LVALUE_EXPR: | |
2114 | |
2115 if (VOID_TYPE_P (TREE_TYPE (x))) | |
2116 return x; | |
2117 | |
2118 loc = EXPR_LOCATION (x); | |
2119 op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops); | |
2120 | |
2121 if (code == CONVERT_EXPR | |
2122 && SCALAR_TYPE_P (TREE_TYPE (x)) | |
2123 && op0 != void_node) | |
2124 /* During parsing we used convert_to_*_nofold; re-convert now using the | |
2125 folding variants, since fold() doesn't do those transformations. */ | |
2126 x = fold (convert (TREE_TYPE (x), op0)); | |
2127 else if (op0 != TREE_OPERAND (x, 0)) | |
2128 { | |
2129 if (op0 == error_mark_node) | |
2130 x = error_mark_node; | |
2131 else | |
2132 x = fold_build1_loc (loc, code, TREE_TYPE (x), op0); | |
2133 } | |
2134 else | |
2135 x = fold (x); | |
2136 | |
2137 /* Conversion of an out-of-range value has implementation-defined | |
2138 behavior; the language considers it different from arithmetic | |
2139 overflow, which is undefined. */ | |
2140 if (TREE_CODE (op0) == INTEGER_CST | |
2141 && TREE_OVERFLOW_P (x) && !TREE_OVERFLOW_P (op0)) | |
2142 TREE_OVERFLOW (x) = false; | |
2143 | |
2144 break; | |
2145 | |
2146 case INDIRECT_REF: | |
2147 /* We don't need the decltype(auto) obfuscation anymore. */ | |
2148 if (REF_PARENTHESIZED_P (x)) | |
2149 { | |
2150 tree p = maybe_undo_parenthesized_ref (x); | |
2151 return cp_fold (p); | |
2152 } | |
2153 goto unary; | |
2154 | |
2155 case ADDR_EXPR: | |
2156 case REALPART_EXPR: | |
2157 case IMAGPART_EXPR: | |
2158 rval_ops = false; | |
2159 /* FALLTHRU */ | |
2160 case CONJ_EXPR: | |
2161 case FIX_TRUNC_EXPR: | |
2162 case FLOAT_EXPR: | |
2163 case NEGATE_EXPR: | |
2164 case ABS_EXPR: | |
2165 case BIT_NOT_EXPR: | |
2166 case TRUTH_NOT_EXPR: | |
2167 case FIXED_CONVERT_EXPR: | |
2168 unary: | |
2169 | |
2170 loc = EXPR_LOCATION (x); | |
2171 op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops); | |
2172 | |
2173 if (op0 != TREE_OPERAND (x, 0)) | |
2174 { | |
2175 if (op0 == error_mark_node) | |
2176 x = error_mark_node; | |
2177 else | |
2178 { | |
2179 x = fold_build1_loc (loc, code, TREE_TYPE (x), op0); | |
2180 if (code == INDIRECT_REF | |
2181 && (INDIRECT_REF_P (x) || TREE_CODE (x) == MEM_REF)) | |
2182 { | |
2183 TREE_READONLY (x) = TREE_READONLY (org_x); | |
2184 TREE_SIDE_EFFECTS (x) = TREE_SIDE_EFFECTS (org_x); | |
2185 TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x); | |
2186 } | |
2187 } | |
2188 } | |
2189 else | |
2190 x = fold (x); | |
2191 | |
2192 gcc_assert (TREE_CODE (x) != COND_EXPR | |
2193 || !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0)))); | |
2194 break; | |
2195 | |
2196 case UNARY_PLUS_EXPR: | |
2197 op0 = cp_fold_rvalue (TREE_OPERAND (x, 0)); | |
2198 if (op0 == error_mark_node) | |
2199 x = error_mark_node; | |
2200 else | |
2201 x = fold_convert (TREE_TYPE (x), op0); | |
2202 break; | |
2203 | |
2204 case POSTDECREMENT_EXPR: | |
2205 case POSTINCREMENT_EXPR: | |
2206 case INIT_EXPR: | |
2207 case PREDECREMENT_EXPR: | |
2208 case PREINCREMENT_EXPR: | |
2209 case COMPOUND_EXPR: | |
2210 case MODIFY_EXPR: | |
2211 rval_ops = false; | |
2212 /* FALLTHRU */ | |
2213 case POINTER_PLUS_EXPR: | |
2214 case PLUS_EXPR: | |
2215 case MINUS_EXPR: | |
2216 case MULT_EXPR: | |
2217 case TRUNC_DIV_EXPR: | |
2218 case CEIL_DIV_EXPR: | |
2219 case FLOOR_DIV_EXPR: | |
2220 case ROUND_DIV_EXPR: | |
2221 case TRUNC_MOD_EXPR: | |
2222 case CEIL_MOD_EXPR: | |
2223 case ROUND_MOD_EXPR: | |
2224 case RDIV_EXPR: | |
2225 case EXACT_DIV_EXPR: | |
2226 case MIN_EXPR: | |
2227 case MAX_EXPR: | |
2228 case LSHIFT_EXPR: | |
2229 case RSHIFT_EXPR: | |
2230 case LROTATE_EXPR: | |
2231 case RROTATE_EXPR: | |
2232 case BIT_AND_EXPR: | |
2233 case BIT_IOR_EXPR: | |
2234 case BIT_XOR_EXPR: | |
2235 case TRUTH_AND_EXPR: | |
2236 case TRUTH_ANDIF_EXPR: | |
2237 case TRUTH_OR_EXPR: | |
2238 case TRUTH_ORIF_EXPR: | |
2239 case TRUTH_XOR_EXPR: | |
2240 case LT_EXPR: case LE_EXPR: | |
2241 case GT_EXPR: case GE_EXPR: | |
2242 case EQ_EXPR: case NE_EXPR: | |
2243 case UNORDERED_EXPR: case ORDERED_EXPR: | |
2244 case UNLT_EXPR: case UNLE_EXPR: | |
2245 case UNGT_EXPR: case UNGE_EXPR: | |
2246 case UNEQ_EXPR: case LTGT_EXPR: | |
2247 case RANGE_EXPR: case COMPLEX_EXPR: | |
2248 | |
2249 loc = EXPR_LOCATION (x); | |
2250 op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval_ops); | |
2251 op1 = cp_fold_rvalue (TREE_OPERAND (x, 1)); | |
2252 | |
2253 if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1)) | |
2254 { | |
2255 if (op0 == error_mark_node || op1 == error_mark_node) | |
2256 x = error_mark_node; | |
2257 else | |
2258 x = fold_build2_loc (loc, code, TREE_TYPE (x), op0, op1); | |
2259 } | |
2260 else | |
2261 x = fold (x); | |
2262 | |
2263 if (TREE_NO_WARNING (org_x) | |
2264 && warn_nonnull_compare | |
2265 && COMPARISON_CLASS_P (org_x)) | |
2266 { | |
2267 if (x == error_mark_node || TREE_CODE (x) == INTEGER_CST) | |
2268 ; | |
2269 else if (COMPARISON_CLASS_P (x)) | |
2270 TREE_NO_WARNING (x) = 1; | |
2271 /* Otherwise give up on optimizing these, let GIMPLE folders | |
2272 optimize those later on. */ | |
2273 else if (op0 != TREE_OPERAND (org_x, 0) | |
2274 || op1 != TREE_OPERAND (org_x, 1)) | |
2275 { | |
2276 x = build2_loc (loc, code, TREE_TYPE (org_x), op0, op1); | |
2277 TREE_NO_WARNING (x) = 1; | |
2278 } | |
2279 else | |
2280 x = org_x; | |
2281 } | |
2282 break; | |
2283 | |
2284 case VEC_COND_EXPR: | |
2285 case COND_EXPR: | |
2286 | |
2287 /* Don't bother folding a void condition, since it can't produce a | |
2288 constant value. Also, some statement-level uses of COND_EXPR leave | |
2289 one of the branches NULL, so folding would crash. */ | |
2290 if (VOID_TYPE_P (TREE_TYPE (x))) | |
2291 return x; | |
2292 | |
2293 loc = EXPR_LOCATION (x); | |
2294 op0 = cp_fold_rvalue (TREE_OPERAND (x, 0)); | |
2295 op1 = cp_fold (TREE_OPERAND (x, 1)); | |
2296 op2 = cp_fold (TREE_OPERAND (x, 2)); | |
2297 | |
2298 if (TREE_CODE (TREE_TYPE (x)) == BOOLEAN_TYPE) | |
2299 { | |
2300 warning_sentinel s (warn_int_in_bool_context); | |
2301 if (!VOID_TYPE_P (TREE_TYPE (op1))) | |
2302 op1 = cp_truthvalue_conversion (op1); | |
2303 if (!VOID_TYPE_P (TREE_TYPE (op2))) | |
2304 op2 = cp_truthvalue_conversion (op2); | |
2305 } | |
2306 | |
2307 if (op0 != TREE_OPERAND (x, 0) | |
2308 || op1 != TREE_OPERAND (x, 1) | |
2309 || op2 != TREE_OPERAND (x, 2)) | |
2310 { | |
2311 if (op0 == error_mark_node | |
2312 || op1 == error_mark_node | |
2313 || op2 == error_mark_node) | |
2314 x = error_mark_node; | |
2315 else | |
2316 x = fold_build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2); | |
2317 } | |
2318 else | |
2319 x = fold (x); | |
2320 | |
2321 /* A COND_EXPR might have incompatible types in branches if one or both | |
2322 arms are bitfields. If folding exposed such a branch, fix it up. */ | |
2323 if (TREE_CODE (x) != code | |
2324 && !useless_type_conversion_p (TREE_TYPE (org_x), TREE_TYPE (x))) | |
2325 x = fold_convert (TREE_TYPE (org_x), x); | |
2326 | |
2327 break; | |
2328 | |
2329 case CALL_EXPR: | |
2330 { | |
2331 int i, m, sv = optimize, nw = sv, changed = 0; | |
2332 tree callee = get_callee_fndecl (x); | |
2333 | |
2334 /* Some built-in function calls will be evaluated at compile-time in | |
2335 fold (). Set optimize to 1 when folding __builtin_constant_p inside | |
2336 a constexpr function so that fold_builtin_1 doesn't fold it to 0. */ | |
2337 if (callee && DECL_BUILT_IN (callee) && !optimize | |
2338 && DECL_IS_BUILTIN_CONSTANT_P (callee) | |
2339 && current_function_decl | |
2340 && DECL_DECLARED_CONSTEXPR_P (current_function_decl)) | |
2341 nw = 1; | |
2342 | |
2343 x = copy_node (x); | |
2344 | |
2345 m = call_expr_nargs (x); | |
2346 for (i = 0; i < m; i++) | |
2347 { | |
2348 r = cp_fold (CALL_EXPR_ARG (x, i)); | |
2349 if (r != CALL_EXPR_ARG (x, i)) | |
2350 { | |
2351 if (r == error_mark_node) | |
2352 { | |
2353 x = error_mark_node; | |
2354 break; | |
2355 } | |
2356 changed = 1; | |
2357 } | |
2358 CALL_EXPR_ARG (x, i) = r; | |
2359 } | |
2360 if (x == error_mark_node) | |
2361 break; | |
2362 | |
2363 optimize = nw; | |
2364 r = fold (x); | |
2365 optimize = sv; | |
2366 | |
2367 if (TREE_CODE (r) != CALL_EXPR) | |
2368 { | |
2369 x = cp_fold (r); | |
2370 break; | |
2371 } | |
2372 | |
2373 optimize = nw; | |
2374 | |
2375 /* Invoke maybe_constant_value for functions declared | |
2376 constexpr and not called with AGGR_INIT_EXPRs. | |
2377 TODO: | |
2378 Do constexpr expansion of expressions where the call itself is not | |
2379 constant, but the call followed by an INDIRECT_REF is. */ | |
2380 if (callee && DECL_DECLARED_CONSTEXPR_P (callee) | |
2381 && !flag_no_inline) | |
2382 r = maybe_constant_value (x); | |
2383 optimize = sv; | |
2384 | |
2385 if (TREE_CODE (r) != CALL_EXPR) | |
2386 { | |
2387 if (DECL_CONSTRUCTOR_P (callee)) | |
2388 { | |
2389 loc = EXPR_LOCATION (x); | |
2390 tree s = build_fold_indirect_ref_loc (loc, | |
2391 CALL_EXPR_ARG (x, 0)); | |
2392 r = build2_loc (loc, INIT_EXPR, TREE_TYPE (s), s, r); | |
2393 } | |
2394 x = r; | |
2395 break; | |
2396 } | |
2397 | |
2398 if (!changed) | |
2399 x = org_x; | |
2400 break; | |
2401 } | |
2402 | |
2403 case CONSTRUCTOR: | |
2404 { | |
2405 unsigned i; | |
2406 constructor_elt *p; | |
2407 vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (x); | |
2408 vec<constructor_elt, va_gc> *nelts = NULL; | |
2409 FOR_EACH_VEC_SAFE_ELT (elts, i, p) | |
2410 { | |
2411 tree op = cp_fold (p->value); | |
2412 if (op != p->value) | |
2413 { | |
2414 if (op == error_mark_node) | |
2415 { | |
2416 x = error_mark_node; | |
2417 vec_free (nelts); | |
2418 break; | |
2419 } | |
2420 if (nelts == NULL) | |
2421 nelts = elts->copy (); | |
2422 (*nelts)[i].value = op; | |
2423 } | |
2424 } | |
2425 if (nelts) | |
2426 x = build_constructor (TREE_TYPE (x), nelts); | |
2427 break; | |
2428 } | |
2429 case TREE_VEC: | |
2430 { | |
2431 bool changed = false; | |
2432 vec<tree, va_gc> *vec = make_tree_vector (); | |
2433 int i, n = TREE_VEC_LENGTH (x); | |
2434 vec_safe_reserve (vec, n); | |
2435 | |
2436 for (i = 0; i < n; i++) | |
2437 { | |
2438 tree op = cp_fold (TREE_VEC_ELT (x, i)); | |
2439 vec->quick_push (op); | |
2440 if (op != TREE_VEC_ELT (x, i)) | |
2441 changed = true; | |
2442 } | |
2443 | |
2444 if (changed) | |
2445 { | |
2446 r = copy_node (x); | |
2447 for (i = 0; i < n; i++) | |
2448 TREE_VEC_ELT (r, i) = (*vec)[i]; | |
2449 x = r; | |
2450 } | |
2451 | |
2452 release_tree_vector (vec); | |
2453 } | |
2454 | |
2455 break; | |
2456 | |
2457 case ARRAY_REF: | |
2458 case ARRAY_RANGE_REF: | |
2459 | |
2460 loc = EXPR_LOCATION (x); | |
2461 op0 = cp_fold (TREE_OPERAND (x, 0)); | |
2462 op1 = cp_fold (TREE_OPERAND (x, 1)); | |
2463 op2 = cp_fold (TREE_OPERAND (x, 2)); | |
2464 op3 = cp_fold (TREE_OPERAND (x, 3)); | |
2465 | |
2466 if (op0 != TREE_OPERAND (x, 0) | |
2467 || op1 != TREE_OPERAND (x, 1) | |
2468 || op2 != TREE_OPERAND (x, 2) | |
2469 || op3 != TREE_OPERAND (x, 3)) | |
2470 { | |
2471 if (op0 == error_mark_node | |
2472 || op1 == error_mark_node | |
2473 || op2 == error_mark_node | |
2474 || op3 == error_mark_node) | |
2475 x = error_mark_node; | |
2476 else | |
2477 { | |
2478 x = build4_loc (loc, code, TREE_TYPE (x), op0, op1, op2, op3); | |
2479 TREE_READONLY (x) = TREE_READONLY (org_x); | |
2480 TREE_SIDE_EFFECTS (x) = TREE_SIDE_EFFECTS (org_x); | |
2481 TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x); | |
2482 } | |
2483 } | |
2484 | |
2485 x = fold (x); | |
2486 break; | |
2487 | |
2488 case SAVE_EXPR: | |
2489 /* A SAVE_EXPR might contain e.g. (0 * i) + (0 * j), which, after | |
2490 folding, evaluates to an invariant. In that case no need to wrap | |
2491 this folded tree with a SAVE_EXPR. */ | |
2492 r = cp_fold (TREE_OPERAND (x, 0)); | |
2493 if (tree_invariant_p (r)) | |
2494 x = r; | |
2495 break; | |
2496 | |
2497 default: | |
2498 return org_x; | |
2499 } | |
2500 | |
2501 fold_cache->put (org_x, x); | |
2502 /* Prevent that we try to fold an already folded result again. */ | |
2503 if (x != org_x) | |
2504 fold_cache->put (x, x); | |
2505 | |
2506 return x; | |
2507 } | |
2508 | |
2509 #include "gt-cp-cp-gimplify.h" |