Line data Source code
1 : /* Convert language-specific tree expression to rtl instructions,
2 : for GNU compiler.
3 : Copyright (C) 1988-2026 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 96045940 : cplus_expand_constant (tree cst)
31 : {
32 96045940 : switch (TREE_CODE (cst))
33 : {
34 34546 : case PTRMEM_CST:
35 34546 : {
36 34546 : tree type = TREE_TYPE (cst);
37 34546 : tree member;
38 :
39 : /* Find the member. */
40 34546 : member = PTRMEM_CST_MEMBER (cst);
41 :
42 : /* We can't lower this until the class is complete. */
43 34546 : if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
44 : return cst;
45 :
46 34507 : if (TREE_CODE (member) == FIELD_DECL)
47 : {
48 : /* Find the offset for the field. */
49 2949 : cst = byte_position (member);
50 6038 : 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 140 : member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
57 140 : DECL_CONTEXT (member));
58 140 : cst = size_binop (PLUS_EXPR, cst, byte_position (member));
59 : }
60 2949 : cst = fold (build_nop (type, cst));
61 : }
62 : else
63 : {
64 31558 : tree delta;
65 31558 : tree pfn;
66 :
67 31558 : expand_ptrmemfunc_cst (cst, &delta, &pfn);
68 31558 : 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 71264042 : FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt)
78 66070637 : 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 6665743060 : 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 6665743060 : if (expr == NULL_TREE || error_operand_p (expr))
100 : return expr;
101 :
102 6665737753 : if (reject_builtin && reject_gcc_builtin (expr, loc))
103 67 : return error_mark_node;
104 :
105 6665737686 : if (TREE_TYPE (expr) && VOID_TYPE_P (TREE_TYPE (expr)))
106 : read_p = false;
107 :
108 6552496489 : if (read_p)
109 6482657081 : mark_exp_read (expr);
110 :
111 6665737686 : tree oexpr = expr;
112 6665737686 : bool recurse_op[3] = { false, false, false };
113 6665737686 : switch (TREE_CODE (expr))
114 : {
115 1679166595 : case VAR_DECL:
116 1679166595 : case PARM_DECL:
117 1679166595 : if (rvalue_p && is_normal_capture_proxy (expr))
118 : {
119 : /* Look through capture by copy. */
120 6764934 : tree cap = DECL_CAPTURED_VARIABLE (expr);
121 6764934 : if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr))
122 6764934 : && decl_constant_var_p (cap))
123 : {
124 185 : tree val = RECUR (cap);
125 185 : if (!is_capture_proxy (val))
126 : {
127 146 : tree l = current_lambda_expr ();
128 146 : LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
129 : }
130 185 : return val;
131 : }
132 : }
133 1679166410 : if (outer_automatic_var_p (expr)
134 1679166410 : && decl_constant_var_p (expr))
135 : {
136 87454 : if (rvalue_p)
137 : {
138 87445 : tree t = maybe_constant_value (expr);
139 87445 : if (TREE_CONSTANT (t))
140 : {
141 : expr = t;
142 6119122889 : break;
143 : }
144 : }
145 84 : iloc_sentinel l (loc);
146 84 : expr = process_outer_var_ref (expr, tf_warning_or_error, true);
147 84 : if (!(TREE_TYPE (oexpr)
148 84 : && TYPE_REF_P (TREE_TYPE (oexpr))))
149 51 : expr = convert_from_reference (expr);
150 84 : }
151 : break;
152 152057708 : case COMPONENT_REF:
153 152057708 : recurse_op[0] = true;
154 152057708 : break;
155 13884719 : case COMPOUND_EXPR:
156 13884719 : recurse_op[1] = true;
157 13884719 : break;
158 18025267 : case COND_EXPR:
159 18025267 : recurse_op[2] = true;
160 18025267 : if (TREE_OPERAND (expr, 1))
161 18025228 : recurse_op[1] = true;
162 : break;
163 356969263 : case INDIRECT_REF:
164 356969263 : if (REFERENCE_REF_P (expr))
165 : {
166 : /* Try to look through the reference. */
167 199046879 : tree ref = TREE_OPERAND (expr, 0);
168 199046879 : if (rvalue_p && is_normal_capture_proxy (ref))
169 : {
170 : /* Look through capture by reference. */
171 736730 : tree cap = DECL_CAPTURED_VARIABLE (ref);
172 736730 : if (!TYPE_REF_P (TREE_TYPE (cap))
173 736730 : && decl_constant_var_p (cap))
174 : {
175 1738 : tree val = RECUR (cap);
176 1738 : if (!is_capture_proxy (val))
177 : {
178 1738 : tree l = current_lambda_expr ();
179 1738 : LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
180 : }
181 1738 : return val;
182 : }
183 : }
184 199045141 : tree r = mark_rvalue_use (ref, loc, reject_builtin);
185 199045141 : if (r == error_mark_node)
186 : return error_mark_node;
187 199045132 : if (r != ref)
188 : {
189 33 : if (!rvalue_p)
190 : {
191 : /* Make sure we still return an lvalue. */
192 30 : gcc_assert (TREE_CODE (r) == NOP_EXPR);
193 30 : TREE_TYPE (r) = cp_build_reference_type (TREE_TYPE (r),
194 : false);
195 : }
196 33 : expr = convert_from_reference (r);
197 : }
198 : }
199 : break;
200 :
201 556076887 : case VIEW_CONVERT_EXPR:
202 556076887 : if (location_wrapper_p (expr))
203 : {
204 546612865 : loc = EXPR_LOCATION (expr);
205 546612865 : tree op = TREE_OPERAND (expr, 0);
206 546612865 : tree nop = RECUR (op);
207 546612865 : if (nop == error_mark_node)
208 : return error_mark_node;
209 546612853 : else if (op == nop)
210 : /* No change. */;
211 625 : else if (DECL_P (nop) || CONSTANT_CLASS_P (nop))
212 : {
213 : /* Reuse the location wrapper. */
214 582 : TREE_OPERAND (expr, 0) = nop;
215 : /* If we're replacing a DECL with a constant, we also need to
216 : change the TREE_CODE of the location wrapper. */
217 582 : if (rvalue_p)
218 582 : TREE_SET_CODE (expr, NON_LVALUE_EXPR);
219 : }
220 : else
221 : {
222 : /* Drop the location wrapper. */
223 43 : expr = nop;
224 43 : protected_set_expr_location (expr, loc);
225 : }
226 546612853 : return expr;
227 : }
228 783395827 : gcc_fallthrough ();
229 783395827 : CASE_CONVERT:
230 783395827 : recurse_op[0] = true;
231 783395827 : break;
232 :
233 2964568 : case MODIFY_EXPR:
234 2964568 : {
235 2964568 : tree lhs = TREE_OPERAND (expr, 0);
236 : /* [expr.ass] "An assignment whose left operand is of
237 : a volatile-qualified type is deprecated unless the assignment
238 : is either a discarded-value expression or appears in an
239 : unevaluated context." */
240 2964568 : if (!cp_unevaluated_operand
241 2964442 : && (TREE_THIS_VOLATILE (lhs)
242 2963475 : || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs)))
243 2965535 : && !TREE_THIS_VOLATILE (expr))
244 : {
245 581 : if (warning_at (location_of (expr), OPT_Wvolatile,
246 : "using value of assignment with "
247 : "%<volatile%>-qualified left operand is "
248 : "deprecated"))
249 : /* Make sure not to warn about this assignment again. */
250 90 : TREE_THIS_VOLATILE (expr) = true;
251 : }
252 : break;
253 : }
254 :
255 : default:
256 : break;
257 : }
258 :
259 24476491538 : for (int i = 0; i < 3; ++i)
260 18357368655 : if (recurse_op[i])
261 : {
262 985388749 : tree op = TREE_OPERAND (expr, i);
263 985388749 : op = RECUR (op);
264 985388749 : if (op == error_mark_node)
265 : return error_mark_node;
266 985388743 : TREE_OPERAND (expr, i) = op;
267 : }
268 :
269 : return expr;
270 : #undef RECUR
271 : }
272 :
273 : /* Called whenever the expression EXPR is used in an rvalue context.
274 : When REJECT_BUILTIN is true the expression is checked to make sure
275 : it doesn't make it possible to obtain the address of a GCC built-in
276 : function with no library fallback (or any of its bits, such as in
277 : a conversion to bool). */
278 :
279 : tree
280 3949893255 : mark_rvalue_use (tree e,
281 : location_t loc /* = UNKNOWN_LOCATION */,
282 : bool reject_builtin /* = true */)
283 : {
284 3949893255 : return mark_use (e, true, true, loc, reject_builtin);
285 : }
286 :
287 : /* Called whenever an expression is used in an lvalue context. */
288 :
289 : tree
290 402385989 : mark_lvalue_use (tree expr)
291 : {
292 402385989 : return mark_use (expr, false, true, input_location, false);
293 : }
294 :
295 : /* As above, but don't consider this use a read. */
296 :
297 : tree
298 37308793 : mark_lvalue_use_nonread (tree expr)
299 : {
300 37308793 : return mark_use (expr, false, false, input_location, false);
301 : }
302 :
303 : /* Called when expr appears as a discarded-value expression. */
304 :
305 : tree
306 72718630 : mark_discarded_use (tree expr)
307 : {
308 : /* The lvalue-to-rvalue conversion (7.1) is applied if and only if the
309 : expression is a glvalue of volatile-qualified type and it is one of the
310 : following:
311 : * ( expression ), where expression is one of these expressions,
312 : * id-expression (8.1.4),
313 : * subscripting (8.2.1),
314 : * class member access (8.2.5),
315 : * indirection (8.3.1),
316 : * pointer-to-member operation (8.5),
317 : * conditional expression (8.16) where both the second and the third
318 : operands are one of these expressions, or
319 : * comma expression (8.19) where the right operand is one of these
320 : expressions. */
321 72718630 : if (expr == NULL_TREE)
322 : return expr;
323 :
324 72718624 : STRIP_ANY_LOCATION_WRAPPER (expr);
325 :
326 72718624 : switch (TREE_CODE (expr))
327 : {
328 122420 : case COND_EXPR:
329 122420 : TREE_OPERAND (expr, 2) = mark_discarded_use (TREE_OPERAND (expr, 2));
330 596291 : gcc_fallthrough ();
331 596291 : case COMPOUND_EXPR:
332 596291 : TREE_OPERAND (expr, 1) = mark_discarded_use (TREE_OPERAND (expr, 1));
333 596291 : return expr;
334 :
335 : case COMPONENT_REF:
336 : case ARRAY_REF:
337 : case INDIRECT_REF:
338 : case MEMBER_REF:
339 : break;
340 64840460 : default:
341 64840460 : if (DECL_P (expr))
342 : break;
343 : else
344 : return expr;
345 : }
346 :
347 : /* Like mark_rvalue_use, but don't reject built-ins. */
348 7310610 : return mark_use (expr, true, true, input_location, false);
349 : }
350 :
351 : /* Called whenever an expression is used in a type use context. */
352 :
353 : tree
354 115048254 : mark_type_use (tree expr)
355 : {
356 115048254 : mark_exp_read (expr);
357 115048254 : return expr;
358 : }
359 :
360 : /* Mark EXP as read, not just set, for set but not used -Wunused
361 : warning purposes. */
362 :
363 : void
364 7021617169 : mark_exp_read (tree exp)
365 : {
366 10515280758 : if (exp == NULL)
367 : return;
368 :
369 10510610407 : if (TREE_TYPE (exp) && VOID_TYPE_P (TREE_TYPE (exp)))
370 : return;
371 :
372 10383997365 : switch (TREE_CODE (exp))
373 : {
374 1182917122 : case VAR_DECL:
375 1182917122 : if (DECL_DECOMPOSITION_P (exp))
376 8150208 : mark_exp_read (DECL_DECOMP_BASE (exp));
377 3442077122 : gcc_fallthrough ();
378 3442077122 : case PARM_DECL:
379 3442077122 : DECL_READ_P (exp) = 1;
380 3442077122 : break;
381 3446184563 : CASE_CONVERT:
382 3446184563 : case ARRAY_REF:
383 3446184563 : case COMPONENT_REF:
384 3446184563 : case MODIFY_EXPR:
385 3446184563 : case REALPART_EXPR:
386 3446184563 : case IMAGPART_EXPR:
387 3446184563 : case ADDR_EXPR:
388 3446184563 : case INDIRECT_REF:
389 3446184563 : case FLOAT_EXPR:
390 3446184563 : case VIEW_CONVERT_EXPR:
391 3446184563 : case PREINCREMENT_EXPR:
392 3446184563 : case PREDECREMENT_EXPR:
393 3446184563 : case POSTINCREMENT_EXPR:
394 3446184563 : case POSTDECREMENT_EXPR:
395 3446184563 : mark_exp_read (TREE_OPERAND (exp, 0));
396 3446184563 : break;
397 22657910 : case COMPOUND_EXPR:
398 22657910 : mark_exp_read (TREE_OPERAND (exp, 1));
399 22657910 : break;
400 24821116 : case COND_EXPR:
401 24821116 : if (TREE_OPERAND (exp, 1))
402 24821067 : mark_exp_read (TREE_OPERAND (exp, 1));
403 24821116 : if (TREE_OPERAND (exp, 2))
404 24821116 : mark_exp_read (TREE_OPERAND (exp, 2));
405 : break;
406 : default:
407 : break;
408 : }
409 : }
410 :
411 : /* Fold X for consideration by one of the warning functions when checking
412 : whether an expression has a constant value. */
413 :
414 : tree
415 76946903 : fold_for_warn (tree x)
416 : {
417 : /* C++ implementation. */
418 :
419 76946903 : if (cp_unevaluated_operand)
420 : /* In an unevaluated context we don't care about the reduced value
421 : of an expression, so neither should any warnings. */
422 : return x;
423 :
424 : /* Prevent warning-dependent constexpr evaluation from changing
425 : DECL_UID (which breaks -fcompare-debug) and from instantiating
426 : templates. */
427 76893666 : uid_sensitive_constexpr_evaluation_sentinel s;
428 :
429 : /* It's not generally safe to fully fold inside of a template, so
430 : call fold_non_dependent_expr instead. */
431 76893666 : if (processing_template_decl)
432 : {
433 3808670 : tree f = fold_non_dependent_expr (x, tf_none);
434 3808670 : if (f == error_mark_node)
435 : return x;
436 : else
437 3808668 : return f;
438 : }
439 73084996 : else if (cxx_dialect >= cxx11)
440 72630982 : x = maybe_constant_value (x);
441 :
442 73084996 : return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
443 76893666 : }
444 :
445 : /* Make EXPR only execute during constant evaluation by wrapping it in a
446 : statement-expression containing 'if consteval'. */
447 :
448 : tree
449 2 : wrap_with_if_consteval (tree expr)
450 : {
451 2 : tree stmtex = begin_stmt_expr ();
452 2 : tree ifcev = begin_if_stmt ();
453 2 : IF_STMT_CONSTEVAL_P (ifcev) = true;
454 2 : finish_if_stmt_cond (boolean_false_node, ifcev);
455 2 : finish_expr_stmt (expr);
456 2 : finish_then_clause (ifcev);
457 2 : finish_if_stmt (ifcev);
458 2 : return finish_stmt_expr (stmtex, /*no scope*/true);
459 : }
|