1/* C++-specific tree lowering bits; see also c-gimplify.cc and gimple.cc.
2
3 Copyright (C) 2002-2024 Free Software Foundation, Inc.
4 Contributed by Jason Merrill <jason@redhat.com>
5
6This file is part of GCC.
7
8GCC is free software; you can redistribute it and/or modify it under
9the terms of the GNU General Public License as published by the Free
10Software Foundation; either version 3, or (at your option) any later
11version.
12
13GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14WARRANTY; without even the implied warranty of MERCHANTABILITY or
15FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16for more details.
17
18You should have received a copy of the GNU General Public License
19along 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 "stringpool.h"
35#include "attribs.h"
36#include "asan.h"
37#include "gcc-rich-location.h"
38#include "memmodel.h"
39#include "tm_p.h"
40#include "output.h"
41#include "file-prefix-map.h"
42#include "cgraph.h"
43#include "omp-general.h"
44#include "opts.h"
45
46/* Keep track of forward references to immediate-escalating functions in
47 case they become consteval. This vector contains ADDR_EXPRs and
48 PTRMEM_CSTs; it also stores FUNCTION_DECLs that had an escalating
49 function call in them, to check that they can be evaluated to a constant,
50 and immediate-escalating functions that may become consteval. */
51static GTY(()) hash_set<tree> *deferred_escalating_exprs;
52
53static void
54remember_escalating_expr (tree t)
55{
56 if (!deferred_escalating_exprs)
57 deferred_escalating_exprs = hash_set<tree>::create_ggc (n: 37);
58 deferred_escalating_exprs->add (k: t);
59}
60
61/* Flags for cp_fold and cp_fold_r. */
62
63enum fold_flags {
64 ff_none = 0,
65 /* Whether we're being called from cp_fold_function. */
66 ff_genericize = 1 << 0,
67 /* Whether we're folding a point where we know we're
68 definitely not in a manifestly constant-evaluated
69 context. */
70 ff_mce_false = 1 << 1,
71};
72
73using fold_flags_t = int;
74
75struct cp_fold_data
76{
77 hash_set<tree> pset;
78 fold_flags_t flags;
79 cp_fold_data (fold_flags_t flags): flags (flags) {}
80};
81
82/* Forward declarations. */
83
84static tree cp_genericize_r (tree *, int *, void *);
85static tree cp_fold_r (tree *, int *, void *);
86static void cp_genericize_tree (tree*, bool);
87static tree cp_fold (tree, fold_flags_t);
88static tree cp_fold_immediate_r (tree *, int *, void *);
89
90/* Genericize a TRY_BLOCK. */
91
92static void
93genericize_try_block (tree *stmt_p)
94{
95 tree body = TRY_STMTS (*stmt_p);
96 tree cleanup = TRY_HANDLERS (*stmt_p);
97
98 *stmt_p = build2 (TRY_CATCH_EXPR, void_type_node, body, cleanup);
99}
100
101/* Genericize a HANDLER by converting to a CATCH_EXPR. */
102
103static void
104genericize_catch_block (tree *stmt_p)
105{
106 tree type = HANDLER_TYPE (*stmt_p);
107 tree body = HANDLER_BODY (*stmt_p);
108
109 /* FIXME should the caught type go in TREE_TYPE? */
110 *stmt_p = build2 (CATCH_EXPR, void_type_node, type, body);
111}
112
113/* A terser interface for building a representation of an exception
114 specification. */
115
116static tree
117build_gimple_eh_filter_tree (tree body, tree allowed, tree failure)
118{
119 tree t;
120
121 /* FIXME should the allowed types go in TREE_TYPE? */
122 t = build2 (EH_FILTER_EXPR, void_type_node, allowed, NULL_TREE);
123 append_to_statement_list (failure, &EH_FILTER_FAILURE (t));
124
125 t = build2 (TRY_CATCH_EXPR, void_type_node, NULL_TREE, t);
126 append_to_statement_list (body, &TREE_OPERAND (t, 0));
127
128 return t;
129}
130
131/* Genericize an EH_SPEC_BLOCK by converting it to a
132 TRY_CATCH_EXPR/EH_FILTER_EXPR pair. */
133
134static void
135genericize_eh_spec_block (tree *stmt_p)
136{
137 tree body = EH_SPEC_STMTS (*stmt_p);
138 tree allowed = EH_SPEC_RAISES (*stmt_p);
139 tree failure = build_call_n (call_unexpected_fn, 1, build_exc_ptr ());
140
141 *stmt_p = build_gimple_eh_filter_tree (body, allowed, failure);
142 suppress_warning (*stmt_p);
143 suppress_warning (TREE_OPERAND (*stmt_p, 1));
144}
145
146/* Return the first non-compound statement in STMT. */
147
148tree
149first_stmt (tree stmt)
150{
151 switch (TREE_CODE (stmt))
152 {
153 case STATEMENT_LIST:
154 if (tree_statement_list_node *p = STATEMENT_LIST_HEAD (stmt))
155 return first_stmt (stmt: p->stmt);
156 return void_node;
157
158 case BIND_EXPR:
159 return first_stmt (BIND_EXPR_BODY (stmt));
160
161 default:
162 return stmt;
163 }
164}
165
166/* Genericize an IF_STMT by turning it into a COND_EXPR. */
167
168static void
169genericize_if_stmt (tree *stmt_p)
170{
171 tree stmt, cond, then_, else_;
172 location_t locus = EXPR_LOCATION (*stmt_p);
173
174 stmt = *stmt_p;
175 cond = IF_COND (stmt);
176 then_ = THEN_CLAUSE (stmt);
177 else_ = ELSE_CLAUSE (stmt);
178
179 if (then_ && else_)
180 {
181 tree ft = first_stmt (stmt: then_);
182 tree fe = first_stmt (stmt: else_);
183 br_predictor pr;
184 if (TREE_CODE (ft) == PREDICT_EXPR
185 && TREE_CODE (fe) == PREDICT_EXPR
186 && (pr = PREDICT_EXPR_PREDICTOR (ft)) == PREDICT_EXPR_PREDICTOR (fe)
187 && (pr == PRED_HOT_LABEL || pr == PRED_COLD_LABEL))
188 {
189 gcc_rich_location richloc (EXPR_LOC_OR_LOC (ft, locus));
190 richloc.add_range (EXPR_LOC_OR_LOC (fe, locus));
191 warning_at (&richloc, OPT_Wattributes,
192 "both branches of %<if%> statement marked as %qs",
193 pr == PRED_HOT_LABEL ? "likely" : "unlikely");
194 }
195 }
196
197 if (!then_)
198 then_ = build_empty_stmt (locus);
199 if (!else_)
200 else_ = build_empty_stmt (locus);
201
202 /* consteval if has been verified not to have the then_/else_ blocks
203 entered by gotos/case labels from elsewhere, and as then_ block
204 can contain unfolded immediate function calls, we have to discard
205 the then_ block regardless of whether else_ has side-effects or not. */
206 if (IF_STMT_CONSTEVAL_P (stmt))
207 {
208 if (block_may_fallthru (then_))
209 stmt = build3 (COND_EXPR, void_type_node, boolean_false_node,
210 void_node, else_);
211 else
212 stmt = else_;
213 }
214 else if (IF_STMT_CONSTEXPR_P (stmt))
215 stmt = integer_nonzerop (cond) ? then_ : else_;
216 /* ??? This optimization doesn't seem to belong here, but removing it
217 causes -Wreturn-type regressions (e.g. 107310). */
218 else if (integer_nonzerop (cond) && !TREE_SIDE_EFFECTS (else_))
219 stmt = then_;
220 else if (integer_zerop (cond) && !TREE_SIDE_EFFECTS (then_))
221 stmt = else_;
222 else
223 stmt = build3 (COND_EXPR, void_type_node, cond, then_, else_);
224 protected_set_expr_location_if_unset (stmt, locus);
225 *stmt_p = stmt;
226}
227
228/* Hook into the middle of gimplifying an OMP_FOR node. */
229
230static enum gimplify_status
231cp_gimplify_omp_for (tree *expr_p, gimple_seq *pre_p)
232{
233 tree for_stmt = *expr_p;
234 gimple_seq seq = NULL;
235
236 /* Protect ourselves from recursion. */
237 if (OMP_FOR_GIMPLIFYING_P (for_stmt))
238 return GS_UNHANDLED;
239 OMP_FOR_GIMPLIFYING_P (for_stmt) = 1;
240
241 gimplify_and_add (for_stmt, &seq);
242 gimple_seq_add_seq (pre_p, seq);
243
244 OMP_FOR_GIMPLIFYING_P (for_stmt) = 0;
245
246 return GS_ALL_DONE;
247}
248
249/* Gimplify an EXPR_STMT node. */
250
251static void
252gimplify_expr_stmt (tree *stmt_p)
253{
254 tree stmt = EXPR_STMT_EXPR (*stmt_p);
255
256 if (stmt == error_mark_node)
257 stmt = NULL;
258
259 /* Gimplification of a statement expression will nullify the
260 statement if all its side effects are moved to *PRE_P and *POST_P.
261
262 In this case we will not want to emit the gimplified statement.
263 However, we may still want to emit a warning, so we do that before
264 gimplification. */
265 if (stmt && warn_unused_value)
266 {
267 if (!TREE_SIDE_EFFECTS (stmt))
268 {
269 if (!IS_EMPTY_STMT (stmt)
270 && !VOID_TYPE_P (TREE_TYPE (stmt))
271 && !warning_suppressed_p (stmt, OPT_Wunused_value))
272 warning (OPT_Wunused_value, "statement with no effect");
273 }
274 else
275 warn_if_unused_value (stmt, input_location);
276 }
277
278 if (stmt == NULL_TREE)
279 stmt = alloc_stmt_list ();
280
281 *stmt_p = stmt;
282}
283
284/* Gimplify initialization from an AGGR_INIT_EXPR. */
285
286static void
287cp_gimplify_init_expr (tree *expr_p)
288{
289 tree from = TREE_OPERAND (*expr_p, 1);
290 tree to = TREE_OPERAND (*expr_p, 0);
291 tree t;
292
293 if (TREE_CODE (from) == TARGET_EXPR)
294 if (tree init = TARGET_EXPR_INITIAL (from))
295 {
296 /* Make sure that we expected to elide this temporary. But also allow
297 gimplify_modify_expr_rhs to elide temporaries of trivial type. */
298 gcc_checking_assert (TARGET_EXPR_ELIDING_P (from)
299 || !TREE_ADDRESSABLE (TREE_TYPE (from)));
300 if (target_expr_needs_replace (t: from))
301 {
302 /* If this was changed by cp_genericize_target_expr, we need to
303 walk into it to replace uses of the slot. */
304 replace_decl (&init, TARGET_EXPR_SLOT (from), to);
305 *expr_p = init;
306 return;
307 }
308 else
309 from = init;
310 }
311
312 /* Look through any COMPOUND_EXPRs, since build_compound_expr pushes them
313 inside the TARGET_EXPR. */
314 for (t = from; t; )
315 {
316 tree sub = TREE_CODE (t) == COMPOUND_EXPR ? TREE_OPERAND (t, 0) : t;
317
318 /* If we are initializing from an AGGR_INIT_EXPR, drop the INIT_EXPR and
319 replace the slot operand with our target.
320
321 Should we add a target parm to gimplify_expr instead? No, as in this
322 case we want to replace the INIT_EXPR. */
323 if (TREE_CODE (sub) == AGGR_INIT_EXPR
324 || TREE_CODE (sub) == VEC_INIT_EXPR)
325 {
326 if (TREE_CODE (sub) == AGGR_INIT_EXPR)
327 AGGR_INIT_EXPR_SLOT (sub) = to;
328 else
329 VEC_INIT_EXPR_SLOT (sub) = to;
330 *expr_p = from;
331
332 /* The initialization is now a side-effect, so the container can
333 become void. */
334 if (from != sub)
335 TREE_TYPE (from) = void_type_node;
336 }
337
338 /* Handle aggregate NSDMI. */
339 replace_placeholders (sub, to);
340
341 if (t == sub)
342 break;
343 else
344 t = TREE_OPERAND (t, 1);
345 }
346
347}
348
349/* Gimplify a MUST_NOT_THROW_EXPR. */
350
351static enum gimplify_status
352gimplify_must_not_throw_expr (tree *expr_p, gimple_seq *pre_p)
353{
354 tree stmt = *expr_p;
355 tree temp = voidify_wrapper_expr (stmt, NULL);
356 tree body = TREE_OPERAND (stmt, 0);
357 gimple_seq try_ = NULL;
358 gimple_seq catch_ = NULL;
359 gimple *mnt;
360
361 gimplify_and_add (body, &try_);
362 mnt = gimple_build_eh_must_not_throw (call_terminate_fn);
363 gimple_seq_add_stmt_without_update (&catch_, mnt);
364 mnt = gimple_build_try (try_, catch_, GIMPLE_TRY_CATCH);
365
366 gimple_seq_add_stmt_without_update (pre_p, mnt);
367 if (temp)
368 {
369 *expr_p = temp;
370 return GS_OK;
371 }
372
373 *expr_p = NULL;
374 return GS_ALL_DONE;
375}
376
377/* Return TRUE if an operand (OP) of a given TYPE being copied is
378 really just an empty class copy.
379
380 Check that the operand has a simple form so that TARGET_EXPRs and
381 non-empty CONSTRUCTORs get reduced properly, and we leave the
382 return slot optimization alone because it isn't a copy. */
383
384bool
385simple_empty_class_p (tree type, tree op, tree_code code)
386{
387 if (TREE_CODE (op) == COMPOUND_EXPR)
388 return simple_empty_class_p (type, TREE_OPERAND (op, 1), code);
389 if (SIMPLE_TARGET_EXPR_P (op)
390 && TYPE_HAS_TRIVIAL_DESTRUCTOR (type))
391 /* The TARGET_EXPR is itself a simple copy, look through it. */
392 return simple_empty_class_p (type, TARGET_EXPR_INITIAL (op), code);
393
394 if (TREE_CODE (op) == PARM_DECL
395 && TREE_ADDRESSABLE (TREE_TYPE (op)))
396 {
397 tree fn = DECL_CONTEXT (op);
398 if (DECL_THUNK_P (fn)
399 || lambda_static_thunk_p (fn))
400 /* In a thunk, we pass through invisible reference parms, so this isn't
401 actually a copy. */
402 return false;
403 }
404
405 return
406 (TREE_CODE (op) == EMPTY_CLASS_EXPR
407 || code == MODIFY_EXPR
408 || is_gimple_lvalue (op)
409 || INDIRECT_REF_P (op)
410 || (TREE_CODE (op) == CONSTRUCTOR
411 && CONSTRUCTOR_NELTS (op) == 0)
412 || (TREE_CODE (op) == CALL_EXPR
413 && !CALL_EXPR_RETURN_SLOT_OPT (op)))
414 && !TREE_CLOBBER_P (op)
415 && is_really_empty_class (type, /*ignore_vptr*/true);
416}
417
418/* Returns true if evaluating E as an lvalue has side-effects;
419 specifically, a volatile lvalue has TREE_SIDE_EFFECTS, but it doesn't really
420 have side-effects until there is a read or write through it. */
421
422static bool
423lvalue_has_side_effects (tree e)
424{
425 if (!TREE_SIDE_EFFECTS (e))
426 return false;
427 while (handled_component_p (t: e))
428 {
429 if (TREE_CODE (e) == ARRAY_REF
430 && TREE_SIDE_EFFECTS (TREE_OPERAND (e, 1)))
431 return true;
432 e = TREE_OPERAND (e, 0);
433 }
434 if (DECL_P (e))
435 /* Just naming a variable has no side-effects. */
436 return false;
437 else if (INDIRECT_REF_P (e))
438 /* Similarly, indirection has no side-effects. */
439 return TREE_SIDE_EFFECTS (TREE_OPERAND (e, 0));
440 else
441 /* For anything else, trust TREE_SIDE_EFFECTS. */
442 return TREE_SIDE_EFFECTS (e);
443}
444
445/* Return true if FN is an immediate-escalating function. */
446
447static bool
448immediate_escalating_function_p (tree fn)
449{
450 if (!fn || !flag_immediate_escalation)
451 return false;
452
453 gcc_checking_assert (TREE_CODE (fn) == FUNCTION_DECL);
454
455 if (DECL_IMMEDIATE_FUNCTION_P (fn))
456 return false;
457
458 /* An immediate-escalating function is
459 -- the call operator of a lambda that is not declared with the consteval
460 specifier */
461 if (LAMBDA_FUNCTION_P (fn))
462 return true;
463 /* -- a defaulted special member function that is not declared with the
464 consteval specifier */
465 special_function_kind sfk = special_memfn_p (fn);
466 if (sfk != sfk_none && DECL_DEFAULTED_FN (fn))
467 return true;
468 /* -- a function that results from the instantiation of a templated entity
469 defined with the constexpr specifier. */
470 return is_instantiation_of_constexpr (fn);
471}
472
473/* Return true if FN is an immediate-escalating function that has not been
474 checked for escalating expressions.. */
475
476static bool
477unchecked_immediate_escalating_function_p (tree fn)
478{
479 return (immediate_escalating_function_p (fn)
480 && !DECL_ESCALATION_CHECKED_P (fn));
481}
482
483/* Promote FN to an immediate function, including its clones. */
484
485static void
486promote_function_to_consteval (tree fn)
487{
488 SET_DECL_IMMEDIATE_FUNCTION_P (fn);
489 DECL_ESCALATION_CHECKED_P (fn) = true;
490 tree clone;
491 FOR_EACH_CLONE (clone, fn)
492 {
493 SET_DECL_IMMEDIATE_FUNCTION_P (clone);
494 DECL_ESCALATION_CHECKED_P (clone) = true;
495 }
496}
497
498/* A wrapper around cp_fold_immediate_r. Return a non-null tree if
499 we found a non-constant immediate function, or taking the address
500 of an immediate function. */
501
502tree
503cp_fold_immediate (tree *tp, mce_value manifestly_const_eval,
504 tree decl /*= current_function_decl*/)
505{
506 if (cxx_dialect <= cxx17)
507 return NULL_TREE;
508
509 temp_override<tree> cfd (current_function_decl, decl);
510
511 fold_flags_t flags = ff_none;
512 if (manifestly_const_eval == mce_false)
513 flags |= ff_mce_false;
514
515 cp_fold_data data (flags);
516 int save_errorcount = errorcount;
517 tree r = cp_walk_tree_without_duplicates (tp, cp_fold_immediate_r, &data);
518 if (errorcount > save_errorcount)
519 return integer_one_node;
520 return r;
521}
522
523/* Maybe say that FN (a function decl with DECL_IMMEDIATE_FUNCTION_P set)
524 was initially not an immediate function, but was promoted to one because
525 its body contained an immediate-escalating expression or conversion. */
526
527static void
528maybe_explain_promoted_consteval (location_t loc, tree fn)
529{
530 if (DECL_ESCALATION_CHECKED_P (fn))
531 {
532 /* See if we can figure out what made the function consteval. */
533 tree x = cp_fold_immediate (tp: &DECL_SAVED_TREE (fn), manifestly_const_eval: mce_unknown, NULL_TREE);
534 if (x)
535 inform (cp_expr_loc_or_loc (t: x, or_loc: loc),
536 "%qD was promoted to an immediate function because its "
537 "body contains an immediate-escalating expression %qE", fn, x);
538 else
539 inform (loc, "%qD was promoted to an immediate function", fn);
540 }
541}
542
543/* Gimplify *EXPR_P as rvalue into an expression that can't be modified
544 by expressions with side-effects in other operands. */
545
546static enum gimplify_status
547gimplify_to_rvalue (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
548 bool (*gimple_test_f) (tree))
549{
550 enum gimplify_status t
551 = gimplify_expr (expr_p, pre_p, post_p, gimple_test_f, fb_rvalue);
552 if (t == GS_ERROR)
553 return GS_ERROR;
554 else if (is_gimple_variable (t: *expr_p) && TREE_CODE (*expr_p) != SSA_NAME)
555 *expr_p = get_initialized_tmp_var (*expr_p, pre_p);
556 return t;
557}
558
559/* Like gimplify_arg, but if ORDERED is set (which should be set if
560 any of the arguments this argument is sequenced before has
561 TREE_SIDE_EFFECTS set, make sure expressions with is_gimple_reg_type type
562 are gimplified into SSA_NAME or a fresh temporary and for
563 non-is_gimple_reg_type we don't optimize away TARGET_EXPRs. */
564
565static enum gimplify_status
566cp_gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location,
567 bool ordered)
568{
569 enum gimplify_status t;
570 if (ordered
571 && !is_gimple_reg_type (TREE_TYPE (*arg_p))
572 && TREE_CODE (*arg_p) == TARGET_EXPR)
573 {
574 /* gimplify_arg would strip away the TARGET_EXPR, but
575 that can mean we don't copy the argument and some following
576 argument with side-effect could modify it. */
577 protected_set_expr_location (*arg_p, call_location);
578 return gimplify_expr (arg_p, pre_p, NULL, is_gimple_lvalue, fb_either);
579 }
580 else
581 {
582 t = gimplify_arg (arg_p, pre_p, call_location);
583 if (t == GS_ERROR)
584 return GS_ERROR;
585 else if (ordered
586 && is_gimple_reg_type (TREE_TYPE (*arg_p))
587 && is_gimple_variable (t: *arg_p)
588 && TREE_CODE (*arg_p) != SSA_NAME
589 /* No need to force references into register, references
590 can't be modified. */
591 && !TYPE_REF_P (TREE_TYPE (*arg_p))
592 /* And this can't be modified either. */
593 && *arg_p != current_class_ptr)
594 *arg_p = get_initialized_tmp_var (*arg_p, pre_p);
595 return t;
596 }
597
598}
599
600/* Do C++-specific gimplification. Args are as for gimplify_expr. */
601
602int
603cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
604{
605 int saved_stmts_are_full_exprs_p = 0;
606 location_t loc = cp_expr_loc_or_input_loc (t: *expr_p);
607 enum tree_code code = TREE_CODE (*expr_p);
608 enum gimplify_status ret;
609
610 if (STATEMENT_CODE_P (code))
611 {
612 saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
613 current_stmt_tree ()->stmts_are_full_exprs_p
614 = STMT_IS_FULL_EXPR_P (*expr_p);
615 }
616
617 switch (code)
618 {
619 case AGGR_INIT_EXPR:
620 simplify_aggr_init_expr (expr_p);
621 ret = GS_OK;
622 break;
623
624 case VEC_INIT_EXPR:
625 {
626 *expr_p = expand_vec_init_expr (NULL_TREE, *expr_p,
627 tf_warning_or_error);
628
629 cp_fold_data data (ff_genericize | ff_mce_false);
630 cp_walk_tree (expr_p, cp_fold_r, &data, NULL);
631 cp_genericize_tree (expr_p, false);
632 copy_if_shared (expr_p);
633 ret = GS_OK;
634 }
635 break;
636
637 case THROW_EXPR:
638 /* FIXME communicate throw type to back end, probably by moving
639 THROW_EXPR into ../tree.def. */
640 *expr_p = TREE_OPERAND (*expr_p, 0);
641 ret = GS_OK;
642 break;
643
644 case MUST_NOT_THROW_EXPR:
645 ret = gimplify_must_not_throw_expr (expr_p, pre_p);
646 break;
647
648 /* We used to do this for MODIFY_EXPR as well, but that's unsafe; the
649 LHS of an assignment might also be involved in the RHS, as in bug
650 25979. */
651 case INIT_EXPR:
652 cp_gimplify_init_expr (expr_p);
653 if (TREE_CODE (*expr_p) != INIT_EXPR)
654 return GS_OK;
655 /* Fall through. */
656 case MODIFY_EXPR:
657 modify_expr_case:
658 {
659 /* If the back end isn't clever enough to know that the lhs and rhs
660 types are the same, add an explicit conversion. */
661 tree op0 = TREE_OPERAND (*expr_p, 0);
662 tree op1 = TREE_OPERAND (*expr_p, 1);
663
664 if (!error_operand_p (t: op0)
665 && !error_operand_p (t: op1)
666 && (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0))
667 || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1)))
668 && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
669 TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
670 TREE_TYPE (op0), op1);
671
672 else if (simple_empty_class_p (TREE_TYPE (op0), op: op1, code))
673 {
674 while (TREE_CODE (op1) == TARGET_EXPR)
675 /* We're disconnecting the initializer from its target,
676 don't create a temporary. */
677 op1 = TARGET_EXPR_INITIAL (op1);
678
679 /* Remove any copies of empty classes. Also drop volatile
680 variables on the RHS to avoid infinite recursion from
681 gimplify_expr trying to load the value. */
682 if (TREE_SIDE_EFFECTS (op1))
683 {
684 if (TREE_THIS_VOLATILE (op1)
685 && (REFERENCE_CLASS_P (op1) || DECL_P (op1)))
686 op1 = build_fold_addr_expr (op1);
687
688 gimplify_and_add (op1, pre_p);
689 }
690 gimplify_expr (&TREE_OPERAND (*expr_p, 0), pre_p, post_p,
691 is_gimple_lvalue, fb_lvalue);
692 *expr_p = TREE_OPERAND (*expr_p, 0);
693 if (code == RETURN_EXPR && REFERENCE_CLASS_P (*expr_p))
694 /* Avoid 'return *<retval>;' */
695 *expr_p = TREE_OPERAND (*expr_p, 0);
696 }
697 /* P0145 says that the RHS is sequenced before the LHS.
698 gimplify_modify_expr gimplifies the RHS before the LHS, but that
699 isn't quite strong enough in two cases:
700
701 1) gimplify.cc wants to leave a CALL_EXPR on the RHS, which would
702 mean it's evaluated after the LHS.
703
704 2) the value calculation of the RHS is also sequenced before the
705 LHS, so for scalar assignment we need to preevaluate if the
706 RHS could be affected by LHS side-effects even if it has no
707 side-effects of its own. We don't need this for classes because
708 class assignment takes its RHS by reference. */
709 else if (flag_strong_eval_order > 1
710 && TREE_CODE (*expr_p) == MODIFY_EXPR
711 && lvalue_has_side_effects (e: op0)
712 && (TREE_CODE (op1) == CALL_EXPR
713 || (SCALAR_TYPE_P (TREE_TYPE (op1))
714 && !TREE_CONSTANT (op1))))
715 TREE_OPERAND (*expr_p, 1) = get_initialized_tmp_var (op1, pre_p);
716 }
717 ret = GS_OK;
718 break;
719
720 case EMPTY_CLASS_EXPR:
721 /* We create an empty CONSTRUCTOR with RECORD_TYPE. */
722 *expr_p = build_constructor (TREE_TYPE (*expr_p), NULL);
723 ret = GS_OK;
724 break;
725
726 case BASELINK:
727 *expr_p = BASELINK_FUNCTIONS (*expr_p);
728 ret = GS_OK;
729 break;
730
731 case TRY_BLOCK:
732 genericize_try_block (stmt_p: expr_p);
733 ret = GS_OK;
734 break;
735
736 case HANDLER:
737 genericize_catch_block (stmt_p: expr_p);
738 ret = GS_OK;
739 break;
740
741 case EH_SPEC_BLOCK:
742 genericize_eh_spec_block (stmt_p: expr_p);
743 ret = GS_OK;
744 break;
745
746 case USING_STMT:
747 gcc_unreachable ();
748
749 case FOR_STMT:
750 case WHILE_STMT:
751 case DO_STMT:
752 case SWITCH_STMT:
753 case CONTINUE_STMT:
754 case BREAK_STMT:
755 gcc_unreachable ();
756
757 case OMP_FOR:
758 case OMP_SIMD:
759 case OMP_DISTRIBUTE:
760 case OMP_LOOP:
761 case OMP_TASKLOOP:
762 ret = cp_gimplify_omp_for (expr_p, pre_p);
763 break;
764
765 case EXPR_STMT:
766 gimplify_expr_stmt (stmt_p: expr_p);
767 ret = GS_OK;
768 break;
769
770 case UNARY_PLUS_EXPR:
771 {
772 tree arg = TREE_OPERAND (*expr_p, 0);
773 tree type = TREE_TYPE (*expr_p);
774 *expr_p = (TREE_TYPE (arg) != type) ? fold_convert (type, arg)
775 : arg;
776 ret = GS_OK;
777 }
778 break;
779
780 case CALL_EXPR:
781 ret = GS_OK;
782 if (flag_strong_eval_order == 2
783 && CALL_EXPR_FN (*expr_p)
784 && !CALL_EXPR_OPERATOR_SYNTAX (*expr_p)
785 && cp_get_callee_fndecl_nofold (*expr_p) == NULL_TREE)
786 {
787 tree fnptrtype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
788 enum gimplify_status t
789 = gimplify_to_rvalue (expr_p: &CALL_EXPR_FN (*expr_p), pre_p, NULL,
790 gimple_test_f: is_gimple_call_addr);
791 if (t == GS_ERROR)
792 ret = GS_ERROR;
793 /* GIMPLE considers most pointer conversion useless, but for
794 calls we actually care about the exact function pointer type. */
795 else if (TREE_TYPE (CALL_EXPR_FN (*expr_p)) != fnptrtype)
796 CALL_EXPR_FN (*expr_p)
797 = build1 (NOP_EXPR, fnptrtype, CALL_EXPR_FN (*expr_p));
798 }
799 if (!CALL_EXPR_FN (*expr_p))
800 /* Internal function call. */;
801 else if (CALL_EXPR_REVERSE_ARGS (*expr_p))
802 {
803 /* This is a call to a (compound) assignment operator that used
804 the operator syntax; gimplify the RHS first. */
805 gcc_assert (call_expr_nargs (*expr_p) == 2);
806 gcc_assert (!CALL_EXPR_ORDERED_ARGS (*expr_p));
807 enum gimplify_status t
808 = cp_gimplify_arg (arg_p: &CALL_EXPR_ARG (*expr_p, 1), pre_p, call_location: loc,
809 TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, 0)));
810 if (t == GS_ERROR)
811 ret = GS_ERROR;
812 }
813 else if (CALL_EXPR_ORDERED_ARGS (*expr_p))
814 {
815 /* Leave the last argument for gimplify_call_expr, to avoid problems
816 with __builtin_va_arg_pack(). */
817 int nargs = call_expr_nargs (*expr_p) - 1;
818 int last_side_effects_arg = -1;
819 for (int i = nargs; i > 0; --i)
820 if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
821 {
822 last_side_effects_arg = i;
823 break;
824 }
825 for (int i = 0; i < nargs; ++i)
826 {
827 enum gimplify_status t
828 = cp_gimplify_arg (arg_p: &CALL_EXPR_ARG (*expr_p, i), pre_p, call_location: loc,
829 ordered: i < last_side_effects_arg);
830 if (t == GS_ERROR)
831 ret = GS_ERROR;
832 }
833 }
834 else if (flag_strong_eval_order
835 && !CALL_EXPR_OPERATOR_SYNTAX (*expr_p))
836 {
837 /* If flag_strong_eval_order, evaluate the object argument first. */
838 tree fntype = TREE_TYPE (CALL_EXPR_FN (*expr_p));
839 if (INDIRECT_TYPE_P (fntype))
840 fntype = TREE_TYPE (fntype);
841 if (TREE_CODE (fntype) == METHOD_TYPE)
842 {
843 int nargs = call_expr_nargs (*expr_p);
844 bool side_effects = false;
845 for (int i = 1; i < nargs; ++i)
846 if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
847 {
848 side_effects = true;
849 break;
850 }
851 enum gimplify_status t
852 = cp_gimplify_arg (arg_p: &CALL_EXPR_ARG (*expr_p, 0), pre_p, call_location: loc,
853 ordered: side_effects);
854 if (t == GS_ERROR)
855 ret = GS_ERROR;
856 }
857 }
858 if (ret != GS_ERROR)
859 {
860 tree decl = cp_get_callee_fndecl_nofold (*expr_p);
861 if (!decl)
862 break;
863 if (fndecl_built_in_p (node: decl, klass: BUILT_IN_FRONTEND))
864 switch (DECL_FE_FUNCTION_CODE (decl))
865 {
866 case CP_BUILT_IN_IS_CONSTANT_EVALUATED:
867 *expr_p = boolean_false_node;
868 break;
869 case CP_BUILT_IN_SOURCE_LOCATION:
870 *expr_p
871 = fold_builtin_source_location (*expr_p);
872 break;
873 case CP_BUILT_IN_IS_CORRESPONDING_MEMBER:
874 *expr_p
875 = fold_builtin_is_corresponding_member
876 (EXPR_LOCATION (*expr_p), call_expr_nargs (*expr_p),
877 &CALL_EXPR_ARG (*expr_p, 0));
878 break;
879 case CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS:
880 *expr_p
881 = fold_builtin_is_pointer_inverconvertible_with_class
882 (EXPR_LOCATION (*expr_p), call_expr_nargs (*expr_p),
883 &CALL_EXPR_ARG (*expr_p, 0));
884 break;
885 default:
886 break;
887 }
888 else if (fndecl_built_in_p (node: decl, name1: BUILT_IN_CLZG, names: BUILT_IN_CTZG))
889 ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p,
890 post_p);
891 else
892 /* All consteval functions should have been processed by now. */
893 gcc_checking_assert (!immediate_invocation_p (decl));
894 }
895 break;
896
897 case TARGET_EXPR:
898 /* A TARGET_EXPR that expresses direct-initialization should have been
899 elided by cp_gimplify_init_expr. */
900 gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p));
901 /* Likewise, but allow extra temps of trivial type so that
902 gimplify_init_ctor_preeval can materialize subobjects of a CONSTRUCTOR
903 on the rhs of an assignment, as in constexpr-aggr1.C. */
904 gcc_checking_assert (!TARGET_EXPR_ELIDING_P (*expr_p)
905 || !TREE_ADDRESSABLE (TREE_TYPE (*expr_p)));
906 ret = GS_UNHANDLED;
907 break;
908
909 case PTRMEM_CST:
910 *expr_p = cplus_expand_constant (*expr_p);
911 if (TREE_CODE (*expr_p) == PTRMEM_CST)
912 ret = GS_ERROR;
913 else
914 ret = GS_OK;
915 break;
916
917 case RETURN_EXPR:
918 if (TREE_OPERAND (*expr_p, 0)
919 && (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == INIT_EXPR
920 || TREE_CODE (TREE_OPERAND (*expr_p, 0)) == MODIFY_EXPR))
921 {
922 expr_p = &TREE_OPERAND (*expr_p, 0);
923 /* Avoid going through the INIT_EXPR case, which can
924 degrade INIT_EXPRs into AGGR_INIT_EXPRs. */
925 goto modify_expr_case;
926 }
927 /* Fall through. */
928
929 default:
930 ret = (enum gimplify_status) c_gimplify_expr (expr_p, pre_p, post_p);
931 break;
932 }
933
934 /* Restore saved state. */
935 if (STATEMENT_CODE_P (code))
936 current_stmt_tree ()->stmts_are_full_exprs_p
937 = saved_stmts_are_full_exprs_p;
938
939 return ret;
940}
941
942static inline bool
943is_invisiref_parm (const_tree t)
944{
945 return ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL)
946 && DECL_BY_REFERENCE (t));
947}
948
949/* A stable comparison routine for use with splay trees and DECLs. */
950
951static int
952splay_tree_compare_decl_uid (splay_tree_key xa, splay_tree_key xb)
953{
954 tree a = (tree) xa;
955 tree b = (tree) xb;
956
957 return DECL_UID (a) - DECL_UID (b);
958}
959
960/* OpenMP context during genericization. */
961
962struct cp_genericize_omp_taskreg
963{
964 bool is_parallel;
965 bool default_shared;
966 struct cp_genericize_omp_taskreg *outer;
967 splay_tree variables;
968};
969
970/* Return true if genericization should try to determine if
971 DECL is firstprivate or shared within task regions. */
972
973static bool
974omp_var_to_track (tree decl)
975{
976 tree type = TREE_TYPE (decl);
977 if (is_invisiref_parm (t: decl))
978 type = TREE_TYPE (type);
979 else if (TYPE_REF_P (type))
980 type = TREE_TYPE (type);
981 while (TREE_CODE (type) == ARRAY_TYPE)
982 type = TREE_TYPE (type);
983 if (type == error_mark_node || !CLASS_TYPE_P (type))
984 return false;
985 if (VAR_P (decl) && CP_DECL_THREAD_LOCAL_P (decl))
986 return false;
987 if (cxx_omp_predetermined_sharing (decl) != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
988 return false;
989 return true;
990}
991
992/* Note DECL use in OpenMP region OMP_CTX during genericization. */
993
994static void
995omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl)
996{
997 splay_tree_node n = splay_tree_lookup (omp_ctx->variables,
998 (splay_tree_key) decl);
999 if (n == NULL)
1000 {
1001 int flags = OMP_CLAUSE_DEFAULT_SHARED;
1002 if (omp_ctx->outer)
1003 omp_cxx_notice_variable (omp_ctx: omp_ctx->outer, decl);
1004 if (!omp_ctx->default_shared)
1005 {
1006 struct cp_genericize_omp_taskreg *octx;
1007
1008 for (octx = omp_ctx->outer; octx; octx = octx->outer)
1009 {
1010 n = splay_tree_lookup (octx->variables, (splay_tree_key) decl);
1011 if (n && n->value != OMP_CLAUSE_DEFAULT_SHARED)
1012 {
1013 flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
1014 break;
1015 }
1016 if (octx->is_parallel)
1017 break;
1018 }
1019 if (octx == NULL
1020 && (TREE_CODE (decl) == PARM_DECL
1021 || (!(TREE_STATIC (decl) || DECL_EXTERNAL (decl))
1022 && DECL_CONTEXT (decl) == current_function_decl)))
1023 flags = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
1024 if (flags == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
1025 {
1026 /* DECL is implicitly determined firstprivate in
1027 the current task construct. Ensure copy ctor and
1028 dtor are instantiated, because during gimplification
1029 it will be already too late. */
1030 tree type = TREE_TYPE (decl);
1031 if (is_invisiref_parm (t: decl))
1032 type = TREE_TYPE (type);
1033 else if (TYPE_REF_P (type))
1034 type = TREE_TYPE (type);
1035 while (TREE_CODE (type) == ARRAY_TYPE)
1036 type = TREE_TYPE (type);
1037 get_copy_ctor (type, tf_none);
1038 get_dtor (type, tf_none);
1039 }
1040 }
1041 splay_tree_insert (omp_ctx->variables, (splay_tree_key) decl, flags);
1042 }
1043}
1044
1045/* True if any of the element initializers in CTOR are TARGET_EXPRs that are
1046 not expected to elide, e.g. because unsafe_copy_elision_p is true. */
1047
1048static bool
1049any_non_eliding_target_exprs (tree ctor)
1050{
1051 for (const constructor_elt &e : *CONSTRUCTOR_ELTS (ctor))
1052 {
1053 if (TREE_CODE (e.value) == TARGET_EXPR
1054 && !TARGET_EXPR_ELIDING_P (e.value))
1055 return true;
1056 }
1057 return false;
1058}
1059
1060/* If we might need to clean up a partially constructed object, break down the
1061 CONSTRUCTOR with split_nonconstant_init. Also expand VEC_INIT_EXPR at this
1062 point. If initializing TO with FROM is non-trivial, overwrite *REPLACE with
1063 the result. */
1064
1065static void
1066cp_genericize_init (tree *replace, tree from, tree to)
1067{
1068 tree init = NULL_TREE;
1069 if (TREE_CODE (from) == VEC_INIT_EXPR)
1070 init = expand_vec_init_expr (to, from, tf_warning_or_error);
1071 else if (TREE_CODE (from) == CONSTRUCTOR
1072 && TREE_SIDE_EFFECTS (from)
1073 && ((flag_exceptions
1074 && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (from)))
1075 || any_non_eliding_target_exprs (ctor: from)))
1076 {
1077 to = cp_stabilize_reference (to);
1078 replace_placeholders (from, to);
1079 init = split_nonconstant_init (to, from);
1080 }
1081
1082 if (init)
1083 {
1084 if (*replace == from)
1085 /* Make cp_gimplify_init_expr call replace_decl on this
1086 TARGET_EXPR_INITIAL. */
1087 init = fold_convert (void_type_node, init);
1088 *replace = init;
1089 }
1090}
1091
1092/* For an INIT_EXPR, replace the INIT_EXPR itself. */
1093
1094static void
1095cp_genericize_init_expr (tree *stmt_p)
1096{
1097 iloc_sentinel ils = EXPR_LOCATION (*stmt_p);
1098 tree to = TREE_OPERAND (*stmt_p, 0);
1099 tree from = TREE_OPERAND (*stmt_p, 1);
1100 if (SIMPLE_TARGET_EXPR_P (from)
1101 /* Return gets confused if we clobber its INIT_EXPR this soon. */
1102 && TREE_CODE (to) != RESULT_DECL)
1103 from = TARGET_EXPR_INITIAL (from);
1104 cp_genericize_init (replace: stmt_p, from, to);
1105}
1106
1107/* For a TARGET_EXPR, change the TARGET_EXPR_INITIAL. We will need to use
1108 replace_decl later when we know what we're initializing. */
1109
1110static void
1111cp_genericize_target_expr (tree *stmt_p)
1112{
1113 iloc_sentinel ils = EXPR_LOCATION (*stmt_p);
1114 tree slot = TARGET_EXPR_SLOT (*stmt_p);
1115 cp_genericize_init (replace: &TARGET_EXPR_INITIAL (*stmt_p),
1116 TARGET_EXPR_INITIAL (*stmt_p), to: slot);
1117 gcc_assert (!DECL_INITIAL (slot));
1118}
1119
1120/* Similar to if (target_expr_needs_replace) replace_decl, but TP is the
1121 TARGET_EXPR_INITIAL, and this also updates *_SLOT. We need this extra
1122 replacement when cp_folding TARGET_EXPR to preserve the invariant that
1123 AGGR_INIT_EXPR_SLOT agrees with the enclosing TARGET_EXPR_SLOT. */
1124
1125static bool
1126maybe_replace_decl (tree *tp, tree decl, tree replacement)
1127{
1128 if (!*tp || !VOID_TYPE_P (TREE_TYPE (*tp)))
1129 return false;
1130 tree t = *tp;
1131 while (TREE_CODE (t) == COMPOUND_EXPR)
1132 t = TREE_OPERAND (t, 1);
1133 if (TREE_CODE (t) == AGGR_INIT_EXPR)
1134 replace_decl (&AGGR_INIT_EXPR_SLOT (t), decl, replacement);
1135 else if (TREE_CODE (t) == VEC_INIT_EXPR)
1136 replace_decl (&VEC_INIT_EXPR_SLOT (t), decl, replacement);
1137 else
1138 replace_decl (tp, decl, replacement);
1139 return true;
1140}
1141
1142/* Genericization context. */
1143
1144struct cp_genericize_data
1145{
1146 hash_set<tree> *p_set;
1147 auto_vec<tree> bind_expr_stack;
1148 struct cp_genericize_omp_taskreg *omp_ctx;
1149 tree try_block;
1150 bool no_sanitize_p;
1151 bool handle_invisiref_parm_p;
1152};
1153
1154/* Emit an error about taking the address of an immediate function.
1155 EXPR is the whole expression; DECL is the immediate function. */
1156
1157static void
1158taking_address_of_imm_fn_error (tree expr, tree decl)
1159{
1160 auto_diagnostic_group d;
1161 const location_t loc = (TREE_CODE (expr) == PTRMEM_CST
1162 ? PTRMEM_CST_LOCATION (expr)
1163 : EXPR_LOCATION (expr));
1164 error_at (loc, "taking address of an immediate function %qD", decl);
1165 maybe_explain_promoted_consteval (loc, fn: decl);
1166}
1167
1168/* A subroutine of cp_fold_r to handle immediate functions. */
1169
1170static tree
1171cp_fold_immediate_r (tree *stmt_p, int *walk_subtrees, void *data_)
1172{
1173 auto data = static_cast<cp_fold_data *>(data_);
1174 tree stmt = *stmt_p;
1175 /* The purpose of this is not to emit errors for mce_unknown. */
1176 const tsubst_flags_t complain = (data->flags & ff_mce_false
1177 ? tf_error : tf_none);
1178 const tree_code code = TREE_CODE (stmt);
1179
1180 /* No need to look into types or unevaluated operands.
1181 NB: This affects cp_fold_r as well. */
1182 if (TYPE_P (stmt)
1183 || unevaluated_p (code)
1184 /* We do not use in_immediate_context here because it checks
1185 more than is desirable, e.g., sk_template_parms. */
1186 || cp_unevaluated_operand
1187 || (current_function_decl
1188 && DECL_IMMEDIATE_FUNCTION_P (current_function_decl)))
1189 {
1190 *walk_subtrees = 0;
1191 return NULL_TREE;
1192 }
1193
1194 tree decl = NULL_TREE;
1195 bool call_p = false;
1196
1197 /* We are looking for &fn or fn(). */
1198 switch (code)
1199 {
1200 case CALL_EXPR:
1201 case AGGR_INIT_EXPR:
1202 if (tree fn = cp_get_callee (stmt))
1203 if (TREE_CODE (fn) != ADDR_EXPR || ADDR_EXPR_DENOTES_CALL_P (fn))
1204 decl = cp_get_fndecl_from_callee (fn, /*fold*/false);
1205 call_p = true;
1206 break;
1207 case PTRMEM_CST:
1208 decl = PTRMEM_CST_MEMBER (stmt);
1209 break;
1210 case ADDR_EXPR:
1211 if (!ADDR_EXPR_DENOTES_CALL_P (stmt))
1212 decl = TREE_OPERAND (stmt, 0);
1213 break;
1214 default:
1215 return NULL_TREE;
1216 }
1217
1218 if (!decl || TREE_CODE (decl) != FUNCTION_DECL)
1219 return NULL_TREE;
1220
1221 /* Fully escalate once all templates have been instantiated. What we're
1222 calling is not a consteval function but it may become one. This
1223 requires recursing; DECL may be promoted to consteval because it
1224 contains an escalating expression E, but E itself may have to be
1225 promoted first, etc. */
1226 if (at_eof > 1 && unchecked_immediate_escalating_function_p (fn: decl))
1227 {
1228 /* Set before the actual walk to avoid endless recursion. */
1229 DECL_ESCALATION_CHECKED_P (decl) = true;
1230 /* We're only looking for the first escalating expression. Let us not
1231 walk more trees than necessary, hence mce_unknown. */
1232 cp_fold_immediate (tp: &DECL_SAVED_TREE (decl), manifestly_const_eval: mce_unknown, decl);
1233 }
1234
1235 /* [expr.const]p16 "An expression or conversion is immediate-escalating if
1236 it is not initially in an immediate function context and it is either
1237 -- an immediate invocation that is not a constant expression and is not
1238 a subexpression of an immediate invocation."
1239
1240 If we are in an immediate-escalating function, the immediate-escalating
1241 expression or conversion makes it an immediate function. So STMT does
1242 not need to produce a constant expression. */
1243 if (DECL_IMMEDIATE_FUNCTION_P (decl))
1244 {
1245 tree e = cxx_constant_value (t: stmt, complain: tf_none);
1246 if (e == error_mark_node)
1247 {
1248 /* This takes care of, e.g.,
1249 template <typename T>
1250 constexpr int f(T t)
1251 {
1252 return id(t);
1253 }
1254 where id (consteval) causes f<int> to be promoted. */
1255 if (immediate_escalating_function_p (fn: current_function_decl))
1256 promote_function_to_consteval (fn: current_function_decl);
1257 else if (complain & tf_error)
1258 {
1259 if (call_p)
1260 {
1261 auto_diagnostic_group d;
1262 location_t loc = cp_expr_loc_or_input_loc (t: stmt);
1263 error_at (loc, "call to consteval function %qE is "
1264 "not a constant expression", stmt);
1265 /* Explain why it's not a constant expression. */
1266 *stmt_p = cxx_constant_value (t: stmt, complain);
1267 maybe_explain_promoted_consteval (loc, fn: decl);
1268 }
1269 else if (!data->pset.add (k: stmt))
1270 {
1271 taking_address_of_imm_fn_error (expr: stmt, decl);
1272 *stmt_p = build_zero_cst (TREE_TYPE (stmt));
1273 }
1274 /* If we're giving hard errors, continue the walk rather than
1275 bailing out after the first error. */
1276 return NULL_TREE;
1277 }
1278 *walk_subtrees = 0;
1279 return stmt;
1280 }
1281 /* We've evaluated the consteval function call. */
1282 if (call_p)
1283 *stmt_p = e;
1284 }
1285 /* We've encountered a function call that may turn out to be consteval
1286 later. Store its caller so that we can ensure that the call is
1287 a constant expression. */
1288 else if (unchecked_immediate_escalating_function_p (fn: decl))
1289 {
1290 /* Make sure we're not inserting new elements while walking
1291 the deferred_escalating_exprs hash table; if we are, it's
1292 likely that a function wasn't properly marked checked for
1293 i-e expressions. */
1294 gcc_checking_assert (at_eof <= 1);
1295 if (current_function_decl)
1296 remember_escalating_expr (t: current_function_decl);
1297 /* auto p = &f<int>; in the global scope won't be ensconced in
1298 a function we could store for later at this point. (If there's
1299 no c_f_d at this point and we're dealing with a call, we should
1300 see the call when cp_fold_function __static_i_and_d.) */
1301 else if (!call_p)
1302 remember_escalating_expr (t: stmt);
1303 }
1304
1305 return NULL_TREE;
1306}
1307
1308/* Perform any pre-gimplification folding of C++ front end trees to
1309 GENERIC.
1310 Note: The folding of non-omp cases is something to move into
1311 the middle-end. As for now we have most foldings only on GENERIC
1312 in fold-const, we need to perform this before transformation to
1313 GIMPLE-form.
1314
1315 ??? This is algorithmically weird because walk_tree works in pre-order, so
1316 we see outer expressions before inner expressions. This isn't as much of an
1317 issue because cp_fold recurses into subexpressions in many cases, but then
1318 walk_tree walks back into those subexpressions again. We avoid the
1319 resulting complexity problem by caching the result of cp_fold, but it's
1320 inelegant. */
1321
1322static tree
1323cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_)
1324{
1325 cp_fold_data *data = (cp_fold_data*)data_;
1326 tree stmt = *stmt_p;
1327 enum tree_code code = TREE_CODE (stmt);
1328
1329 if (cxx_dialect >= cxx20)
1330 {
1331 /* Unfortunately we must handle code like
1332 false ? bar () : 42
1333 where we have to check bar too. The cp_fold call below could
1334 fold the ?: into a constant before we've checked it. */
1335 if (code == COND_EXPR)
1336 {
1337 auto then_fn = cp_fold_r, else_fn = cp_fold_r;
1338 /* See if we can figure out if either of the branches is dead. If it
1339 is, we don't need to do everything that cp_fold_r does. */
1340 cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_fold_r, data, nullptr);
1341 if (integer_zerop (TREE_OPERAND (stmt, 0)))
1342 then_fn = cp_fold_immediate_r;
1343 else if (integer_nonzerop (TREE_OPERAND (stmt, 0)))
1344 else_fn = cp_fold_immediate_r;
1345
1346 if (TREE_OPERAND (stmt, 1))
1347 cp_walk_tree (&TREE_OPERAND (stmt, 1), then_fn, data,
1348 nullptr);
1349 if (TREE_OPERAND (stmt, 2))
1350 cp_walk_tree (&TREE_OPERAND (stmt, 2), else_fn, data,
1351 nullptr);
1352 *walk_subtrees = 0;
1353 /* Don't return yet, still need the cp_fold below. */
1354 }
1355 else
1356 cp_fold_immediate_r (stmt_p, walk_subtrees, data_: data);
1357 }
1358
1359 *stmt_p = stmt = cp_fold (*stmt_p, data->flags);
1360
1361 /* For certain trees, like +foo(), the cp_fold above will remove the +,
1362 and the subsequent tree walk would go straight down to the CALL_EXPR's
1363 operands, meaning that cp_fold_immediate_r would never see the
1364 CALL_EXPR. Ew :(. */
1365 if (TREE_CODE (stmt) == CALL_EXPR && code != CALL_EXPR)
1366 cp_fold_immediate_r (stmt_p, walk_subtrees, data_: data);
1367
1368 if (data->pset.add (k: stmt))
1369 {
1370 /* Don't walk subtrees of stmts we've already walked once, otherwise
1371 we can have exponential complexity with e.g. lots of nested
1372 SAVE_EXPRs or TARGET_EXPRs. cp_fold uses a cache and will return
1373 always the same tree, which the first time cp_fold_r has been
1374 called on it had the subtrees walked. */
1375 *walk_subtrees = 0;
1376 return NULL_TREE;
1377 }
1378
1379 code = TREE_CODE (stmt);
1380 switch (code)
1381 {
1382 tree x;
1383 int i, n;
1384 case OMP_FOR:
1385 case OMP_SIMD:
1386 case OMP_DISTRIBUTE:
1387 case OMP_LOOP:
1388 case OMP_TASKLOOP:
1389 case OACC_LOOP:
1390 cp_walk_tree (&OMP_FOR_BODY (stmt), cp_fold_r, data, NULL);
1391 cp_walk_tree (&OMP_FOR_CLAUSES (stmt), cp_fold_r, data, NULL);
1392 cp_walk_tree (&OMP_FOR_INIT (stmt), cp_fold_r, data, NULL);
1393 x = OMP_FOR_COND (stmt);
1394 if (x && TREE_CODE_CLASS (TREE_CODE (x)) == tcc_comparison)
1395 {
1396 cp_walk_tree (&TREE_OPERAND (x, 0), cp_fold_r, data, NULL);
1397 cp_walk_tree (&TREE_OPERAND (x, 1), cp_fold_r, data, NULL);
1398 }
1399 else if (x && TREE_CODE (x) == TREE_VEC)
1400 {
1401 n = TREE_VEC_LENGTH (x);
1402 for (i = 0; i < n; i++)
1403 {
1404 tree o = TREE_VEC_ELT (x, i);
1405 if (o && TREE_CODE_CLASS (TREE_CODE (o)) == tcc_comparison)
1406 cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
1407 }
1408 }
1409 x = OMP_FOR_INCR (stmt);
1410 if (x && TREE_CODE (x) == TREE_VEC)
1411 {
1412 n = TREE_VEC_LENGTH (x);
1413 for (i = 0; i < n; i++)
1414 {
1415 tree o = TREE_VEC_ELT (x, i);
1416 if (o && TREE_CODE (o) == MODIFY_EXPR)
1417 o = TREE_OPERAND (o, 1);
1418 if (o && (TREE_CODE (o) == PLUS_EXPR || TREE_CODE (o) == MINUS_EXPR
1419 || TREE_CODE (o) == POINTER_PLUS_EXPR))
1420 {
1421 cp_walk_tree (&TREE_OPERAND (o, 0), cp_fold_r, data, NULL);
1422 cp_walk_tree (&TREE_OPERAND (o, 1), cp_fold_r, data, NULL);
1423 }
1424 }
1425 }
1426 cp_walk_tree (&OMP_FOR_PRE_BODY (stmt), cp_fold_r, data, NULL);
1427 *walk_subtrees = 0;
1428 return NULL_TREE;
1429
1430 case IF_STMT:
1431 if (IF_STMT_CONSTEVAL_P (stmt))
1432 {
1433 /* Don't walk THEN_CLAUSE (stmt) for consteval if. IF_COND is always
1434 boolean_false_node. */
1435 cp_walk_tree (&ELSE_CLAUSE (stmt), cp_fold_r, data, NULL);
1436 cp_walk_tree (&IF_SCOPE (stmt), cp_fold_r, data, NULL);
1437 *walk_subtrees = 0;
1438 return NULL_TREE;
1439 }
1440 break;
1441
1442 /* cp_genericize_{init,target}_expr are only for genericize time; they're
1443 here rather than in cp_genericize to avoid problems with the invisible
1444 reference transition. */
1445 case INIT_EXPR:
1446 if (data->flags & ff_genericize)
1447 cp_genericize_init_expr (stmt_p);
1448 break;
1449
1450 case TARGET_EXPR:
1451 if (data->flags & ff_genericize)
1452 cp_genericize_target_expr (stmt_p);
1453
1454 /* Folding might replace e.g. a COND_EXPR with a TARGET_EXPR; in
1455 that case, strip it in favor of this one. */
1456 if (tree &init = TARGET_EXPR_INITIAL (stmt))
1457 {
1458 cp_walk_tree (&init, cp_fold_r, data, NULL);
1459 cp_walk_tree (&TARGET_EXPR_CLEANUP (stmt), cp_fold_r, data, NULL);
1460 *walk_subtrees = 0;
1461 if (TREE_CODE (init) == TARGET_EXPR)
1462 {
1463 tree sub = TARGET_EXPR_INITIAL (init);
1464 maybe_replace_decl (tp: &sub, TARGET_EXPR_SLOT (init),
1465 TARGET_EXPR_SLOT (stmt));
1466 init = sub;
1467 }
1468 }
1469 break;
1470
1471 default:
1472 break;
1473 }
1474
1475 return NULL_TREE;
1476}
1477
1478/* Fold ALL the trees! FIXME we should be able to remove this, but
1479 apparently that still causes optimization regressions. */
1480
1481void
1482cp_fold_function (tree fndecl)
1483{
1484 /* By now all manifestly-constant-evaluated expressions will have
1485 been constant-evaluated already if possible, so we can safely
1486 pass ff_mce_false. */
1487 cp_fold_data data (ff_genericize | ff_mce_false);
1488 cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_r, &data, NULL);
1489
1490 /* This is merely an optimization: if FNDECL has no i-e expressions,
1491 we'll not save c_f_d, and we can safely say that FNDECL will not
1492 be promoted to consteval. */
1493 if (deferred_escalating_exprs
1494 && !deferred_escalating_exprs->contains (k: current_function_decl))
1495 DECL_ESCALATION_CHECKED_P (fndecl) = true;
1496}
1497
1498/* We've stashed immediate-escalating functions. Now see if they indeed
1499 ought to be promoted to consteval. */
1500
1501void
1502process_and_check_pending_immediate_escalating_fns ()
1503{
1504 /* This will be null for -fno-immediate-escalation. */
1505 if (!deferred_escalating_exprs)
1506 return;
1507
1508 for (auto e : *deferred_escalating_exprs)
1509 if (TREE_CODE (e) == FUNCTION_DECL && !DECL_ESCALATION_CHECKED_P (e))
1510 cp_fold_immediate (tp: &DECL_SAVED_TREE (e), manifestly_const_eval: mce_false, decl: e);
1511
1512 /* We've escalated every function that could have been promoted to
1513 consteval. Check that we are not taking the address of a consteval
1514 function. */
1515 for (auto e : *deferred_escalating_exprs)
1516 {
1517 if (TREE_CODE (e) == FUNCTION_DECL)
1518 continue;
1519 tree decl = (TREE_CODE (e) == PTRMEM_CST
1520 ? PTRMEM_CST_MEMBER (e)
1521 : TREE_OPERAND (e, 0));
1522 if (DECL_IMMEDIATE_FUNCTION_P (decl))
1523 taking_address_of_imm_fn_error (expr: e, decl);
1524 }
1525
1526 deferred_escalating_exprs = nullptr;
1527}
1528
1529/* Turn SPACESHIP_EXPR EXPR into GENERIC. */
1530
1531static tree genericize_spaceship (tree expr)
1532{
1533 iloc_sentinel s (cp_expr_location (t_: expr));
1534 tree type = TREE_TYPE (expr);
1535 tree op0 = TREE_OPERAND (expr, 0);
1536 tree op1 = TREE_OPERAND (expr, 1);
1537 return genericize_spaceship (input_location, type, op0, op1);
1538}
1539
1540/* If EXPR involves an anonymous VLA type, prepend a DECL_EXPR for that type
1541 to trigger gimplify_type_sizes; otherwise a cast to pointer-to-VLA confuses
1542 the middle-end (c++/88256). If EXPR is a DECL, use add_stmt and return
1543 NULL_TREE; otherwise return a COMPOUND_STMT of the DECL_EXPR and EXPR. */
1544
1545tree
1546predeclare_vla (tree expr)
1547{
1548 tree type = TREE_TYPE (expr);
1549 if (type == error_mark_node)
1550 return expr;
1551 if (is_typedef_decl (x: expr))
1552 type = DECL_ORIGINAL_TYPE (expr);
1553
1554 /* We need to strip pointers for gimplify_type_sizes. */
1555 tree vla = type;
1556 while (POINTER_TYPE_P (vla))
1557 {
1558 if (TYPE_NAME (vla))
1559 return expr;
1560 vla = TREE_TYPE (vla);
1561 }
1562 if (vla == type || TYPE_NAME (vla)
1563 || !variably_modified_type_p (vla, NULL_TREE))
1564 return expr;
1565
1566 tree decl = build_decl (input_location, TYPE_DECL, NULL_TREE, vla);
1567 DECL_ARTIFICIAL (decl) = 1;
1568 TYPE_NAME (vla) = decl;
1569 tree dexp = build_stmt (input_location, DECL_EXPR, decl);
1570 if (DECL_P (expr))
1571 {
1572 add_stmt (dexp);
1573 return NULL_TREE;
1574 }
1575 else
1576 {
1577 expr = build2 (COMPOUND_EXPR, type, dexp, expr);
1578 return expr;
1579 }
1580}
1581
1582/* Perform any pre-gimplification lowering of C++ front end trees to
1583 GENERIC. */
1584
1585static tree
1586cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
1587{
1588 tree stmt = *stmt_p;
1589 struct cp_genericize_data *wtd = (struct cp_genericize_data *) data;
1590 hash_set<tree> *p_set = wtd->p_set;
1591
1592 /* If in an OpenMP context, note var uses. */
1593 if (UNLIKELY (wtd->omp_ctx != NULL)
1594 && (VAR_P (stmt)
1595 || TREE_CODE (stmt) == PARM_DECL
1596 || TREE_CODE (stmt) == RESULT_DECL)
1597 && omp_var_to_track (decl: stmt))
1598 omp_cxx_notice_variable (omp_ctx: wtd->omp_ctx, decl: stmt);
1599
1600 /* Don't dereference parms in a thunk, pass the references through. */
1601 if ((TREE_CODE (stmt) == CALL_EXPR && call_from_lambda_thunk_p (stmt))
1602 || (TREE_CODE (stmt) == AGGR_INIT_EXPR && AGGR_INIT_FROM_THUNK_P (stmt)))
1603 {
1604 *walk_subtrees = 0;
1605 return NULL;
1606 }
1607
1608 /* Dereference invisible reference parms. */
1609 if (wtd->handle_invisiref_parm_p && is_invisiref_parm (t: stmt))
1610 {
1611 *stmt_p = convert_from_reference (stmt);
1612 p_set->add (k: *stmt_p);
1613 *walk_subtrees = 0;
1614 return NULL;
1615 }
1616
1617 /* Map block scope extern declarations to visible declarations with the
1618 same name and type in outer scopes if any. */
1619 if (VAR_OR_FUNCTION_DECL_P (stmt) && DECL_LOCAL_DECL_P (stmt))
1620 if (tree alias = DECL_LOCAL_DECL_ALIAS (stmt))
1621 {
1622 if (alias != error_mark_node)
1623 {
1624 *stmt_p = alias;
1625 TREE_USED (alias) |= TREE_USED (stmt);
1626 }
1627 *walk_subtrees = 0;
1628 return NULL;
1629 }
1630
1631 if (TREE_CODE (stmt) == INTEGER_CST
1632 && TYPE_REF_P (TREE_TYPE (stmt))
1633 && (flag_sanitize & (SANITIZE_NULL | SANITIZE_ALIGNMENT))
1634 && !wtd->no_sanitize_p)
1635 {
1636 ubsan_maybe_instrument_reference (stmt_p);
1637 if (*stmt_p != stmt)
1638 {
1639 *walk_subtrees = 0;
1640 return NULL_TREE;
1641 }
1642 }
1643
1644 /* Other than invisiref parms, don't walk the same tree twice. */
1645 if (p_set->contains (k: stmt))
1646 {
1647 *walk_subtrees = 0;
1648 return NULL_TREE;
1649 }
1650
1651 switch (TREE_CODE (stmt))
1652 {
1653 case ADDR_EXPR:
1654 if (is_invisiref_parm (TREE_OPERAND (stmt, 0)))
1655 {
1656 /* If in an OpenMP context, note var uses. */
1657 if (UNLIKELY (wtd->omp_ctx != NULL)
1658 && omp_var_to_track (TREE_OPERAND (stmt, 0)))
1659 omp_cxx_notice_variable (omp_ctx: wtd->omp_ctx, TREE_OPERAND (stmt, 0));
1660 *stmt_p = fold_convert (TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
1661 *walk_subtrees = 0;
1662 }
1663 break;
1664
1665 case RETURN_EXPR:
1666 if (TREE_OPERAND (stmt, 0))
1667 {
1668 if (is_invisiref_parm (TREE_OPERAND (stmt, 0)))
1669 /* Don't dereference an invisiref RESULT_DECL inside a
1670 RETURN_EXPR. */
1671 *walk_subtrees = 0;
1672 if (RETURN_EXPR_LOCAL_ADDR_P (stmt))
1673 {
1674 /* Don't return the address of a local variable. */
1675 tree *p = &TREE_OPERAND (stmt, 0);
1676 while (TREE_CODE (*p) == COMPOUND_EXPR)
1677 p = &TREE_OPERAND (*p, 0);
1678 if (TREE_CODE (*p) == INIT_EXPR)
1679 {
1680 tree op = TREE_OPERAND (*p, 1);
1681 tree new_op = build2 (COMPOUND_EXPR, TREE_TYPE (op), op,
1682 build_zero_cst (TREE_TYPE (op)));
1683 TREE_OPERAND (*p, 1) = new_op;
1684 }
1685 }
1686 }
1687 break;
1688
1689 case OMP_CLAUSE:
1690 switch (OMP_CLAUSE_CODE (stmt))
1691 {
1692 case OMP_CLAUSE_LASTPRIVATE:
1693 /* Don't dereference an invisiref in OpenMP clauses. */
1694 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
1695 {
1696 *walk_subtrees = 0;
1697 if (OMP_CLAUSE_LASTPRIVATE_STMT (stmt))
1698 cp_walk_tree (&OMP_CLAUSE_LASTPRIVATE_STMT (stmt),
1699 cp_genericize_r, data, NULL);
1700 }
1701 break;
1702 case OMP_CLAUSE_PRIVATE:
1703 /* Don't dereference an invisiref in OpenMP clauses. */
1704 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
1705 *walk_subtrees = 0;
1706 else if (wtd->omp_ctx != NULL)
1707 {
1708 /* Private clause doesn't cause any references to the
1709 var in outer contexts, avoid calling
1710 omp_cxx_notice_variable for it. */
1711 struct cp_genericize_omp_taskreg *old = wtd->omp_ctx;
1712 wtd->omp_ctx = NULL;
1713 cp_walk_tree (&OMP_CLAUSE_DECL (stmt), cp_genericize_r,
1714 data, NULL);
1715 wtd->omp_ctx = old;
1716 *walk_subtrees = 0;
1717 }
1718 break;
1719 case OMP_CLAUSE_SHARED:
1720 case OMP_CLAUSE_FIRSTPRIVATE:
1721 case OMP_CLAUSE_COPYIN:
1722 case OMP_CLAUSE_COPYPRIVATE:
1723 case OMP_CLAUSE_INCLUSIVE:
1724 case OMP_CLAUSE_EXCLUSIVE:
1725 /* Don't dereference an invisiref in OpenMP clauses. */
1726 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
1727 *walk_subtrees = 0;
1728 break;
1729 case OMP_CLAUSE_REDUCTION:
1730 case OMP_CLAUSE_IN_REDUCTION:
1731 case OMP_CLAUSE_TASK_REDUCTION:
1732 /* Don't dereference an invisiref in reduction clause's
1733 OMP_CLAUSE_DECL either. OMP_CLAUSE_REDUCTION_{INIT,MERGE}
1734 still needs to be genericized. */
1735 if (is_invisiref_parm (OMP_CLAUSE_DECL (stmt)))
1736 {
1737 *walk_subtrees = 0;
1738 if (OMP_CLAUSE_REDUCTION_INIT (stmt))
1739 cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (stmt),
1740 cp_genericize_r, data, NULL);
1741 if (OMP_CLAUSE_REDUCTION_MERGE (stmt))
1742 cp_walk_tree (&OMP_CLAUSE_REDUCTION_MERGE (stmt),
1743 cp_genericize_r, data, NULL);
1744 }
1745 break;
1746 default:
1747 break;
1748 }
1749 break;
1750
1751 /* Due to the way voidify_wrapper_expr is written, we don't get a chance
1752 to lower this construct before scanning it, so we need to lower these
1753 before doing anything else. */
1754 case CLEANUP_STMT:
1755 *stmt_p = build2_loc (EXPR_LOCATION (stmt),
1756 CLEANUP_EH_ONLY (stmt) ? TRY_CATCH_EXPR
1757 : TRY_FINALLY_EXPR,
1758 void_type_node,
1759 CLEANUP_BODY (stmt),
1760 CLEANUP_EXPR (stmt));
1761 break;
1762
1763 case IF_STMT:
1764 genericize_if_stmt (stmt_p);
1765 /* *stmt_p has changed, tail recurse to handle it again. */
1766 return cp_genericize_r (stmt_p, walk_subtrees, data);
1767
1768 /* COND_EXPR might have incompatible types in branches if one or both
1769 arms are bitfields. Fix it up now. */
1770 case COND_EXPR:
1771 {
1772 tree type_left
1773 = (TREE_OPERAND (stmt, 1)
1774 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 1))
1775 : NULL_TREE);
1776 tree type_right
1777 = (TREE_OPERAND (stmt, 2)
1778 ? is_bitfield_expr_with_lowered_type (TREE_OPERAND (stmt, 2))
1779 : NULL_TREE);
1780 if (type_left
1781 && !useless_type_conversion_p (TREE_TYPE (stmt),
1782 TREE_TYPE (TREE_OPERAND (stmt, 1))))
1783 {
1784 TREE_OPERAND (stmt, 1)
1785 = fold_convert (type_left, TREE_OPERAND (stmt, 1));
1786 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
1787 type_left));
1788 }
1789 if (type_right
1790 && !useless_type_conversion_p (TREE_TYPE (stmt),
1791 TREE_TYPE (TREE_OPERAND (stmt, 2))))
1792 {
1793 TREE_OPERAND (stmt, 2)
1794 = fold_convert (type_right, TREE_OPERAND (stmt, 2));
1795 gcc_assert (useless_type_conversion_p (TREE_TYPE (stmt),
1796 type_right));
1797 }
1798 }
1799 break;
1800
1801 case BIND_EXPR:
1802 if (UNLIKELY (wtd->omp_ctx != NULL))
1803 {
1804 tree decl;
1805 for (decl = BIND_EXPR_VARS (stmt); decl; decl = DECL_CHAIN (decl))
1806 if (VAR_P (decl)
1807 && !DECL_EXTERNAL (decl)
1808 && omp_var_to_track (decl))
1809 {
1810 splay_tree_node n
1811 = splay_tree_lookup (wtd->omp_ctx->variables,
1812 (splay_tree_key) decl);
1813 if (n == NULL)
1814 splay_tree_insert (wtd->omp_ctx->variables,
1815 (splay_tree_key) decl,
1816 TREE_STATIC (decl)
1817 ? OMP_CLAUSE_DEFAULT_SHARED
1818 : OMP_CLAUSE_DEFAULT_PRIVATE);
1819 }
1820 }
1821 if (sanitize_flags_p (flag: SANITIZE_NULL | SANITIZE_ALIGNMENT | SANITIZE_VPTR))
1822 {
1823 /* The point here is to not sanitize static initializers. */
1824 bool no_sanitize_p = wtd->no_sanitize_p;
1825 wtd->no_sanitize_p = true;
1826 for (tree decl = BIND_EXPR_VARS (stmt);
1827 decl;
1828 decl = DECL_CHAIN (decl))
1829 if (VAR_P (decl)
1830 && TREE_STATIC (decl)
1831 && DECL_INITIAL (decl))
1832 cp_walk_tree (&DECL_INITIAL (decl), cp_genericize_r, data, NULL);
1833 wtd->no_sanitize_p = no_sanitize_p;
1834 }
1835 wtd->bind_expr_stack.safe_push (obj: stmt);
1836 cp_walk_tree (&BIND_EXPR_BODY (stmt),
1837 cp_genericize_r, data, NULL);
1838 wtd->bind_expr_stack.pop ();
1839 break;
1840
1841 case ASSERTION_STMT:
1842 case PRECONDITION_STMT:
1843 case POSTCONDITION_STMT:
1844 {
1845 if (tree check = build_contract_check (stmt))
1846 {
1847 *stmt_p = check;
1848 return cp_genericize_r (stmt_p, walk_subtrees, data);
1849 }
1850
1851 /* If we didn't build a check, replace it with void_node so we don't
1852 leak contracts into GENERIC. */
1853 *stmt_p = void_node;
1854 *walk_subtrees = 0;
1855 }
1856 break;
1857
1858 case USING_STMT:
1859 {
1860 tree block = NULL_TREE;
1861
1862 /* Get the innermost inclosing GIMPLE_BIND that has a non NULL
1863 BLOCK, and append an IMPORTED_DECL to its
1864 BLOCK_VARS chained list. */
1865 if (wtd->bind_expr_stack.exists ())
1866 {
1867 int i;
1868 for (i = wtd->bind_expr_stack.length () - 1; i >= 0; i--)
1869 if ((block = BIND_EXPR_BLOCK (wtd->bind_expr_stack[i])))
1870 break;
1871 }
1872 if (block)
1873 {
1874 tree decl = TREE_OPERAND (stmt, 0);
1875 gcc_assert (decl);
1876
1877 if (undeduced_auto_decl (decl))
1878 /* Omit from the GENERIC, the back-end can't handle it. */;
1879 else
1880 {
1881 tree using_directive = make_node (IMPORTED_DECL);
1882 TREE_TYPE (using_directive) = void_type_node;
1883 DECL_CONTEXT (using_directive) = current_function_decl;
1884 DECL_SOURCE_LOCATION (using_directive)
1885 = cp_expr_loc_or_input_loc (t: stmt);
1886
1887 IMPORTED_DECL_ASSOCIATED_DECL (using_directive) = decl;
1888 DECL_CHAIN (using_directive) = BLOCK_VARS (block);
1889 BLOCK_VARS (block) = using_directive;
1890 }
1891 }
1892 /* The USING_STMT won't appear in GENERIC. */
1893 *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1894 *walk_subtrees = 0;
1895 }
1896 break;
1897
1898 case DECL_EXPR:
1899 if (TREE_CODE (DECL_EXPR_DECL (stmt)) == USING_DECL)
1900 {
1901 /* Using decls inside DECL_EXPRs are just dropped on the floor. */
1902 *stmt_p = build1 (NOP_EXPR, void_type_node, integer_zero_node);
1903 *walk_subtrees = 0;
1904 }
1905 else
1906 {
1907 tree d = DECL_EXPR_DECL (stmt);
1908 if (VAR_P (d))
1909 gcc_assert (CP_DECL_THREAD_LOCAL_P (d) == DECL_THREAD_LOCAL_P (d));
1910 }
1911 break;
1912
1913 case OMP_PARALLEL:
1914 case OMP_TASK:
1915 case OMP_TASKLOOP:
1916 {
1917 struct cp_genericize_omp_taskreg omp_ctx;
1918 tree c, decl;
1919 splay_tree_node n;
1920
1921 *walk_subtrees = 0;
1922 cp_walk_tree (&OMP_CLAUSES (stmt), cp_genericize_r, data, NULL);
1923 omp_ctx.is_parallel = TREE_CODE (stmt) == OMP_PARALLEL;
1924 omp_ctx.default_shared = omp_ctx.is_parallel;
1925 omp_ctx.outer = wtd->omp_ctx;
1926 omp_ctx.variables = splay_tree_new (splay_tree_compare_decl_uid, 0, 0);
1927 wtd->omp_ctx = &omp_ctx;
1928 for (c = OMP_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
1929 switch (OMP_CLAUSE_CODE (c))
1930 {
1931 case OMP_CLAUSE_SHARED:
1932 case OMP_CLAUSE_PRIVATE:
1933 case OMP_CLAUSE_FIRSTPRIVATE:
1934 case OMP_CLAUSE_LASTPRIVATE:
1935 decl = OMP_CLAUSE_DECL (c);
1936 if (decl == error_mark_node || !omp_var_to_track (decl))
1937 break;
1938 n = splay_tree_lookup (omp_ctx.variables, (splay_tree_key) decl);
1939 if (n != NULL)
1940 break;
1941 splay_tree_insert (omp_ctx.variables, (splay_tree_key) decl,
1942 OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED
1943 ? OMP_CLAUSE_DEFAULT_SHARED
1944 : OMP_CLAUSE_DEFAULT_PRIVATE);
1945 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE && omp_ctx.outer)
1946 omp_cxx_notice_variable (omp_ctx: omp_ctx.outer, decl);
1947 break;
1948 case OMP_CLAUSE_DEFAULT:
1949 if (OMP_CLAUSE_DEFAULT_KIND (c) == OMP_CLAUSE_DEFAULT_SHARED)
1950 omp_ctx.default_shared = true;
1951 default:
1952 break;
1953 }
1954 if (TREE_CODE (stmt) == OMP_TASKLOOP)
1955 c_genericize_control_stmt (stmt_p, walk_subtrees, data,
1956 cp_genericize_r, cp_walk_subtrees);
1957 else
1958 cp_walk_tree (&OMP_BODY (stmt), cp_genericize_r, data, NULL);
1959 wtd->omp_ctx = omp_ctx.outer;
1960 splay_tree_delete (omp_ctx.variables);
1961 }
1962 break;
1963
1964 case OMP_TARGET:
1965 cfun->has_omp_target = true;
1966 break;
1967
1968 case TRY_BLOCK:
1969 {
1970 *walk_subtrees = 0;
1971 tree try_block = wtd->try_block;
1972 wtd->try_block = stmt;
1973 cp_walk_tree (&TRY_STMTS (stmt), cp_genericize_r, data, NULL);
1974 wtd->try_block = try_block;
1975 cp_walk_tree (&TRY_HANDLERS (stmt), cp_genericize_r, data, NULL);
1976 }
1977 break;
1978
1979 case MUST_NOT_THROW_EXPR:
1980 /* MUST_NOT_THROW_COND might be something else with TM. */
1981 if (MUST_NOT_THROW_COND (stmt) == NULL_TREE)
1982 {
1983 *walk_subtrees = 0;
1984 tree try_block = wtd->try_block;
1985 wtd->try_block = stmt;
1986 cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_genericize_r, data, NULL);
1987 wtd->try_block = try_block;
1988 }
1989 break;
1990
1991 case THROW_EXPR:
1992 {
1993 location_t loc = location_of (stmt);
1994 if (warning_suppressed_p (stmt /* What warning? */))
1995 /* Never mind. */;
1996 else if (wtd->try_block)
1997 {
1998 if (TREE_CODE (wtd->try_block) == MUST_NOT_THROW_EXPR)
1999 {
2000 auto_diagnostic_group d;
2001 if (warning_at (loc, OPT_Wterminate,
2002 "%<throw%> will always call %<terminate%>")
2003 && cxx_dialect >= cxx11
2004 && DECL_DESTRUCTOR_P (current_function_decl))
2005 inform (loc, "in C++11 destructors default to %<noexcept%>");
2006 }
2007 }
2008 else
2009 {
2010 if (warn_cxx11_compat && cxx_dialect < cxx11
2011 && DECL_DESTRUCTOR_P (current_function_decl)
2012 && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl))
2013 == NULL_TREE)
2014 && (get_defaulted_eh_spec (current_function_decl)
2015 == empty_except_spec))
2016 warning_at (loc, OPT_Wc__11_compat,
2017 "in C++11 this %<throw%> will call %<terminate%> "
2018 "because destructors default to %<noexcept%>");
2019 }
2020 }
2021 break;
2022
2023 case CONVERT_EXPR:
2024 gcc_checking_assert (!AGGREGATE_TYPE_P (TREE_TYPE (stmt)));
2025 gcc_assert (!CONVERT_EXPR_VBASE_PATH (stmt));
2026 break;
2027
2028 case SPACESHIP_EXPR:
2029 *stmt_p = genericize_spaceship (expr: *stmt_p);
2030 break;
2031
2032 case PTRMEM_CST:
2033 /* By the time we get here we're handing off to the back end, so we don't
2034 need or want to preserve PTRMEM_CST anymore. */
2035 *stmt_p = cplus_expand_constant (stmt);
2036 *walk_subtrees = 0;
2037 break;
2038
2039 case MEM_REF:
2040 /* For MEM_REF, make sure not to sanitize the second operand even
2041 if it has reference type. It is just an offset with a type
2042 holding other information. There is no other processing we
2043 need to do for INTEGER_CSTs, so just ignore the second argument
2044 unconditionally. */
2045 cp_walk_tree (&TREE_OPERAND (stmt, 0), cp_genericize_r, data, NULL);
2046 *walk_subtrees = 0;
2047 break;
2048
2049 case NOP_EXPR:
2050 *stmt_p = predeclare_vla (expr: *stmt_p);
2051
2052 /* Warn of new allocations that are not big enough for the target
2053 type. */
2054 if (warn_alloc_size
2055 && TREE_CODE (TREE_OPERAND (stmt, 0)) == CALL_EXPR
2056 && POINTER_TYPE_P (TREE_TYPE (stmt)))
2057 {
2058 if (tree fndecl = get_callee_fndecl (TREE_OPERAND (stmt, 0)))
2059 if (DECL_IS_MALLOC (fndecl))
2060 {
2061 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (fndecl));
2062 tree alloc_size = lookup_attribute (attr_name: "alloc_size", list: attrs);
2063 if (alloc_size)
2064 warn_for_alloc_size (EXPR_LOCATION (stmt),
2065 TREE_TYPE (TREE_TYPE (stmt)),
2066 TREE_OPERAND (stmt, 0), alloc_size);
2067 }
2068 }
2069
2070 if (!wtd->no_sanitize_p
2071 && sanitize_flags_p (flag: SANITIZE_NULL | SANITIZE_ALIGNMENT)
2072 && TYPE_REF_P (TREE_TYPE (stmt)))
2073 ubsan_maybe_instrument_reference (stmt_p);
2074 break;
2075
2076 case CALL_EXPR:
2077 /* Evaluate function concept checks instead of treating them as
2078 normal functions. */
2079 if (concept_check_p (t: stmt))
2080 {
2081 *stmt_p = evaluate_concept_check (stmt);
2082 * walk_subtrees = 0;
2083 break;
2084 }
2085
2086 if (!wtd->no_sanitize_p
2087 && sanitize_flags_p (flag: (SANITIZE_NULL
2088 | SANITIZE_ALIGNMENT | SANITIZE_VPTR)))
2089 {
2090 tree fn = CALL_EXPR_FN (stmt);
2091 if (fn != NULL_TREE
2092 && !error_operand_p (t: fn)
2093 && INDIRECT_TYPE_P (TREE_TYPE (fn))
2094 && TREE_CODE (TREE_TYPE (TREE_TYPE (fn))) == METHOD_TYPE)
2095 {
2096 bool is_ctor
2097 = TREE_CODE (fn) == ADDR_EXPR
2098 && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL
2099 && DECL_CONSTRUCTOR_P (TREE_OPERAND (fn, 0));
2100 if (sanitize_flags_p (flag: SANITIZE_NULL | SANITIZE_ALIGNMENT))
2101 ubsan_maybe_instrument_member_call (stmt, is_ctor);
2102 if (sanitize_flags_p (flag: SANITIZE_VPTR) && !is_ctor)
2103 cp_ubsan_maybe_instrument_member_call (stmt);
2104 }
2105 else if (fn == NULL_TREE
2106 && CALL_EXPR_IFN (stmt) == IFN_UBSAN_NULL
2107 && TREE_CODE (CALL_EXPR_ARG (stmt, 0)) == INTEGER_CST
2108 && TYPE_REF_P (TREE_TYPE (CALL_EXPR_ARG (stmt, 0))))
2109 *walk_subtrees = 0;
2110 }
2111 /* Fall through. */
2112 case AGGR_INIT_EXPR:
2113 /* For calls to a multi-versioned function, overload resolution
2114 returns the function with the highest target priority, that is,
2115 the version that will checked for dispatching first. If this
2116 version is inlinable, a direct call to this version can be made
2117 otherwise the call should go through the dispatcher. */
2118 {
2119 tree fn = cp_get_callee_fndecl_nofold (stmt);
2120 if (fn && DECL_FUNCTION_VERSIONED (fn)
2121 && (current_function_decl == NULL
2122 || !targetm.target_option.can_inline_p (current_function_decl,
2123 fn)))
2124 if (tree dis = get_function_version_dispatcher (fn))
2125 {
2126 mark_versions_used (dis);
2127 dis = build_address (dis);
2128 if (TREE_CODE (stmt) == CALL_EXPR)
2129 CALL_EXPR_FN (stmt) = dis;
2130 else
2131 AGGR_INIT_EXPR_FN (stmt) = dis;
2132 }
2133 }
2134 break;
2135
2136 case TARGET_EXPR:
2137 if (TARGET_EXPR_INITIAL (stmt)
2138 && TREE_CODE (TARGET_EXPR_INITIAL (stmt)) == CONSTRUCTOR
2139 && CONSTRUCTOR_PLACEHOLDER_BOUNDARY (TARGET_EXPR_INITIAL (stmt)))
2140 TARGET_EXPR_NO_ELIDE (stmt) = 1;
2141 break;
2142
2143 case TEMPLATE_ID_EXPR:
2144 gcc_assert (concept_check_p (stmt));
2145 /* Emit the value of the concept check. */
2146 *stmt_p = evaluate_concept_check (stmt);
2147 walk_subtrees = 0;
2148 break;
2149
2150 case OMP_DISTRIBUTE:
2151 /* Need to explicitly instantiate copy ctors on class iterators of
2152 composite distribute parallel for. */
2153 if (OMP_FOR_INIT (*stmt_p) == NULL_TREE)
2154 {
2155 tree *data[4] = { NULL, NULL, NULL, NULL };
2156 tree inner = walk_tree (&OMP_FOR_BODY (*stmt_p),
2157 find_combined_omp_for, data, NULL);
2158 if (inner != NULL_TREE
2159 && TREE_CODE (inner) == OMP_FOR)
2160 {
2161 for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (inner)); i++)
2162 if (OMP_FOR_ORIG_DECLS (inner)
2163 && TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner),
2164 i)) == TREE_LIST
2165 && TREE_PURPOSE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner),
2166 i)))
2167 {
2168 tree orig = TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (inner), i);
2169 /* Class iterators aren't allowed on OMP_SIMD, so the only
2170 case we need to solve is distribute parallel for. */
2171 gcc_assert (TREE_CODE (inner) == OMP_FOR
2172 && data[1]);
2173 tree orig_decl = TREE_PURPOSE (orig);
2174 tree c, cl = NULL_TREE;
2175 for (c = OMP_FOR_CLAUSES (inner);
2176 c; c = OMP_CLAUSE_CHAIN (c))
2177 if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2178 || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
2179 && OMP_CLAUSE_DECL (c) == orig_decl)
2180 {
2181 cl = c;
2182 break;
2183 }
2184 if (cl == NULL_TREE)
2185 {
2186 for (c = OMP_PARALLEL_CLAUSES (*data[1]);
2187 c; c = OMP_CLAUSE_CHAIN (c))
2188 if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
2189 && OMP_CLAUSE_DECL (c) == orig_decl)
2190 {
2191 cl = c;
2192 break;
2193 }
2194 }
2195 if (cl)
2196 {
2197 orig_decl = require_complete_type (orig_decl);
2198 tree inner_type = TREE_TYPE (orig_decl);
2199 if (orig_decl == error_mark_node)
2200 continue;
2201 if (TYPE_REF_P (TREE_TYPE (orig_decl)))
2202 inner_type = TREE_TYPE (inner_type);
2203
2204 while (TREE_CODE (inner_type) == ARRAY_TYPE)
2205 inner_type = TREE_TYPE (inner_type);
2206 get_copy_ctor (inner_type, tf_warning_or_error);
2207 }
2208 }
2209 }
2210 }
2211 /* FALLTHRU */
2212
2213 case FOR_STMT:
2214 case WHILE_STMT:
2215 case DO_STMT:
2216 case SWITCH_STMT:
2217 case CONTINUE_STMT:
2218 case BREAK_STMT:
2219 case OMP_FOR:
2220 case OMP_SIMD:
2221 case OMP_LOOP:
2222 case OACC_LOOP:
2223 case STATEMENT_LIST:
2224 /* These cases are handled by shared code. */
2225 c_genericize_control_stmt (stmt_p, walk_subtrees, data,
2226 cp_genericize_r, cp_walk_subtrees);
2227 break;
2228
2229 case BIT_CAST_EXPR:
2230 *stmt_p = build1_loc (EXPR_LOCATION (stmt), code: VIEW_CONVERT_EXPR,
2231 TREE_TYPE (stmt), TREE_OPERAND (stmt, 0));
2232 break;
2233
2234 default:
2235 if (IS_TYPE_OR_DECL_P (stmt))
2236 *walk_subtrees = 0;
2237 break;
2238 }
2239
2240 p_set->add (k: *stmt_p);
2241
2242 return NULL;
2243}
2244
2245/* Lower C++ front end trees to GENERIC in T_P. */
2246
2247static void
2248cp_genericize_tree (tree* t_p, bool handle_invisiref_parm_p)
2249{
2250 struct cp_genericize_data wtd;
2251
2252 wtd.p_set = new hash_set<tree>;
2253 wtd.bind_expr_stack.create (nelems: 0);
2254 wtd.omp_ctx = NULL;
2255 wtd.try_block = NULL_TREE;
2256 wtd.no_sanitize_p = false;
2257 wtd.handle_invisiref_parm_p = handle_invisiref_parm_p;
2258 cp_walk_tree (t_p, cp_genericize_r, &wtd, NULL);
2259 delete wtd.p_set;
2260 if (sanitize_flags_p (flag: SANITIZE_VPTR))
2261 cp_ubsan_instrument_member_accesses (t_p);
2262}
2263
2264/* If a function that should end with a return in non-void
2265 function doesn't obviously end with return, add ubsan
2266 instrumentation code to verify it at runtime. If -fsanitize=return
2267 is not enabled, instrument __builtin_unreachable. */
2268
2269static void
2270cp_maybe_instrument_return (tree fndecl)
2271{
2272 if (VOID_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))
2273 || DECL_CONSTRUCTOR_P (fndecl)
2274 || DECL_DESTRUCTOR_P (fndecl)
2275 || !targetm.warn_func_return (fndecl))
2276 return;
2277
2278 if (!sanitize_flags_p (flag: SANITIZE_RETURN, fn: fndecl)
2279 /* Don't add __builtin_unreachable () if not optimizing, it will not
2280 improve any optimizations in that case, just break UB code.
2281 Don't add it if -fsanitize=unreachable -fno-sanitize=return either,
2282 UBSan covers this with ubsan_instrument_return above where sufficient
2283 information is provided, while the __builtin_unreachable () below
2284 if return sanitization is disabled will just result in hard to
2285 understand runtime error without location. */
2286 && ((!optimize && !flag_unreachable_traps)
2287 || sanitize_flags_p (flag: SANITIZE_UNREACHABLE, fn: fndecl)))
2288 return;
2289
2290 tree t = DECL_SAVED_TREE (fndecl);
2291 while (t)
2292 {
2293 switch (TREE_CODE (t))
2294 {
2295 case BIND_EXPR:
2296 t = BIND_EXPR_BODY (t);
2297 continue;
2298 case TRY_FINALLY_EXPR:
2299 case CLEANUP_POINT_EXPR:
2300 t = TREE_OPERAND (t, 0);
2301 continue;
2302 case STATEMENT_LIST:
2303 {
2304 tree_stmt_iterator i = tsi_last (t);
2305 while (!tsi_end_p (i))
2306 {
2307 tree p = tsi_stmt (i);
2308 if (TREE_CODE (p) != DEBUG_BEGIN_STMT)
2309 break;
2310 tsi_prev (i: &i);
2311 }
2312 if (!tsi_end_p (i))
2313 {
2314 t = tsi_stmt (i);
2315 continue;
2316 }
2317 }
2318 break;
2319 case RETURN_EXPR:
2320 return;
2321 default:
2322 break;
2323 }
2324 break;
2325 }
2326 if (t == NULL_TREE)
2327 return;
2328 tree *p = &DECL_SAVED_TREE (fndecl);
2329 if (TREE_CODE (*p) == BIND_EXPR)
2330 p = &BIND_EXPR_BODY (*p);
2331
2332 location_t loc = DECL_SOURCE_LOCATION (fndecl);
2333 if (sanitize_flags_p (flag: SANITIZE_RETURN, fn: fndecl))
2334 t = ubsan_instrument_return (loc);
2335 else
2336 t = build_builtin_unreachable (BUILTINS_LOCATION);
2337
2338 append_to_statement_list (t, p);
2339}
2340
2341void
2342cp_genericize (tree fndecl)
2343{
2344 tree t;
2345
2346 /* Fix up the types of parms passed by invisible reference. */
2347 for (t = DECL_ARGUMENTS (fndecl); t; t = DECL_CHAIN (t))
2348 if (TREE_ADDRESSABLE (TREE_TYPE (t)))
2349 {
2350 /* If a function's arguments are copied to create a thunk,
2351 then DECL_BY_REFERENCE will be set -- but the type of the
2352 argument will be a pointer type, so we will never get
2353 here. */
2354 gcc_assert (!DECL_BY_REFERENCE (t));
2355 gcc_assert (DECL_ARG_TYPE (t) != TREE_TYPE (t));
2356 TREE_TYPE (t) = DECL_ARG_TYPE (t);
2357 DECL_BY_REFERENCE (t) = 1;
2358 TREE_ADDRESSABLE (t) = 0;
2359 relayout_decl (t);
2360 }
2361
2362 /* Do the same for the return value. */
2363 if (TREE_ADDRESSABLE (TREE_TYPE (DECL_RESULT (fndecl))))
2364 {
2365 t = DECL_RESULT (fndecl);
2366 TREE_TYPE (t) = build_reference_type (TREE_TYPE (t));
2367 DECL_BY_REFERENCE (t) = 1;
2368 TREE_ADDRESSABLE (t) = 0;
2369 relayout_decl (t);
2370 if (DECL_NAME (t))
2371 {
2372 /* Adjust DECL_VALUE_EXPR of the original var. */
2373 tree outer = outer_curly_brace_block (current_function_decl);
2374 tree var;
2375
2376 if (outer)
2377 for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
2378 if (VAR_P (var)
2379 && DECL_NAME (t) == DECL_NAME (var)
2380 && DECL_HAS_VALUE_EXPR_P (var)
2381 && DECL_VALUE_EXPR (var) == t)
2382 {
2383 tree val = convert_from_reference (t);
2384 SET_DECL_VALUE_EXPR (var, val);
2385 break;
2386 }
2387 }
2388 }
2389
2390 /* If we're a clone, the body is already GIMPLE. */
2391 if (DECL_CLONED_FUNCTION_P (fndecl))
2392 return;
2393
2394 /* Allow cp_genericize calls to be nested. */
2395 bc_state_t save_state;
2396 save_bc_state (&save_state);
2397
2398 /* We do want to see every occurrence of the parms, so we can't just use
2399 walk_tree's hash functionality. */
2400 cp_genericize_tree (t_p: &DECL_SAVED_TREE (fndecl), handle_invisiref_parm_p: true);
2401
2402 cp_maybe_instrument_return (fndecl);
2403
2404 /* Do everything else. */
2405 c_genericize (fndecl);
2406 restore_bc_state (&save_state);
2407}
2408
2409/* Build code to apply FN to each member of ARG1 and ARG2. FN may be
2410 NULL if there is in fact nothing to do. ARG2 may be null if FN
2411 actually only takes one argument. */
2412
2413static tree
2414cxx_omp_clause_apply_fn (tree fn, tree arg1, tree arg2)
2415{
2416 tree defparm, parm, t;
2417 int i = 0;
2418 int nargs;
2419 tree *argarray;
2420
2421 if (fn == NULL)
2422 return NULL;
2423
2424 nargs = list_length (DECL_ARGUMENTS (fn));
2425 argarray = XALLOCAVEC (tree, nargs);
2426
2427 defparm = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fn)));
2428 if (arg2)
2429 defparm = TREE_CHAIN (defparm);
2430
2431 bool is_method = TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE;
2432 if (TREE_CODE (TREE_TYPE (arg1)) == ARRAY_TYPE)
2433 {
2434 tree inner_type = TREE_TYPE (arg1);
2435 tree start1, end1, p1;
2436 tree start2 = NULL, p2 = NULL;
2437 tree ret = NULL, lab;
2438
2439 start1 = arg1;
2440 start2 = arg2;
2441 do
2442 {
2443 inner_type = TREE_TYPE (inner_type);
2444 start1 = build4 (ARRAY_REF, inner_type, start1,
2445 size_zero_node, NULL, NULL);
2446 if (arg2)
2447 start2 = build4 (ARRAY_REF, inner_type, start2,
2448 size_zero_node, NULL, NULL);
2449 }
2450 while (TREE_CODE (inner_type) == ARRAY_TYPE);
2451 start1 = build_fold_addr_expr_loc (input_location, start1);
2452 if (arg2)
2453 start2 = build_fold_addr_expr_loc (input_location, start2);
2454
2455 end1 = TYPE_SIZE_UNIT (TREE_TYPE (arg1));
2456 end1 = fold_build_pointer_plus (start1, end1);
2457
2458 p1 = create_tmp_var (TREE_TYPE (start1));
2459 t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, start1);
2460 append_to_statement_list (t, &ret);
2461
2462 if (arg2)
2463 {
2464 p2 = create_tmp_var (TREE_TYPE (start2));
2465 t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, start2);
2466 append_to_statement_list (t, &ret);
2467 }
2468
2469 lab = create_artificial_label (input_location);
2470 t = build1 (LABEL_EXPR, void_type_node, lab);
2471 append_to_statement_list (t, &ret);
2472
2473 argarray[i++] = p1;
2474 if (arg2)
2475 argarray[i++] = p2;
2476 /* Handle default arguments. */
2477 for (parm = defparm; parm && parm != void_list_node;
2478 parm = TREE_CHAIN (parm), i++)
2479 argarray[i] = convert_default_arg (TREE_VALUE (parm),
2480 TREE_PURPOSE (parm), fn,
2481 i - is_method, tf_warning_or_error);
2482 t = build_call_a (fn, i, argarray);
2483 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (t)))
2484 t = build_cplus_new (TREE_TYPE (t), t, tf_warning_or_error);
2485 t = fold_convert (void_type_node, t);
2486 t = fold_build_cleanup_point_expr (TREE_TYPE (t), expr: t);
2487 append_to_statement_list (t, &ret);
2488
2489 t = fold_build_pointer_plus (p1, TYPE_SIZE_UNIT (inner_type));
2490 t = build2 (MODIFY_EXPR, TREE_TYPE (p1), p1, t);
2491 append_to_statement_list (t, &ret);
2492
2493 if (arg2)
2494 {
2495 t = fold_build_pointer_plus (p2, TYPE_SIZE_UNIT (inner_type));
2496 t = build2 (MODIFY_EXPR, TREE_TYPE (p2), p2, t);
2497 append_to_statement_list (t, &ret);
2498 }
2499
2500 t = build2 (NE_EXPR, boolean_type_node, p1, end1);
2501 t = build3 (COND_EXPR, void_type_node, t, build_and_jump (&lab), NULL);
2502 append_to_statement_list (t, &ret);
2503
2504 return ret;
2505 }
2506 else
2507 {
2508 argarray[i++] = build_fold_addr_expr_loc (input_location, arg1);
2509 if (arg2)
2510 argarray[i++] = build_fold_addr_expr_loc (input_location, arg2);
2511 /* Handle default arguments. */
2512 for (parm = defparm; parm && parm != void_list_node;
2513 parm = TREE_CHAIN (parm), i++)
2514 argarray[i] = convert_default_arg (TREE_VALUE (parm),
2515 TREE_PURPOSE (parm), fn,
2516 i - is_method, tf_warning_or_error);
2517 t = build_call_a (fn, i, argarray);
2518 if (MAYBE_CLASS_TYPE_P (TREE_TYPE (t)))
2519 t = build_cplus_new (TREE_TYPE (t), t, tf_warning_or_error);
2520 t = fold_convert (void_type_node, t);
2521 return fold_build_cleanup_point_expr (TREE_TYPE (t), expr: t);
2522 }
2523}
2524
2525/* Return code to initialize DECL with its default constructor, or
2526 NULL if there's nothing to do. */
2527
2528tree
2529cxx_omp_clause_default_ctor (tree clause, tree decl, tree /*outer*/)
2530{
2531 tree info = CP_OMP_CLAUSE_INFO (clause);
2532 tree ret = NULL;
2533
2534 if (info)
2535 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), arg1: decl, NULL);
2536
2537 return ret;
2538}
2539
2540/* Return code to initialize DST with a copy constructor from SRC. */
2541
2542tree
2543cxx_omp_clause_copy_ctor (tree clause, tree dst, tree src)
2544{
2545 tree info = CP_OMP_CLAUSE_INFO (clause);
2546 tree ret = NULL;
2547
2548 if (info)
2549 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 0), arg1: dst, arg2: src);
2550 if (ret == NULL)
2551 ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
2552
2553 return ret;
2554}
2555
2556/* Similarly, except use an assignment operator instead. */
2557
2558tree
2559cxx_omp_clause_assign_op (tree clause, tree dst, tree src)
2560{
2561 tree info = CP_OMP_CLAUSE_INFO (clause);
2562 tree ret = NULL;
2563
2564 if (info)
2565 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 2), arg1: dst, arg2: src);
2566 if (ret == NULL)
2567 ret = build2 (MODIFY_EXPR, TREE_TYPE (dst), dst, src);
2568
2569 return ret;
2570}
2571
2572/* Return code to destroy DECL. */
2573
2574tree
2575cxx_omp_clause_dtor (tree clause, tree decl)
2576{
2577 tree info = CP_OMP_CLAUSE_INFO (clause);
2578 tree ret = NULL;
2579
2580 if (info)
2581 ret = cxx_omp_clause_apply_fn (TREE_VEC_ELT (info, 1), arg1: decl, NULL);
2582
2583 return ret;
2584}
2585
2586/* True if OpenMP should privatize what this DECL points to rather
2587 than the DECL itself. */
2588
2589bool
2590cxx_omp_privatize_by_reference (const_tree decl)
2591{
2592 return (TYPE_REF_P (TREE_TYPE (decl))
2593 || is_invisiref_parm (t: decl));
2594}
2595
2596/* Return true if DECL is const qualified var having no mutable member. */
2597bool
2598cxx_omp_const_qual_no_mutable (tree decl)
2599{
2600 tree type = TREE_TYPE (decl);
2601 if (TYPE_REF_P (type))
2602 {
2603 if (!is_invisiref_parm (t: decl))
2604 return false;
2605 type = TREE_TYPE (type);
2606
2607 if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
2608 {
2609 /* NVR doesn't preserve const qualification of the
2610 variable's type. */
2611 tree outer = outer_curly_brace_block (current_function_decl);
2612 tree var;
2613
2614 if (outer)
2615 for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
2616 if (VAR_P (var)
2617 && DECL_NAME (decl) == DECL_NAME (var)
2618 && (TYPE_MAIN_VARIANT (type)
2619 == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
2620 {
2621 if (TYPE_READONLY (TREE_TYPE (var)))
2622 type = TREE_TYPE (var);
2623 break;
2624 }
2625 }
2626 }
2627
2628 if (type == error_mark_node)
2629 return false;
2630
2631 /* Variables with const-qualified type having no mutable member
2632 are predetermined shared. */
2633 if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
2634 return true;
2635
2636 return false;
2637}
2638
2639/* OMP_CLAUSE_DEFAULT_UNSPECIFIED unless OpenMP sharing attribute
2640 of DECL is predetermined. */
2641
2642enum omp_clause_default_kind
2643cxx_omp_predetermined_sharing_1 (tree decl)
2644{
2645 /* Static data members are predetermined shared. */
2646 if (TREE_STATIC (decl))
2647 {
2648 tree ctx = CP_DECL_CONTEXT (decl);
2649 if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx))
2650 return OMP_CLAUSE_DEFAULT_SHARED;
2651
2652 if (c_omp_predefined_variable (decl))
2653 return OMP_CLAUSE_DEFAULT_SHARED;
2654 }
2655
2656 /* this may not be specified in data-sharing clauses, still we need
2657 to predetermined it firstprivate. */
2658 if (decl == current_class_ptr)
2659 return OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
2660
2661 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
2662}
2663
2664/* Likewise, but also include the artificial vars. We don't want to
2665 disallow the artificial vars being mentioned in explicit clauses,
2666 as we use artificial vars e.g. for loop constructs with random
2667 access iterators other than pointers, but during gimplification
2668 we want to treat them as predetermined. */
2669
2670enum omp_clause_default_kind
2671cxx_omp_predetermined_sharing (tree decl)
2672{
2673 enum omp_clause_default_kind ret = cxx_omp_predetermined_sharing_1 (decl);
2674 if (ret != OMP_CLAUSE_DEFAULT_UNSPECIFIED)
2675 return ret;
2676
2677 /* Predetermine artificial variables holding integral values, those
2678 are usually result of gimplify_one_sizepos or SAVE_EXPR
2679 gimplification. */
2680 if (VAR_P (decl)
2681 && DECL_ARTIFICIAL (decl)
2682 && INTEGRAL_TYPE_P (TREE_TYPE (decl))
2683 && !(DECL_LANG_SPECIFIC (decl)
2684 && DECL_OMP_PRIVATIZED_MEMBER (decl)))
2685 return OMP_CLAUSE_DEFAULT_SHARED;
2686
2687 /* Similarly for typeinfo symbols. */
2688 if (VAR_P (decl) && DECL_ARTIFICIAL (decl) && DECL_TINFO_P (decl))
2689 return OMP_CLAUSE_DEFAULT_SHARED;
2690
2691 return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
2692}
2693
2694enum omp_clause_defaultmap_kind
2695cxx_omp_predetermined_mapping (tree decl)
2696{
2697 /* Predetermine artificial variables holding integral values, those
2698 are usually result of gimplify_one_sizepos or SAVE_EXPR
2699 gimplification. */
2700 if (VAR_P (decl)
2701 && DECL_ARTIFICIAL (decl)
2702 && INTEGRAL_TYPE_P (TREE_TYPE (decl))
2703 && !(DECL_LANG_SPECIFIC (decl)
2704 && DECL_OMP_PRIVATIZED_MEMBER (decl)))
2705 return OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
2706
2707 if (c_omp_predefined_variable (decl))
2708 return OMP_CLAUSE_DEFAULTMAP_TO;
2709
2710 return OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
2711}
2712
2713/* Finalize an implicitly determined clause. */
2714
2715void
2716cxx_omp_finish_clause (tree c, gimple_seq *, bool /* openacc */)
2717{
2718 tree decl, inner_type;
2719 bool make_shared = false;
2720
2721 if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE
2722 && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE
2723 && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE
2724 || !OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c)))
2725 return;
2726
2727 decl = OMP_CLAUSE_DECL (c);
2728 decl = require_complete_type (decl);
2729 inner_type = TREE_TYPE (decl);
2730 if (decl == error_mark_node)
2731 make_shared = true;
2732 else if (TYPE_REF_P (TREE_TYPE (decl)))
2733 inner_type = TREE_TYPE (inner_type);
2734
2735 /* We're interested in the base element, not arrays. */
2736 while (TREE_CODE (inner_type) == ARRAY_TYPE)
2737 inner_type = TREE_TYPE (inner_type);
2738
2739 /* Check for special function availability by building a call to one.
2740 Save the results, because later we won't be in the right context
2741 for making these queries. */
2742 bool first = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE;
2743 bool last = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE;
2744 if (!make_shared
2745 && CLASS_TYPE_P (inner_type)
2746 && cxx_omp_create_clause_info (c, inner_type, !first, first, last,
2747 true))
2748 make_shared = true;
2749
2750 if (make_shared)
2751 {
2752 OMP_CLAUSE_CODE (c) = OMP_CLAUSE_SHARED;
2753 OMP_CLAUSE_SHARED_FIRSTPRIVATE (c) = 0;
2754 OMP_CLAUSE_SHARED_READONLY (c) = 0;
2755 }
2756}
2757
2758/* Return true if DECL's DECL_VALUE_EXPR (if any) should be
2759 disregarded in OpenMP construct, because it is going to be
2760 remapped during OpenMP lowering. SHARED is true if DECL
2761 is going to be shared, false if it is going to be privatized. */
2762
2763bool
2764cxx_omp_disregard_value_expr (tree decl, bool shared)
2765{
2766 if (shared)
2767 return false;
2768 if (VAR_P (decl)
2769 && DECL_HAS_VALUE_EXPR_P (decl)
2770 && DECL_ARTIFICIAL (decl)
2771 && DECL_LANG_SPECIFIC (decl)
2772 && DECL_OMP_PRIVATIZED_MEMBER (decl))
2773 return true;
2774 if (VAR_P (decl) && DECL_CONTEXT (decl) && is_capture_proxy (decl))
2775 return true;
2776 return false;
2777}
2778
2779/* Fold expression X which is used as an rvalue if RVAL is true. */
2780
2781static tree
2782cp_fold_maybe_rvalue (tree x, bool rval, fold_flags_t flags)
2783{
2784 while (true)
2785 {
2786 x = cp_fold (x, flags);
2787 if (rval)
2788 x = mark_rvalue_use (x);
2789 if (rval && DECL_P (x)
2790 && !TYPE_REF_P (TREE_TYPE (x)))
2791 {
2792 tree v = decl_constant_value (x);
2793 if (v != x && v != error_mark_node)
2794 {
2795 x = v;
2796 continue;
2797 }
2798 }
2799 break;
2800 }
2801 return x;
2802}
2803
2804tree
2805cp_fold_maybe_rvalue (tree x, bool rval)
2806{
2807 return cp_fold_maybe_rvalue (x, rval, flags: ff_none);
2808}
2809
2810/* Fold expression X which is used as an rvalue. */
2811
2812static tree
2813cp_fold_rvalue (tree x, fold_flags_t flags)
2814{
2815 return cp_fold_maybe_rvalue (x, rval: true, flags);
2816}
2817
2818tree
2819cp_fold_rvalue (tree x)
2820{
2821 return cp_fold_rvalue (x, flags: ff_none);
2822}
2823
2824/* Perform folding on expression X. */
2825
2826static tree
2827cp_fully_fold (tree x, mce_value manifestly_const_eval)
2828{
2829 if (processing_template_decl)
2830 return x;
2831 /* FIXME cp_fold ought to be a superset of maybe_constant_value so we don't
2832 have to call both. */
2833 if (cxx_dialect >= cxx11)
2834 {
2835 x = maybe_constant_value (x, /*decl=*/NULL_TREE, manifestly_const_eval);
2836 /* Sometimes we are given a CONSTRUCTOR but the call above wraps it into
2837 a TARGET_EXPR; undo that here. */
2838 if (TREE_CODE (x) == TARGET_EXPR)
2839 x = TARGET_EXPR_INITIAL (x);
2840 else if (TREE_CODE (x) == VIEW_CONVERT_EXPR
2841 && TREE_CODE (TREE_OPERAND (x, 0)) == CONSTRUCTOR
2842 && TREE_TYPE (TREE_OPERAND (x, 0)) == TREE_TYPE (x))
2843 x = TREE_OPERAND (x, 0);
2844 }
2845 fold_flags_t flags = ff_none;
2846 if (manifestly_const_eval == mce_false)
2847 flags |= ff_mce_false;
2848 return cp_fold_rvalue (x, flags);
2849}
2850
2851tree
2852cp_fully_fold (tree x)
2853{
2854 return cp_fully_fold (x, manifestly_const_eval: mce_unknown);
2855}
2856
2857/* Likewise, but also fold recursively, which cp_fully_fold doesn't perform
2858 in some cases. */
2859
2860tree
2861cp_fully_fold_init (tree x)
2862{
2863 if (processing_template_decl)
2864 return x;
2865 x = cp_fully_fold (x, manifestly_const_eval: mce_false);
2866 cp_fold_data data (ff_mce_false);
2867 cp_walk_tree (&x, cp_fold_r, &data, NULL);
2868 return x;
2869}
2870
2871/* c-common interface to cp_fold. If IN_INIT, this is in a static initializer
2872 and certain changes are made to the folding done. Or should be (FIXME). We
2873 never touch maybe_const, as it is only used for the C front-end
2874 C_MAYBE_CONST_EXPR. */
2875
2876tree
2877c_fully_fold (tree x, bool /*in_init*/, bool */*maybe_const*/, bool lval)
2878{
2879 return cp_fold_maybe_rvalue (x, rval: !lval);
2880}
2881
2882static GTY((deletable)) hash_map<tree, tree> *fold_caches[2];
2883
2884/* Subroutine of cp_fold. Returns which fold cache to use according
2885 to the given flags. We need multiple caches since the result of
2886 folding may depend on which flags are used. */
2887
2888static hash_map<tree, tree> *&
2889get_fold_cache (fold_flags_t flags)
2890{
2891 if (flags & ff_mce_false)
2892 return fold_caches[1];
2893 else
2894 return fold_caches[0];
2895}
2896
2897/* Dispose of the whole FOLD_CACHE. */
2898
2899void
2900clear_fold_cache (void)
2901{
2902 for (auto& fold_cache : fold_caches)
2903 if (fold_cache != NULL)
2904 fold_cache->empty ();
2905}
2906
2907/* This function tries to fold an expression X.
2908 To avoid combinatorial explosion, folding results are kept in fold_cache.
2909 If X is invalid, we don't fold at all.
2910 For performance reasons we don't cache expressions representing a
2911 declaration or constant.
2912 Function returns X or its folded variant. */
2913
2914static tree
2915cp_fold (tree x, fold_flags_t flags)
2916{
2917 tree op0, op1, op2, op3;
2918 tree org_x = x, r = NULL_TREE;
2919 enum tree_code code;
2920 location_t loc;
2921 bool rval_ops = true;
2922
2923 if (!x || x == error_mark_node)
2924 return x;
2925
2926 if (EXPR_P (x) && (!TREE_TYPE (x) || TREE_TYPE (x) == error_mark_node))
2927 return x;
2928
2929 /* Don't bother to cache DECLs or constants. */
2930 if (DECL_P (x) || CONSTANT_CLASS_P (x))
2931 return x;
2932
2933 auto& fold_cache = get_fold_cache (flags);
2934 if (fold_cache == NULL)
2935 fold_cache = hash_map<tree, tree>::create_ggc (size: 101);
2936
2937 if (tree *cached = fold_cache->get (k: x))
2938 {
2939 /* unshare_expr doesn't recurse into SAVE_EXPRs. If SAVE_EXPR's
2940 argument has been folded into a tree invariant, make sure it is
2941 unshared. See PR112727. */
2942 if (TREE_CODE (x) == SAVE_EXPR && *cached != x)
2943 return unshare_expr (*cached);
2944 return *cached;
2945 }
2946
2947 uid_sensitive_constexpr_evaluation_checker c;
2948
2949 code = TREE_CODE (x);
2950 switch (code)
2951 {
2952 case CLEANUP_POINT_EXPR:
2953 /* Strip CLEANUP_POINT_EXPR if the expression doesn't have side
2954 effects. */
2955 r = cp_fold_rvalue (TREE_OPERAND (x, 0), flags);
2956 if (!TREE_SIDE_EFFECTS (r))
2957 x = r;
2958 break;
2959
2960 case SIZEOF_EXPR:
2961 x = fold_sizeof_expr (x);
2962 break;
2963
2964 case VIEW_CONVERT_EXPR:
2965 rval_ops = false;
2966 /* FALLTHRU */
2967 case NON_LVALUE_EXPR:
2968 CASE_CONVERT:
2969
2970 if (VOID_TYPE_P (TREE_TYPE (x)))
2971 {
2972 /* This is just to make sure we don't end up with casts to
2973 void from error_mark_node. If we just return x, then
2974 cp_fold_r might fold the operand into error_mark_node and
2975 leave the conversion in the IR. STRIP_USELESS_TYPE_CONVERSION
2976 during gimplification doesn't like such casts.
2977 Don't create a new tree if op0 != TREE_OPERAND (x, 0), the
2978 folding of the operand should be in the caches and if in cp_fold_r
2979 it will modify it in place. */
2980 op0 = cp_fold (TREE_OPERAND (x, 0), flags);
2981 if (op0 == error_mark_node)
2982 x = error_mark_node;
2983 break;
2984 }
2985
2986 loc = EXPR_LOCATION (x);
2987 op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval: rval_ops, flags);
2988
2989 if (code == CONVERT_EXPR
2990 && SCALAR_TYPE_P (TREE_TYPE (x))
2991 && op0 != void_node)
2992 /* During parsing we used convert_to_*_nofold; re-convert now using the
2993 folding variants, since fold() doesn't do those transformations. */
2994 x = fold (convert (TREE_TYPE (x), op0));
2995 else if (op0 != TREE_OPERAND (x, 0))
2996 {
2997 if (op0 == error_mark_node)
2998 x = error_mark_node;
2999 else
3000 x = fold_build1_loc (loc, code, TREE_TYPE (x), op0);
3001 }
3002 else
3003 x = fold (x);
3004
3005 /* Conversion of an out-of-range value has implementation-defined
3006 behavior; the language considers it different from arithmetic
3007 overflow, which is undefined. */
3008 if (TREE_CODE (op0) == INTEGER_CST
3009 && TREE_OVERFLOW_P (x) && !TREE_OVERFLOW_P (op0))
3010 TREE_OVERFLOW (x) = false;
3011
3012 break;
3013
3014 case EXCESS_PRECISION_EXPR:
3015 op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval: rval_ops, flags);
3016 x = fold_convert_loc (EXPR_LOCATION (x), TREE_TYPE (x), op0);
3017 break;
3018
3019 case INDIRECT_REF:
3020 /* We don't need the decltype(auto) obfuscation anymore. */
3021 if (REF_PARENTHESIZED_P (x))
3022 {
3023 tree p = maybe_undo_parenthesized_ref (x);
3024 if (p != x)
3025 return cp_fold (x: p, flags);
3026 }
3027 goto unary;
3028
3029 case ADDR_EXPR:
3030 loc = EXPR_LOCATION (x);
3031 op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval: false, flags);
3032
3033 /* Cope with user tricks that amount to offsetof. */
3034 if (op0 != error_mark_node
3035 && !FUNC_OR_METHOD_TYPE_P (TREE_TYPE (op0)))
3036 {
3037 tree val = get_base_address (t: op0);
3038 if (val
3039 && INDIRECT_REF_P (val)
3040 && COMPLETE_TYPE_P (TREE_TYPE (val))
3041 && TREE_CONSTANT (TREE_OPERAND (val, 0)))
3042 {
3043 val = TREE_OPERAND (val, 0);
3044 STRIP_NOPS (val);
3045 val = maybe_constant_value (val);
3046 if (TREE_CODE (val) == INTEGER_CST)
3047 return fold_offsetof (op0, TREE_TYPE (x));
3048 }
3049 }
3050 goto finish_unary;
3051
3052 case REALPART_EXPR:
3053 case IMAGPART_EXPR:
3054 rval_ops = false;
3055 /* FALLTHRU */
3056 case CONJ_EXPR:
3057 case FIX_TRUNC_EXPR:
3058 case FLOAT_EXPR:
3059 case NEGATE_EXPR:
3060 case ABS_EXPR:
3061 case ABSU_EXPR:
3062 case BIT_NOT_EXPR:
3063 case TRUTH_NOT_EXPR:
3064 case FIXED_CONVERT_EXPR:
3065 unary:
3066
3067 loc = EXPR_LOCATION (x);
3068 op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval: rval_ops, flags);
3069
3070 finish_unary:
3071 if (op0 != TREE_OPERAND (x, 0))
3072 {
3073 if (op0 == error_mark_node)
3074 x = error_mark_node;
3075 else
3076 {
3077 x = fold_build1_loc (loc, code, TREE_TYPE (x), op0);
3078 if (code == INDIRECT_REF
3079 && (INDIRECT_REF_P (x) || TREE_CODE (x) == MEM_REF))
3080 {
3081 TREE_READONLY (x) = TREE_READONLY (org_x);
3082 TREE_SIDE_EFFECTS (x) = TREE_SIDE_EFFECTS (org_x);
3083 TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
3084 }
3085 }
3086 }
3087 else
3088 x = fold (x);
3089
3090 gcc_assert (TREE_CODE (x) != COND_EXPR
3091 || !VOID_TYPE_P (TREE_TYPE (TREE_OPERAND (x, 0))));
3092 break;
3093
3094 case UNARY_PLUS_EXPR:
3095 op0 = cp_fold_rvalue (TREE_OPERAND (x, 0), flags);
3096 if (op0 == error_mark_node)
3097 x = error_mark_node;
3098 else
3099 x = fold_convert (TREE_TYPE (x), op0);
3100 break;
3101
3102 case POSTDECREMENT_EXPR:
3103 case POSTINCREMENT_EXPR:
3104 case INIT_EXPR:
3105 case PREDECREMENT_EXPR:
3106 case PREINCREMENT_EXPR:
3107 case COMPOUND_EXPR:
3108 case MODIFY_EXPR:
3109 rval_ops = false;
3110 /* FALLTHRU */
3111 case POINTER_PLUS_EXPR:
3112 case PLUS_EXPR:
3113 case POINTER_DIFF_EXPR:
3114 case MINUS_EXPR:
3115 case MULT_EXPR:
3116 case TRUNC_DIV_EXPR:
3117 case CEIL_DIV_EXPR:
3118 case FLOOR_DIV_EXPR:
3119 case ROUND_DIV_EXPR:
3120 case TRUNC_MOD_EXPR:
3121 case CEIL_MOD_EXPR:
3122 case ROUND_MOD_EXPR:
3123 case RDIV_EXPR:
3124 case EXACT_DIV_EXPR:
3125 case MIN_EXPR:
3126 case MAX_EXPR:
3127 case LSHIFT_EXPR:
3128 case RSHIFT_EXPR:
3129 case LROTATE_EXPR:
3130 case RROTATE_EXPR:
3131 case BIT_AND_EXPR:
3132 case BIT_IOR_EXPR:
3133 case BIT_XOR_EXPR:
3134 case TRUTH_AND_EXPR:
3135 case TRUTH_ANDIF_EXPR:
3136 case TRUTH_OR_EXPR:
3137 case TRUTH_ORIF_EXPR:
3138 case TRUTH_XOR_EXPR:
3139 case LT_EXPR: case LE_EXPR:
3140 case GT_EXPR: case GE_EXPR:
3141 case EQ_EXPR: case NE_EXPR:
3142 case UNORDERED_EXPR: case ORDERED_EXPR:
3143 case UNLT_EXPR: case UNLE_EXPR:
3144 case UNGT_EXPR: case UNGE_EXPR:
3145 case UNEQ_EXPR: case LTGT_EXPR:
3146 case RANGE_EXPR: case COMPLEX_EXPR:
3147
3148 loc = EXPR_LOCATION (x);
3149 op0 = cp_fold_maybe_rvalue (TREE_OPERAND (x, 0), rval: rval_ops, flags);
3150 op1 = cp_fold_rvalue (TREE_OPERAND (x, 1), flags);
3151
3152 /* decltype(nullptr) has only one value, so optimize away all comparisons
3153 with that type right away, keeping them in the IL causes troubles for
3154 various optimizations. */
3155 if (COMPARISON_CLASS_P (org_x)
3156 && TREE_CODE (TREE_TYPE (op0)) == NULLPTR_TYPE
3157 && TREE_CODE (TREE_TYPE (op1)) == NULLPTR_TYPE)
3158 {
3159 switch (code)
3160 {
3161 case EQ_EXPR:
3162 x = constant_boolean_node (true, TREE_TYPE (x));
3163 break;
3164 case NE_EXPR:
3165 x = constant_boolean_node (false, TREE_TYPE (x));
3166 break;
3167 default:
3168 gcc_unreachable ();
3169 }
3170 return omit_two_operands_loc (loc, TREE_TYPE (x), x,
3171 op0, op1);
3172 }
3173
3174 if (op0 != TREE_OPERAND (x, 0) || op1 != TREE_OPERAND (x, 1))
3175 {
3176 if (op0 == error_mark_node || op1 == error_mark_node)
3177 x = error_mark_node;
3178 else
3179 x = fold_build2_loc (loc, code, TREE_TYPE (x), op0, op1);
3180 }
3181 else
3182 x = fold (x);
3183
3184 /* This is only needed for -Wnonnull-compare and only if
3185 TREE_NO_WARNING (org_x), but to avoid that option affecting code
3186 generation, we do it always. */
3187 if (COMPARISON_CLASS_P (org_x))
3188 {
3189 if (x == error_mark_node || TREE_CODE (x) == INTEGER_CST)
3190 ;
3191 else if (COMPARISON_CLASS_P (x))
3192 {
3193 if (warn_nonnull_compare
3194 && warning_suppressed_p (org_x, OPT_Wnonnull_compare))
3195 suppress_warning (x, OPT_Wnonnull_compare);
3196 }
3197 /* Otherwise give up on optimizing these, let GIMPLE folders
3198 optimize those later on. */
3199 else if (op0 != TREE_OPERAND (org_x, 0)
3200 || op1 != TREE_OPERAND (org_x, 1))
3201 {
3202 x = build2_loc (loc, code, TREE_TYPE (org_x), arg0: op0, arg1: op1);
3203 if (warn_nonnull_compare
3204 && warning_suppressed_p (org_x, OPT_Wnonnull_compare))
3205 suppress_warning (x, OPT_Wnonnull_compare);
3206 }
3207 else
3208 x = org_x;
3209 }
3210
3211 break;
3212
3213 case VEC_COND_EXPR:
3214 case COND_EXPR:
3215 loc = EXPR_LOCATION (x);
3216 op0 = cp_fold_rvalue (TREE_OPERAND (x, 0), flags);
3217 op1 = cp_fold (TREE_OPERAND (x, 1), flags);
3218 op2 = cp_fold (TREE_OPERAND (x, 2), flags);
3219
3220 if (TREE_CODE (TREE_TYPE (x)) == BOOLEAN_TYPE)
3221 {
3222 warning_sentinel s (warn_int_in_bool_context);
3223 if (!VOID_TYPE_P (TREE_TYPE (op1)))
3224 op1 = cp_truthvalue_conversion (op1, tf_warning_or_error);
3225 if (!VOID_TYPE_P (TREE_TYPE (op2)))
3226 op2 = cp_truthvalue_conversion (op2, tf_warning_or_error);
3227 }
3228 else if (VOID_TYPE_P (TREE_TYPE (x)))
3229 {
3230 if (TREE_CODE (op0) == INTEGER_CST)
3231 {
3232 /* If the condition is constant, fold can fold away
3233 the COND_EXPR. If some statement-level uses of COND_EXPR
3234 have one of the branches NULL, avoid folding crash. */
3235 if (!op1)
3236 op1 = build_empty_stmt (loc);
3237 if (!op2)
3238 op2 = build_empty_stmt (loc);
3239 }
3240 else
3241 {
3242 /* Otherwise, don't bother folding a void condition, since
3243 it can't produce a constant value. */
3244 if (op0 != TREE_OPERAND (x, 0)
3245 || op1 != TREE_OPERAND (x, 1)
3246 || op2 != TREE_OPERAND (x, 2))
3247 x = build3_loc (loc, code, TREE_TYPE (x), arg0: op0, arg1: op1, arg2: op2);
3248 break;
3249 }
3250 }
3251
3252 if (op0 != TREE_OPERAND (x, 0)
3253 || op1 != TREE_OPERAND (x, 1)
3254 || op2 != TREE_OPERAND (x, 2))
3255 {
3256 if (op0 == error_mark_node
3257 || op1 == error_mark_node
3258 || op2 == error_mark_node)
3259 x = error_mark_node;
3260 else
3261 x = fold_build3_loc (loc, code, TREE_TYPE (x), op0, op1, op2);
3262 }
3263 else
3264 x = fold (x);
3265
3266 /* A COND_EXPR might have incompatible types in branches if one or both
3267 arms are bitfields. If folding exposed such a branch, fix it up. */
3268 if (TREE_CODE (x) != code
3269 && x != error_mark_node
3270 && !useless_type_conversion_p (TREE_TYPE (org_x), TREE_TYPE (x)))
3271 x = fold_convert (TREE_TYPE (org_x), x);
3272
3273 break;
3274
3275 case CALL_EXPR:
3276 {
3277 tree callee = get_callee_fndecl (x);
3278
3279 /* "Inline" calls to std::move/forward and other cast-like functions
3280 by simply folding them into a corresponding cast to their return
3281 type. This is cheaper than relying on the middle end to do so, and
3282 also means we avoid generating useless debug info for them at all.
3283
3284 At this point the argument has already been converted into a
3285 reference, so it suffices to use a NOP_EXPR to express the
3286 cast. */
3287 if ((OPTION_SET_P (flag_fold_simple_inlines)
3288 ? flag_fold_simple_inlines
3289 : !flag_no_inline)
3290 && call_expr_nargs (x) == 1
3291 && decl_in_std_namespace_p (callee)
3292 && DECL_NAME (callee) != NULL_TREE
3293 && (id_equal (DECL_NAME (callee), str: "move")
3294 || id_equal (DECL_NAME (callee), str: "forward")
3295 || id_equal (DECL_NAME (callee), str: "addressof")
3296 /* This addressof equivalent is used heavily in libstdc++. */
3297 || id_equal (DECL_NAME (callee), str: "__addressof")
3298 || id_equal (DECL_NAME (callee), str: "as_const")))
3299 {
3300 r = CALL_EXPR_ARG (x, 0);
3301 /* Check that the return and argument types are sane before
3302 folding. */
3303 if (INDIRECT_TYPE_P (TREE_TYPE (x))
3304 && INDIRECT_TYPE_P (TREE_TYPE (r)))
3305 {
3306 if (!same_type_p (TREE_TYPE (x), TREE_TYPE (r)))
3307 r = build_nop (TREE_TYPE (x), r);
3308 x = cp_fold (x: r, flags);
3309 break;
3310 }
3311 }
3312
3313 int sv = optimize, nw = sv;
3314
3315 /* Some built-in function calls will be evaluated at compile-time in
3316 fold (). Set optimize to 1 when folding __builtin_constant_p inside
3317 a constexpr function so that fold_builtin_1 doesn't fold it to 0. */
3318 if (callee && fndecl_built_in_p (node: callee) && !optimize
3319 && DECL_IS_BUILTIN_CONSTANT_P (callee)
3320 && current_function_decl
3321 && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
3322 nw = 1;
3323
3324 if (callee && fndecl_built_in_p (node: callee, klass: BUILT_IN_FRONTEND))
3325 {
3326 iloc_sentinel ils (EXPR_LOCATION (x));
3327 switch (DECL_FE_FUNCTION_CODE (decl: callee))
3328 {
3329 case CP_BUILT_IN_IS_CONSTANT_EVALUATED:
3330 /* Defer folding __builtin_is_constant_evaluated unless
3331 we know this isn't a manifestly constant-evaluated
3332 context. */
3333 if (flags & ff_mce_false)
3334 x = boolean_false_node;
3335 break;
3336 case CP_BUILT_IN_SOURCE_LOCATION:
3337 x = fold_builtin_source_location (x);
3338 break;
3339 case CP_BUILT_IN_IS_CORRESPONDING_MEMBER:
3340 x = fold_builtin_is_corresponding_member
3341 (EXPR_LOCATION (x), call_expr_nargs (x),
3342 &CALL_EXPR_ARG (x, 0));
3343 break;
3344 case CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS:
3345 x = fold_builtin_is_pointer_inverconvertible_with_class
3346 (EXPR_LOCATION (x), call_expr_nargs (x),
3347 &CALL_EXPR_ARG (x, 0));
3348 break;
3349 default:
3350 break;
3351 }
3352 break;
3353 }
3354
3355 if (callee
3356 && fndecl_built_in_p (node: callee, name: CP_BUILT_IN_SOURCE_LOCATION,
3357 klass: BUILT_IN_FRONTEND))
3358 {
3359 x = fold_builtin_source_location (x);
3360 break;
3361 }
3362
3363 bool changed = false;
3364 int m = call_expr_nargs (x);
3365 for (int i = 0; i < m; i++)
3366 {
3367 r = cp_fold (CALL_EXPR_ARG (x, i), flags);
3368 if (r != CALL_EXPR_ARG (x, i))
3369 {
3370 if (r == error_mark_node)
3371 {
3372 x = error_mark_node;
3373 break;
3374 }
3375 if (!changed)
3376 x = copy_node (x);
3377 CALL_EXPR_ARG (x, i) = r;
3378 changed = true;
3379 }
3380 }
3381 if (x == error_mark_node)
3382 break;
3383
3384 optimize = nw;
3385 r = fold (x);
3386 optimize = sv;
3387
3388 if (TREE_CODE (r) != CALL_EXPR)
3389 {
3390 x = cp_fold (x: r, flags);
3391 break;
3392 }
3393
3394 optimize = nw;
3395
3396 /* Invoke maybe_constant_value for functions declared
3397 constexpr and not called with AGGR_INIT_EXPRs.
3398 TODO:
3399 Do constexpr expansion of expressions where the call itself is not
3400 constant, but the call followed by an INDIRECT_REF is. */
3401 if (callee && DECL_DECLARED_CONSTEXPR_P (callee)
3402 && !flag_no_inline)
3403 {
3404 mce_value manifestly_const_eval = mce_unknown;
3405 if (flags & ff_mce_false)
3406 /* Allow folding __builtin_is_constant_evaluated to false during
3407 constexpr evaluation of this call. */
3408 manifestly_const_eval = mce_false;
3409 r = maybe_constant_value (x, /*decl=*/NULL_TREE,
3410 manifestly_const_eval);
3411 }
3412 optimize = sv;
3413
3414 if (TREE_CODE (r) != CALL_EXPR)
3415 {
3416 if (DECL_CONSTRUCTOR_P (callee))
3417 {
3418 loc = EXPR_LOCATION (x);
3419 tree a = CALL_EXPR_ARG (x, 0);
3420 bool return_this = targetm.cxx.cdtor_returns_this ();
3421 if (return_this)
3422 a = cp_save_expr (a);
3423 tree s = build_fold_indirect_ref_loc (loc, a);
3424 r = cp_build_init_expr (t: s, i: r);
3425 if (return_this)
3426 r = build2_loc (loc, code: COMPOUND_EXPR, TREE_TYPE (x), arg0: r,
3427 arg1: fold_convert_loc (loc, TREE_TYPE (x), a));
3428 }
3429 x = r;
3430 break;
3431 }
3432
3433 break;
3434 }
3435
3436 case CONSTRUCTOR:
3437 {
3438 unsigned i;
3439 constructor_elt *p;
3440 vec<constructor_elt, va_gc> *elts = CONSTRUCTOR_ELTS (x);
3441 vec<constructor_elt, va_gc> *nelts = NULL;
3442 FOR_EACH_VEC_SAFE_ELT (elts, i, p)
3443 {
3444 tree op = cp_fold (x: p->value, flags);
3445 if (op != p->value)
3446 {
3447 if (op == error_mark_node)
3448 {
3449 x = error_mark_node;
3450 vec_free (v&: nelts);
3451 break;
3452 }
3453 if (nelts == NULL)
3454 nelts = elts->copy ();
3455 (*nelts)[i].value = op;
3456 }
3457 }
3458 if (nelts)
3459 {
3460 x = build_constructor (TREE_TYPE (x), nelts);
3461 CONSTRUCTOR_PLACEHOLDER_BOUNDARY (x)
3462 = CONSTRUCTOR_PLACEHOLDER_BOUNDARY (org_x);
3463 CONSTRUCTOR_MUTABLE_POISON (x)
3464 = CONSTRUCTOR_MUTABLE_POISON (org_x);
3465 }
3466 if (VECTOR_TYPE_P (TREE_TYPE (x)))
3467 x = fold (x);
3468 break;
3469 }
3470 case TREE_VEC:
3471 {
3472 bool changed = false;
3473 int n = TREE_VEC_LENGTH (x);
3474
3475 for (int i = 0; i < n; i++)
3476 {
3477 tree op = cp_fold (TREE_VEC_ELT (x, i), flags);
3478 if (op != TREE_VEC_ELT (x, i))
3479 {
3480 if (!changed)
3481 x = copy_node (x);
3482 TREE_VEC_ELT (x, i) = op;
3483 changed = true;
3484 }
3485 }
3486 }
3487
3488 break;
3489
3490 case ARRAY_REF:
3491 case ARRAY_RANGE_REF:
3492
3493 loc = EXPR_LOCATION (x);
3494 op0 = cp_fold (TREE_OPERAND (x, 0), flags);
3495 op1 = cp_fold (TREE_OPERAND (x, 1), flags);
3496 op2 = cp_fold (TREE_OPERAND (x, 2), flags);
3497 op3 = cp_fold (TREE_OPERAND (x, 3), flags);
3498
3499 if (op0 != TREE_OPERAND (x, 0)
3500 || op1 != TREE_OPERAND (x, 1)
3501 || op2 != TREE_OPERAND (x, 2)
3502 || op3 != TREE_OPERAND (x, 3))
3503 {
3504 if (op0 == error_mark_node
3505 || op1 == error_mark_node
3506 || op2 == error_mark_node
3507 || op3 == error_mark_node)
3508 x = error_mark_node;
3509 else
3510 {
3511 x = build4_loc (loc, code, TREE_TYPE (x), arg0: op0, arg1: op1, arg2: op2, arg3: op3);
3512 TREE_READONLY (x) = TREE_READONLY (org_x);
3513 TREE_SIDE_EFFECTS (x) = TREE_SIDE_EFFECTS (org_x);
3514 TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
3515 }
3516 }
3517
3518 x = fold (x);
3519 break;
3520
3521 case SAVE_EXPR:
3522 /* A SAVE_EXPR might contain e.g. (0 * i) + (0 * j), which, after
3523 folding, evaluates to an invariant. In that case no need to wrap
3524 this folded tree with a SAVE_EXPR. */
3525 r = cp_fold (TREE_OPERAND (x, 0), flags);
3526 if (tree_invariant_p (r))
3527 x = r;
3528 break;
3529
3530 case REQUIRES_EXPR:
3531 x = evaluate_requires_expr (x);
3532 break;
3533
3534 default:
3535 return org_x;
3536 }
3537
3538 if (EXPR_P (x) && TREE_CODE (x) == code)
3539 {
3540 TREE_THIS_VOLATILE (x) = TREE_THIS_VOLATILE (org_x);
3541 copy_warning (x, org_x);
3542 }
3543
3544 if (!c.evaluation_restricted_p ())
3545 {
3546 fold_cache->put (k: org_x, v: x);
3547 /* Prevent that we try to fold an already folded result again. */
3548 if (x != org_x)
3549 fold_cache->put (k: x, v: x);
3550 }
3551
3552 return x;
3553}
3554
3555/* Look up "hot", "cold", "likely" or "unlikely" in attribute list LIST. */
3556
3557tree
3558lookup_hotness_attribute (tree list)
3559{
3560 for (; list; list = TREE_CHAIN (list))
3561 {
3562 tree name = get_attribute_name (list);
3563 if ((is_attribute_p (attr_name: "hot", ident: name)
3564 || is_attribute_p (attr_name: "cold", ident: name)
3565 || is_attribute_p (attr_name: "likely", ident: name)
3566 || is_attribute_p (attr_name: "unlikely", ident: name))
3567 && is_attribute_namespace_p (attr_ns: "", attr: list))
3568 break;
3569 }
3570 return list;
3571}
3572
3573/* Remove "hot", "cold", "likely" and "unlikely" attributes from LIST. */
3574
3575static tree
3576remove_hotness_attribute (tree list)
3577{
3578 for (tree *p = &list; *p; )
3579 {
3580 tree l = *p;
3581 tree name = get_attribute_name (l);
3582 if ((is_attribute_p (attr_name: "hot", ident: name)
3583 || is_attribute_p (attr_name: "cold", ident: name)
3584 || is_attribute_p (attr_name: "likely", ident: name)
3585 || is_attribute_p (attr_name: "unlikely", ident: name))
3586 && is_attribute_namespace_p (attr_ns: "", attr: l))
3587 {
3588 *p = TREE_CHAIN (l);
3589 continue;
3590 }
3591 p = &TREE_CHAIN (l);
3592 }
3593 return list;
3594}
3595
3596/* If [[likely]] or [[unlikely]] appear on this statement, turn it into a
3597 PREDICT_EXPR. */
3598
3599tree
3600process_stmt_hotness_attribute (tree std_attrs, location_t attrs_loc)
3601{
3602 if (std_attrs == error_mark_node)
3603 return std_attrs;
3604 if (tree attr = lookup_hotness_attribute (list: std_attrs))
3605 {
3606 tree name = get_attribute_name (attr);
3607 bool hot = (is_attribute_p (attr_name: "hot", ident: name)
3608 || is_attribute_p (attr_name: "likely", ident: name));
3609 tree pred = build_predict_expr (hot ? PRED_HOT_LABEL : PRED_COLD_LABEL,
3610 hot ? TAKEN : NOT_TAKEN);
3611 SET_EXPR_LOCATION (pred, attrs_loc);
3612 add_stmt (pred);
3613 if (tree other = lookup_hotness_attribute (TREE_CHAIN (attr)))
3614 warning (OPT_Wattributes, "ignoring attribute %qE after earlier %qE",
3615 get_attribute_name (other), name);
3616 std_attrs = remove_hotness_attribute (list: std_attrs);
3617 }
3618 return std_attrs;
3619}
3620
3621/* Build IFN_ASSUME internal call for assume condition ARG. */
3622
3623tree
3624build_assume_call (location_t loc, tree arg)
3625{
3626 if (!processing_template_decl)
3627 arg = fold_build_cleanup_point_expr (TREE_TYPE (arg), expr: arg);
3628 return build_call_expr_internal_loc (loc, IFN_ASSUME, void_type_node,
3629 1, arg);
3630}
3631
3632/* If [[assume (cond)]] appears on this statement, handle it. */
3633
3634tree
3635process_stmt_assume_attribute (tree std_attrs, tree statement,
3636 location_t attrs_loc)
3637{
3638 if (std_attrs == error_mark_node)
3639 return std_attrs;
3640 tree attr = lookup_attribute (attr_ns: "gnu", attr_name: "assume", list: std_attrs);
3641 if (!attr)
3642 return std_attrs;
3643 /* The next token after the assume attribute is not ';'. */
3644 if (statement)
3645 {
3646 warning_at (attrs_loc, OPT_Wattributes,
3647 "%<assume%> attribute not followed by %<;%>");
3648 attr = NULL_TREE;
3649 }
3650 for (; attr; attr = lookup_attribute (attr_ns: "gnu", attr_name: "assume", TREE_CHAIN (attr)))
3651 {
3652 tree args = TREE_VALUE (attr);
3653 if (args && PACK_EXPANSION_P (args))
3654 {
3655 auto_diagnostic_group d;
3656 error_at (attrs_loc, "pack expansion of %qE attribute",
3657 get_attribute_name (attr));
3658 if (cxx_dialect >= cxx17)
3659 inform (attrs_loc, "use fold expression in the attribute "
3660 "argument instead");
3661 continue;
3662 }
3663 int nargs = list_length (args);
3664 if (nargs != 1)
3665 {
3666 auto_diagnostic_group d;
3667 error_at (attrs_loc, "wrong number of arguments specified for "
3668 "%qE attribute", get_attribute_name (attr));
3669 inform (attrs_loc, "expected %i, found %i", 1, nargs);
3670 }
3671 else
3672 {
3673 tree arg = TREE_VALUE (args);
3674 if (!type_dependent_expression_p (arg))
3675 arg = contextual_conv_bool (arg, tf_warning_or_error);
3676 if (error_operand_p (t: arg))
3677 continue;
3678 finish_expr_stmt (build_assume_call (loc: attrs_loc, arg));
3679 }
3680 }
3681 return remove_attribute ("gnu", "assume", std_attrs);
3682}
3683
3684/* Return the type std::source_location::__impl after performing
3685 verification on it. */
3686
3687tree
3688get_source_location_impl_type ()
3689{
3690 tree name = get_identifier ("source_location");
3691 tree decl = lookup_qualified_name (std_node, name);
3692 if (TREE_CODE (decl) != TYPE_DECL)
3693 {
3694 auto_diagnostic_group d;
3695 if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
3696 qualified_name_lookup_error (std_node, name, decl, input_location);
3697 else
3698 error ("%qD is not a type", decl);
3699 return error_mark_node;
3700 }
3701 name = get_identifier ("__impl");
3702 tree type = TREE_TYPE (decl);
3703 decl = lookup_qualified_name (scope: type, name);
3704 if (TREE_CODE (decl) != TYPE_DECL)
3705 {
3706 auto_diagnostic_group d;
3707 if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
3708 qualified_name_lookup_error (type, name, decl, input_location);
3709 else
3710 error ("%qD is not a type", decl);
3711 return error_mark_node;
3712 }
3713 type = TREE_TYPE (decl);
3714 if (TREE_CODE (type) != RECORD_TYPE)
3715 {
3716 error ("%qD is not a class type", decl);
3717 return error_mark_node;
3718 }
3719
3720 int cnt = 0;
3721 for (tree field = TYPE_FIELDS (type);
3722 (field = next_aggregate_field (field)) != NULL_TREE;
3723 field = DECL_CHAIN (field))
3724 {
3725 if (DECL_NAME (field) != NULL_TREE)
3726 {
3727 const char *n = IDENTIFIER_POINTER (DECL_NAME (field));
3728 if (strcmp (s1: n, s2: "_M_file_name") == 0
3729 || strcmp (s1: n, s2: "_M_function_name") == 0)
3730 {
3731 if (TREE_TYPE (field) != const_string_type_node)
3732 {
3733 error ("%qD does not have %<const char *%> type", field);
3734 return error_mark_node;
3735 }
3736 cnt++;
3737 continue;
3738 }
3739 else if (strcmp (s1: n, s2: "_M_line") == 0 || strcmp (s1: n, s2: "_M_column") == 0)
3740 {
3741 if (TREE_CODE (TREE_TYPE (field)) != INTEGER_TYPE)
3742 {
3743 error ("%qD does not have integral type", field);
3744 return error_mark_node;
3745 }
3746 cnt++;
3747 continue;
3748 }
3749 }
3750 cnt = 0;
3751 break;
3752 }
3753 if (cnt != 4)
3754 {
3755 error ("%<std::source_location::__impl%> does not contain only "
3756 "non-static data members %<_M_file_name%>, "
3757 "%<_M_function_name%>, %<_M_line%> and %<_M_column%>");
3758 return error_mark_node;
3759 }
3760 return build_qualified_type (type, TYPE_QUAL_CONST);
3761}
3762
3763/* Type for source_location_table hash_set. */
3764struct GTY((for_user)) source_location_table_entry {
3765 location_t loc;
3766 unsigned uid;
3767 tree var;
3768};
3769
3770/* Traits class for function start hash maps below. */
3771
3772struct source_location_table_entry_hash
3773 : ggc_remove <source_location_table_entry>
3774{
3775 typedef source_location_table_entry value_type;
3776 typedef source_location_table_entry compare_type;
3777
3778 static hashval_t
3779 hash (const source_location_table_entry &ref)
3780 {
3781 inchash::hash hstate (0);
3782 hstate.add_int (v: ref.loc);
3783 hstate.add_int (v: ref.uid);
3784 return hstate.end ();
3785 }
3786
3787 static bool
3788 equal (const source_location_table_entry &ref1,
3789 const source_location_table_entry &ref2)
3790 {
3791 return ref1.loc == ref2.loc && ref1.uid == ref2.uid;
3792 }
3793
3794 static void
3795 mark_deleted (source_location_table_entry &ref)
3796 {
3797 ref.loc = UNKNOWN_LOCATION;
3798 ref.uid = -1U;
3799 ref.var = NULL_TREE;
3800 }
3801
3802 static const bool empty_zero_p = true;
3803
3804 static void
3805 mark_empty (source_location_table_entry &ref)
3806 {
3807 ref.loc = UNKNOWN_LOCATION;
3808 ref.uid = 0;
3809 ref.var = NULL_TREE;
3810 }
3811
3812 static bool
3813 is_deleted (const source_location_table_entry &ref)
3814 {
3815 return (ref.loc == UNKNOWN_LOCATION
3816 && ref.uid == -1U
3817 && ref.var == NULL_TREE);
3818 }
3819
3820 static bool
3821 is_empty (const source_location_table_entry &ref)
3822 {
3823 return (ref.loc == UNKNOWN_LOCATION
3824 && ref.uid == 0
3825 && ref.var == NULL_TREE);
3826 }
3827
3828 static void
3829 pch_nx (source_location_table_entry &p)
3830 {
3831 extern void gt_pch_nx (source_location_table_entry &);
3832 gt_pch_nx (p);
3833 }
3834
3835 static void
3836 pch_nx (source_location_table_entry &p, gt_pointer_operator op, void *cookie)
3837 {
3838 extern void gt_pch_nx (source_location_table_entry *, gt_pointer_operator,
3839 void *);
3840 gt_pch_nx (&p, op, cookie);
3841 }
3842};
3843
3844static GTY(()) hash_table <source_location_table_entry_hash>
3845 *source_location_table;
3846static GTY(()) unsigned int source_location_id;
3847
3848/* Fold the __builtin_source_location () call T. */
3849
3850tree
3851fold_builtin_source_location (const_tree t)
3852{
3853 gcc_assert (TREE_CODE (t) == CALL_EXPR);
3854 /* TREE_TYPE (t) is const std::source_location::__impl* */
3855 tree source_location_impl = TREE_TYPE (TREE_TYPE (t));
3856 if (source_location_impl == error_mark_node)
3857 return build_zero_cst (const_ptr_type_node);
3858 gcc_assert (CLASS_TYPE_P (source_location_impl)
3859 && id_equal (TYPE_IDENTIFIER (source_location_impl), "__impl"));
3860
3861 location_t loc = EXPR_LOCATION (t);
3862 if (source_location_table == NULL)
3863 source_location_table
3864 = hash_table <source_location_table_entry_hash>::create_ggc (n: 64);
3865 const line_map_ordinary *map;
3866 source_location_table_entry entry;
3867 entry.loc
3868 = linemap_resolve_location (line_table, loc, lrk: LRK_MACRO_EXPANSION_POINT,
3869 loc_map: &map);
3870 entry.uid = current_function_decl ? DECL_UID (current_function_decl) : -1;
3871 entry.var = error_mark_node;
3872 source_location_table_entry *entryp
3873 = source_location_table->find_slot (value: entry, insert: INSERT);
3874 tree var;
3875 if (entryp->var)
3876 var = entryp->var;
3877 else
3878 {
3879 char tmp_name[32];
3880 ASM_GENERATE_INTERNAL_LABEL (tmp_name, "Lsrc_loc", source_location_id++);
3881 var = build_decl (loc, VAR_DECL, get_identifier (tmp_name),
3882 source_location_impl);
3883 TREE_STATIC (var) = 1;
3884 TREE_PUBLIC (var) = 0;
3885 DECL_ARTIFICIAL (var) = 1;
3886 DECL_IGNORED_P (var) = 1;
3887 DECL_EXTERNAL (var) = 0;
3888 DECL_DECLARED_CONSTEXPR_P (var) = 1;
3889 DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (var) = 1;
3890 layout_decl (var, 0);
3891
3892 vec<constructor_elt, va_gc> *v = NULL;
3893 vec_alloc (v, nelems: 4);
3894 for (tree field = TYPE_FIELDS (source_location_impl);
3895 (field = next_aggregate_field (field)) != NULL_TREE;
3896 field = DECL_CHAIN (field))
3897 {
3898 const char *n = IDENTIFIER_POINTER (DECL_NAME (field));
3899 tree val = NULL_TREE;
3900 if (strcmp (s1: n, s2: "_M_file_name") == 0)
3901 {
3902 if (const char *fname = LOCATION_FILE (loc))
3903 {
3904 fname = remap_macro_filename (fname);
3905 val = build_string_literal (p: fname);
3906 }
3907 else
3908 val = build_string_literal (p: "");
3909 }
3910 else if (strcmp (s1: n, s2: "_M_function_name") == 0)
3911 {
3912 const char *name = "";
3913
3914 if (current_function_decl)
3915 name = cxx_printable_name (current_function_decl, 2);
3916
3917 val = build_string_literal (p: name);
3918 }
3919 else if (strcmp (s1: n, s2: "_M_line") == 0)
3920 val = build_int_cst (TREE_TYPE (field), LOCATION_LINE (loc));
3921 else if (strcmp (s1: n, s2: "_M_column") == 0)
3922 val = build_int_cst (TREE_TYPE (field), LOCATION_COLUMN (loc));
3923 else
3924 gcc_unreachable ();
3925 CONSTRUCTOR_APPEND_ELT (v, field, val);
3926 }
3927
3928 tree ctor = build_constructor (source_location_impl, v);
3929 TREE_CONSTANT (ctor) = 1;
3930 TREE_STATIC (ctor) = 1;
3931 DECL_INITIAL (var) = ctor;
3932 varpool_node::finalize_decl (decl: var);
3933 *entryp = entry;
3934 entryp->var = var;
3935 }
3936
3937 return build_fold_addr_expr_with_type_loc (loc, var, TREE_TYPE (t));
3938}
3939
3940#include "gt-cp-cp-gimplify.h"
3941

source code of gcc/cp/cp-gimplify.cc