Branch data Line data Source code
1 : : /* Convert language-specific tree expression to rtl instructions,
2 : : for GNU compiler.
3 : : Copyright (C) 1988-2025 Free Software Foundation, Inc.
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify
8 : : it under the terms of the GNU General Public License as published by
9 : : the Free Software Foundation; either version 3, or (at your option)
10 : : any later version.
11 : :
12 : : GCC is distributed in the hope that it will be useful,
13 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : : GNU General Public License for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with GCC; see the file COPYING3. If not see
19 : : <http://www.gnu.org/licenses/>. */
20 : :
21 : :
22 : : #include "config.h"
23 : : #include "system.h"
24 : : #include "coretypes.h"
25 : : #include "cp-tree.h"
26 : :
27 : : /* Expand C++-specific constants. Currently, this means PTRMEM_CST. */
28 : :
29 : : tree
30 : 51684378 : cplus_expand_constant (tree cst)
31 : : {
32 : 51684378 : switch (TREE_CODE (cst))
33 : : {
34 : 37281 : case PTRMEM_CST:
35 : 37281 : {
36 : 37281 : tree type = TREE_TYPE (cst);
37 : 37281 : tree member;
38 : :
39 : : /* Find the member. */
40 : 37281 : member = PTRMEM_CST_MEMBER (cst);
41 : :
42 : : /* We can't lower this until the class is complete. */
43 : 37281 : if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
44 : : return cst;
45 : :
46 : 37248 : if (TREE_CODE (member) == FIELD_DECL)
47 : : {
48 : : /* Find the offset for the field. */
49 : 3722 : cst = byte_position (member);
50 : 7570 : while (!same_type_p (DECL_CONTEXT (member),
51 : : TYPE_PTRMEM_CLASS_TYPE (type)))
52 : : {
53 : : /* The MEMBER must have been nestled within an
54 : : anonymous aggregate contained in TYPE. Find the
55 : : anonymous aggregate. */
56 : 126 : member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
57 : 126 : DECL_CONTEXT (member));
58 : 126 : cst = size_binop (PLUS_EXPR, cst, byte_position (member));
59 : : }
60 : 3722 : cst = fold (build_nop (type, cst));
61 : : }
62 : : else
63 : : {
64 : 33526 : tree delta;
65 : 33526 : tree pfn;
66 : :
67 : 33526 : expand_ptrmemfunc_cst (cst, &delta, &pfn);
68 : 33526 : cst = build_ptrmemfunc1 (type, delta, pfn);
69 : : }
70 : : }
71 : : break;
72 : :
73 : : case CONSTRUCTOR:
74 : : {
75 : : constructor_elt *elt;
76 : : unsigned HOST_WIDE_INT idx;
77 : 37618528 : FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt)
78 : 33258351 : elt->value = cplus_expand_constant (elt->value);
79 : : }
80 : :
81 : : default:
82 : : /* There's nothing to do. */
83 : : break;
84 : : }
85 : :
86 : : return cst;
87 : : }
88 : :
89 : : /* We've seen an actual use of EXPR. Possibly replace an outer variable
90 : : reference inside with its constant value or a lambda capture. */
91 : :
92 : : tree
93 : 4900189936 : mark_use (tree expr, bool rvalue_p, bool read_p,
94 : : location_t loc /* = UNKNOWN_LOCATION */,
95 : : bool reject_builtin /* = true */)
96 : : {
97 : : #define RECUR(t) mark_use ((t), rvalue_p, read_p, loc, reject_builtin)
98 : :
99 : 4900189936 : if (expr == NULL_TREE || error_operand_p (expr))
100 : : return expr;
101 : :
102 : 4900185207 : if (reject_builtin && reject_gcc_builtin (expr, loc))
103 : 66 : return error_mark_node;
104 : :
105 : 4900185141 : if (TREE_TYPE (expr) && VOID_TYPE_P (TREE_TYPE (expr)))
106 : : read_p = false;
107 : :
108 : 4815556423 : if (read_p)
109 : 4752515173 : mark_exp_read (expr);
110 : :
111 : 4900185141 : tree oexpr = expr;
112 : 4900185141 : bool recurse_op[3] = { false, false, false };
113 : 4900185141 : switch (TREE_CODE (expr))
114 : : {
115 : 1238489622 : case VAR_DECL:
116 : 1238489622 : case PARM_DECL:
117 : 1238489622 : if (rvalue_p && is_normal_capture_proxy (expr))
118 : : {
119 : : /* Look through capture by copy. */
120 : 6428405 : tree cap = DECL_CAPTURED_VARIABLE (expr);
121 : 6428405 : if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr))
122 : 6428405 : && decl_constant_var_p (cap))
123 : : {
124 : 162 : tree val = RECUR (cap);
125 : 162 : if (!is_capture_proxy (val))
126 : : {
127 : 120 : tree l = current_lambda_expr ();
128 : 120 : LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
129 : : }
130 : 162 : return val;
131 : : }
132 : : }
133 : 1238489460 : if (outer_automatic_var_p (expr)
134 : 1238489460 : && decl_constant_var_p (expr))
135 : : {
136 : 86714 : if (rvalue_p)
137 : : {
138 : 86705 : tree t = maybe_constant_value (expr);
139 : 86705 : if (TREE_CONSTANT (t))
140 : : {
141 : : expr = t;
142 : 4493312821 : break;
143 : : }
144 : : }
145 : 72 : iloc_sentinel l (loc);
146 : 72 : expr = process_outer_var_ref (expr, tf_warning_or_error, true);
147 : 72 : if (!(TREE_TYPE (oexpr)
148 : 72 : && TYPE_REF_P (TREE_TYPE (oexpr))))
149 : 54 : expr = convert_from_reference (expr);
150 : 72 : }
151 : : break;
152 : 114499351 : case COMPONENT_REF:
153 : 114499351 : recurse_op[0] = true;
154 : 114499351 : break;
155 : 6246183 : case COMPOUND_EXPR:
156 : 6246183 : recurse_op[1] = true;
157 : 6246183 : break;
158 : 13675438 : case COND_EXPR:
159 : 13675438 : recurse_op[2] = true;
160 : 13675438 : if (TREE_OPERAND (expr, 1))
161 : 13675399 : recurse_op[1] = true;
162 : : break;
163 : 255344558 : case INDIRECT_REF:
164 : 255344558 : if (REFERENCE_REF_P (expr))
165 : : {
166 : : /* Try to look through the reference. */
167 : 134882071 : tree ref = TREE_OPERAND (expr, 0);
168 : 134882071 : if (rvalue_p && is_normal_capture_proxy (ref))
169 : : {
170 : : /* Look through capture by reference. */
171 : 1208654 : tree cap = DECL_CAPTURED_VARIABLE (ref);
172 : 1208654 : if (!TYPE_REF_P (TREE_TYPE (cap))
173 : 1208654 : && decl_constant_var_p (cap))
174 : : {
175 : 1061 : tree val = RECUR (cap);
176 : 1061 : if (!is_capture_proxy (val))
177 : : {
178 : 1061 : tree l = current_lambda_expr ();
179 : 1061 : LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
180 : : }
181 : 1061 : return val;
182 : : }
183 : : }
184 : 134881010 : tree r = mark_rvalue_use (ref, loc, reject_builtin);
185 : 134881010 : if (r != ref)
186 : : {
187 : 21 : if (!rvalue_p)
188 : : {
189 : : /* Make sure we still return an lvalue. */
190 : 12 : gcc_assert (TREE_CODE (r) == NOP_EXPR);
191 : 12 : TREE_TYPE (r) = cp_build_reference_type (TREE_TYPE (r),
192 : : false);
193 : : }
194 : 21 : expr = convert_from_reference (r);
195 : : }
196 : : }
197 : : break;
198 : :
199 : 414854838 : case VIEW_CONVERT_EXPR:
200 : 414854838 : if (location_wrapper_p (expr))
201 : : {
202 : 406871097 : loc = EXPR_LOCATION (expr);
203 : 406871097 : tree op = TREE_OPERAND (expr, 0);
204 : 406871097 : tree nop = RECUR (op);
205 : 406871097 : if (nop == error_mark_node)
206 : : return error_mark_node;
207 : 406871085 : else if (op == nop)
208 : : /* No change. */;
209 : 318 : else if (DECL_P (nop) || CONSTANT_CLASS_P (nop))
210 : : {
211 : : /* Reuse the location wrapper. */
212 : 306 : TREE_OPERAND (expr, 0) = nop;
213 : : /* If we're replacing a DECL with a constant, we also need to
214 : : change the TREE_CODE of the location wrapper. */
215 : 306 : if (rvalue_p)
216 : 306 : TREE_SET_CODE (expr, NON_LVALUE_EXPR);
217 : : }
218 : : else
219 : : {
220 : : /* Drop the location wrapper. */
221 : 12 : expr = nop;
222 : 12 : protected_set_expr_location (expr, loc);
223 : : }
224 : 406871085 : return expr;
225 : : }
226 : 520864692 : gcc_fallthrough ();
227 : 520864692 : CASE_CONVERT:
228 : 520864692 : recurse_op[0] = true;
229 : 520864692 : break;
230 : :
231 : 2541469 : case MODIFY_EXPR:
232 : 2541469 : {
233 : 2541469 : tree lhs = TREE_OPERAND (expr, 0);
234 : : /* [expr.ass] "An assignment whose left operand is of
235 : : a volatile-qualified type is deprecated unless the assignment
236 : : is either a discarded-value expression or appears in an
237 : : unevaluated context." */
238 : 2541469 : if (!cp_unevaluated_operand
239 : 2541343 : && (TREE_THIS_VOLATILE (lhs)
240 : 2540700 : || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs)))
241 : 2542112 : && !TREE_THIS_VOLATILE (expr))
242 : : {
243 : 446 : if (warning_at (location_of (expr), OPT_Wvolatile,
244 : : "using value of assignment with "
245 : : "%<volatile%>-qualified left operand is "
246 : : "deprecated"))
247 : : /* Make sure not to warn about this assignment again. */
248 : 80 : TREE_THIS_VOLATILE (expr) = true;
249 : : }
250 : : break;
251 : : }
252 : :
253 : : default:
254 : : break;
255 : : }
256 : :
257 : 17973251266 : for (int i = 0; i < 3; ++i)
258 : 13479938451 : if (recurse_op[i])
259 : : {
260 : 668961063 : tree op = TREE_OPERAND (expr, i);
261 : 668961063 : op = RECUR (op);
262 : 668961063 : if (op == error_mark_node)
263 : : return error_mark_node;
264 : 668961057 : TREE_OPERAND (expr, i) = op;
265 : : }
266 : :
267 : : return expr;
268 : : #undef RECUR
269 : : }
270 : :
271 : : /* Called whenever the expression EXPR is used in an rvalue context.
272 : : When REJECT_BUILTIN is true the expression is checked to make sure
273 : : it doesn't make it possible to obtain the address of a GCC built-in
274 : : function with no library fallback (or any of its bits, such as in
275 : : a conversion to bool). */
276 : :
277 : : tree
278 : 2857130740 : mark_rvalue_use (tree e,
279 : : location_t loc /* = UNKNOWN_LOCATION */,
280 : : bool reject_builtin /* = true */)
281 : : {
282 : 2857130740 : return mark_use (e, true, true, loc, reject_builtin);
283 : : }
284 : :
285 : : /* Called whenever an expression is used in an lvalue context. */
286 : :
287 : : tree
288 : 332304809 : mark_lvalue_use (tree expr)
289 : : {
290 : 332304809 : return mark_use (expr, false, true, input_location, false);
291 : : }
292 : :
293 : : /* As above, but don't consider this use a read. */
294 : :
295 : : tree
296 : 33464031 : mark_lvalue_use_nonread (tree expr)
297 : : {
298 : 33464031 : return mark_use (expr, false, false, input_location, false);
299 : : }
300 : :
301 : : /* Called when expr appears as a discarded-value expression. */
302 : :
303 : : tree
304 : 58191025 : mark_discarded_use (tree expr)
305 : : {
306 : : /* The lvalue-to-rvalue conversion (7.1) is applied if and only if the
307 : : expression is a glvalue of volatile-qualified type and it is one of the
308 : : following:
309 : : * ( expression ), where expression is one of these expressions,
310 : : * id-expression (8.1.4),
311 : : * subscripting (8.2.1),
312 : : * class member access (8.2.5),
313 : : * indirection (8.3.1),
314 : : * pointer-to-member operation (8.5),
315 : : * conditional expression (8.16) where both the second and the third
316 : : operands are one of these expressions, or
317 : : * comma expression (8.19) where the right operand is one of these
318 : : expressions. */
319 : 58191025 : if (expr == NULL_TREE)
320 : : return expr;
321 : :
322 : 58191019 : STRIP_ANY_LOCATION_WRAPPER (expr);
323 : :
324 : 58191019 : switch (TREE_CODE (expr))
325 : : {
326 : 129407 : case COND_EXPR:
327 : 129407 : TREE_OPERAND (expr, 2) = mark_discarded_use (TREE_OPERAND (expr, 2));
328 : 517745 : gcc_fallthrough ();
329 : 517745 : case COMPOUND_EXPR:
330 : 517745 : TREE_OPERAND (expr, 1) = mark_discarded_use (TREE_OPERAND (expr, 1));
331 : 517745 : return expr;
332 : :
333 : : case COMPONENT_REF:
334 : : case ARRAY_REF:
335 : : case INDIRECT_REF:
336 : : case MEMBER_REF:
337 : : break;
338 : 53451631 : default:
339 : 53451631 : if (DECL_P (expr))
340 : : break;
341 : : else
342 : : return expr;
343 : : }
344 : :
345 : : /* Like mark_rvalue_use, but don't reject built-ins. */
346 : 4263060 : return mark_use (expr, true, true, input_location, false);
347 : : }
348 : :
349 : : /* Called whenever an expression is used in a type use context. */
350 : :
351 : : tree
352 : 95105072 : mark_type_use (tree expr)
353 : : {
354 : 95105072 : mark_exp_read (expr);
355 : 95105072 : return expr;
356 : : }
357 : :
358 : : /* Mark EXP as read, not just set, for set but not used -Wunused
359 : : warning purposes. */
360 : :
361 : : void
362 : 5178514187 : mark_exp_read (tree exp)
363 : : {
364 : 7677226970 : if (exp == NULL)
365 : : return;
366 : :
367 : 7674830372 : if (TREE_TYPE (exp) && VOID_TYPE_P (TREE_TYPE (exp)))
368 : : return;
369 : :
370 : 7571025836 : switch (TREE_CODE (exp))
371 : : {
372 : 910040089 : case VAR_DECL:
373 : 910040089 : if (DECL_DECOMPOSITION_P (exp))
374 : 4260020 : mark_exp_read (DECL_DECOMP_BASE (exp));
375 : 2489228164 : gcc_fallthrough ();
376 : 2489228164 : case PARM_DECL:
377 : 2489228164 : DECL_READ_P (exp) = 1;
378 : 2489228164 : break;
379 : 2470787977 : CASE_CONVERT:
380 : 2470787977 : case ARRAY_REF:
381 : 2470787977 : case COMPONENT_REF:
382 : 2470787977 : case MODIFY_EXPR:
383 : 2470787977 : case REALPART_EXPR:
384 : 2470787977 : case IMAGPART_EXPR:
385 : 2470787977 : case ADDR_EXPR:
386 : 2470787977 : case INDIRECT_REF:
387 : 2470787977 : case FLOAT_EXPR:
388 : 2470787977 : case VIEW_CONVERT_EXPR:
389 : 2470787977 : case PREINCREMENT_EXPR:
390 : 2470787977 : case PREDECREMENT_EXPR:
391 : 2470787977 : case POSTINCREMENT_EXPR:
392 : 2470787977 : case POSTDECREMENT_EXPR:
393 : 2470787977 : mark_exp_read (TREE_OPERAND (exp, 0));
394 : 2470787977 : break;
395 : 8656036 : case COMPOUND_EXPR:
396 : 8656036 : mark_exp_read (TREE_OPERAND (exp, 1));
397 : 8656036 : break;
398 : 19268770 : case COND_EXPR:
399 : 19268770 : if (TREE_OPERAND (exp, 1))
400 : 19268721 : mark_exp_read (TREE_OPERAND (exp, 1));
401 : 19268770 : if (TREE_OPERAND (exp, 2))
402 : 19268770 : mark_exp_read (TREE_OPERAND (exp, 2));
403 : : break;
404 : : default:
405 : : break;
406 : : }
407 : : }
408 : :
409 : : /* Fold X for consideration by one of the warning functions when checking
410 : : whether an expression has a constant value. */
411 : :
412 : : tree
413 : 66228085 : fold_for_warn (tree x)
414 : : {
415 : : /* C++ implementation. */
416 : :
417 : 66228085 : if (cp_unevaluated_operand)
418 : : /* In an unevaluated context we don't care about the reduced value
419 : : of an expression, so neither should any warnings. */
420 : : return x;
421 : :
422 : : /* Prevent warning-dependent constexpr evaluation from changing
423 : : DECL_UID (which breaks -fcompare-debug) and from instantiating
424 : : templates. */
425 : 66191833 : uid_sensitive_constexpr_evaluation_sentinel s;
426 : :
427 : : /* It's not generally safe to fully fold inside of a template, so
428 : : call fold_non_dependent_expr instead. */
429 : 66191833 : if (processing_template_decl)
430 : : {
431 : 3257235 : tree f = fold_non_dependent_expr (x, tf_none);
432 : 3257235 : if (f == error_mark_node)
433 : : return x;
434 : : else
435 : 3257233 : return f;
436 : : }
437 : 62934598 : else if (cxx_dialect >= cxx11)
438 : 62547954 : x = maybe_constant_value (x);
439 : :
440 : 62934598 : return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
441 : 66191833 : }
442 : :
443 : : /* Make EXPR only execute during constant evaluation by wrapping it in a
444 : : statement-expression containing 'if consteval'. */
445 : :
446 : : tree
447 : 1 : wrap_with_if_consteval (tree expr)
448 : : {
449 : 1 : tree stmtex = begin_stmt_expr ();
450 : 1 : tree ifcev = begin_if_stmt ();
451 : 1 : IF_STMT_CONSTEVAL_P (ifcev) = true;
452 : 1 : finish_if_stmt_cond (boolean_false_node, ifcev);
453 : 1 : finish_expr_stmt (expr);
454 : 1 : finish_then_clause (ifcev);
455 : 1 : finish_if_stmt (ifcev);
456 : 1 : return finish_stmt_expr (stmtex, /*no scope*/true);
457 : : }
|