Branch data Line data Source code
1 : : /* Convert language-specific tree expression to rtl instructions,
2 : : for GNU compiler.
3 : : Copyright (C) 1988-2024 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 : 41023988 : cplus_expand_constant (tree cst)
31 : : {
32 : 41023988 : switch (TREE_CODE (cst))
33 : : {
34 : 36525 : case PTRMEM_CST:
35 : 36525 : {
36 : 36525 : tree type = TREE_TYPE (cst);
37 : 36525 : tree member;
38 : :
39 : : /* Find the member. */
40 : 36525 : member = PTRMEM_CST_MEMBER (cst);
41 : :
42 : : /* We can't lower this until the class is complete. */
43 : 36525 : if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
44 : : return cst;
45 : :
46 : 36492 : if (TREE_CODE (member) == FIELD_DECL)
47 : : {
48 : : /* Find the offset for the field. */
49 : 4023 : cst = byte_position (member);
50 : 8202 : 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 : 156 : member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
57 : 156 : DECL_CONTEXT (member));
58 : 156 : cst = size_binop (PLUS_EXPR, cst, byte_position (member));
59 : : }
60 : 4023 : cst = fold (build_nop (type, cst));
61 : : }
62 : : else
63 : : {
64 : 32469 : tree delta;
65 : 32469 : tree pfn;
66 : :
67 : 32469 : expand_ptrmemfunc_cst (cst, &delta, &pfn);
68 : 32469 : 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 : 29705557 : FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt)
78 : 25875820 : 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 : 4720558663 : 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 : 4720558663 : if (expr == NULL_TREE || error_operand_p (expr))
100 : : return expr;
101 : :
102 : 4720553875 : if (reject_builtin && reject_gcc_builtin (expr, loc))
103 : 66 : return error_mark_node;
104 : :
105 : 4720553809 : if (read_p)
106 : 4662591606 : mark_exp_read (expr);
107 : :
108 : 4720553809 : tree oexpr = expr;
109 : 4720553809 : bool recurse_op[3] = { false, false, false };
110 : 4720553809 : switch (TREE_CODE (expr))
111 : : {
112 : 1167534518 : case VAR_DECL:
113 : 1167534518 : case PARM_DECL:
114 : 1167534518 : if (rvalue_p && is_normal_capture_proxy (expr))
115 : : {
116 : : /* Look through capture by copy. */
117 : 5626208 : tree cap = DECL_CAPTURED_VARIABLE (expr);
118 : 5626208 : if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr))
119 : 5626208 : && decl_constant_var_p (cap))
120 : : {
121 : 168 : tree val = RECUR (cap);
122 : 168 : if (!is_capture_proxy (val))
123 : : {
124 : 123 : tree l = current_lambda_expr ();
125 : 123 : LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
126 : : }
127 : 168 : return val;
128 : : }
129 : : }
130 : 1167534350 : if (outer_automatic_var_p (expr)
131 : 1167534350 : && decl_constant_var_p (expr))
132 : : {
133 : 82967 : if (rvalue_p)
134 : : {
135 : 82958 : tree t = maybe_constant_value (expr);
136 : 82958 : if (TREE_CONSTANT (t))
137 : : {
138 : : expr = t;
139 : 4321995221 : break;
140 : : }
141 : : }
142 : 60 : iloc_sentinel l (loc);
143 : 60 : expr = process_outer_var_ref (expr, tf_warning_or_error, true);
144 : 60 : if (!(TREE_TYPE (oexpr)
145 : 60 : && TYPE_REF_P (TREE_TYPE (oexpr))))
146 : 42 : expr = convert_from_reference (expr);
147 : 60 : }
148 : : break;
149 : 107866876 : case COMPONENT_REF:
150 : 107866876 : recurse_op[0] = true;
151 : 107866876 : break;
152 : 6337127 : case COMPOUND_EXPR:
153 : 6337127 : recurse_op[1] = true;
154 : 6337127 : break;
155 : 14055628 : case COND_EXPR:
156 : 14055628 : recurse_op[2] = true;
157 : 14055628 : if (TREE_OPERAND (expr, 1))
158 : 14055582 : recurse_op[1] = true;
159 : : break;
160 : 222130777 : case INDIRECT_REF:
161 : 222130777 : if (REFERENCE_REF_P (expr))
162 : : {
163 : : /* Try to look through the reference. */
164 : 109935154 : tree ref = TREE_OPERAND (expr, 0);
165 : 109935154 : if (rvalue_p && is_normal_capture_proxy (ref))
166 : : {
167 : : /* Look through capture by reference. */
168 : 1020144 : tree cap = DECL_CAPTURED_VARIABLE (ref);
169 : 1020144 : if (!TYPE_REF_P (TREE_TYPE (cap))
170 : 1020144 : && decl_constant_var_p (cap))
171 : : {
172 : 852 : tree val = RECUR (cap);
173 : 852 : if (!is_capture_proxy (val))
174 : : {
175 : 852 : tree l = current_lambda_expr ();
176 : 852 : LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
177 : : }
178 : 852 : return val;
179 : : }
180 : : }
181 : 109934302 : tree r = mark_rvalue_use (ref, loc, reject_builtin);
182 : 109934302 : if (r != ref)
183 : 15 : expr = convert_from_reference (r);
184 : : }
185 : : break;
186 : :
187 : 406435050 : case VIEW_CONVERT_EXPR:
188 : 406435050 : if (location_wrapper_p (expr))
189 : : {
190 : 398557568 : loc = EXPR_LOCATION (expr);
191 : 398557568 : tree op = TREE_OPERAND (expr, 0);
192 : 398557568 : tree nop = RECUR (op);
193 : 398557568 : if (nop == error_mark_node)
194 : : return error_mark_node;
195 : 398557559 : else if (op == nop)
196 : : /* No change. */;
197 : 302 : else if (DECL_P (nop) || CONSTANT_CLASS_P (nop))
198 : : {
199 : : /* Reuse the location wrapper. */
200 : 290 : TREE_OPERAND (expr, 0) = nop;
201 : : /* If we're replacing a DECL with a constant, we also need to
202 : : change the TREE_CODE of the location wrapper. */
203 : 290 : if (rvalue_p)
204 : 290 : TREE_SET_CODE (expr, NON_LVALUE_EXPR);
205 : : }
206 : : else
207 : : {
208 : : /* Drop the location wrapper. */
209 : 12 : expr = nop;
210 : 12 : protected_set_expr_location (expr, loc);
211 : : }
212 : 398557559 : return expr;
213 : : }
214 : 482182702 : gcc_fallthrough();
215 : 482182702 : CASE_CONVERT:
216 : 482182702 : recurse_op[0] = true;
217 : 482182702 : break;
218 : :
219 : 3384475 : case MODIFY_EXPR:
220 : 3384475 : {
221 : 3384475 : tree lhs = TREE_OPERAND (expr, 0);
222 : : /* [expr.ass] "An assignment whose left operand is of
223 : : a volatile-qualified type is deprecated unless the assignment
224 : : is either a discarded-value expression or appears in an
225 : : unevaluated context." */
226 : 3384475 : if (!cp_unevaluated_operand
227 : 3384337 : && (TREE_THIS_VOLATILE (lhs)
228 : 3383547 : || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs)))
229 : 3385265 : && !TREE_THIS_VOLATILE (expr))
230 : : {
231 : 526 : if (warning_at (location_of (expr), OPT_Wvolatile,
232 : : "using value of assignment with "
233 : : "%<volatile%>-qualified left operand is "
234 : : "deprecated"))
235 : : /* Make sure not to warn about this assignment again. */
236 : 80 : TREE_THIS_VOLATILE (expr) = true;
237 : : }
238 : : break;
239 : : }
240 : :
241 : : default:
242 : : break;
243 : : }
244 : :
245 : 17287980884 : for (int i = 0; i < 3; ++i)
246 : 12965985663 : if (recurse_op[i])
247 : : {
248 : 624497915 : tree op = TREE_OPERAND (expr, i);
249 : 624497915 : op = RECUR (op);
250 : 624497915 : if (op == error_mark_node)
251 : : return error_mark_node;
252 : 624497915 : TREE_OPERAND (expr, i) = op;
253 : : }
254 : :
255 : : return expr;
256 : : #undef RECUR
257 : : }
258 : :
259 : : /* Called whenever the expression EXPR is used in an rvalue context.
260 : : When REJECT_BUILTIN is true the expression is checked to make sure
261 : : it doesn't make it possible to obtain the address of a GCC built-in
262 : : function with no library fallback (or any of its bits, such as in
263 : : a conversion to bool). */
264 : :
265 : : tree
266 : 2856110242 : mark_rvalue_use (tree e,
267 : : location_t loc /* = UNKNOWN_LOCATION */,
268 : : bool reject_builtin /* = true */)
269 : : {
270 : 2856110242 : return mark_use (e, true, true, loc, reject_builtin);
271 : : }
272 : :
273 : : /* Called whenever an expression is used in an lvalue context. */
274 : :
275 : : tree
276 : 276262097 : mark_lvalue_use (tree expr)
277 : : {
278 : 276262097 : return mark_use (expr, false, true, input_location, false);
279 : : }
280 : :
281 : : /* As above, but don't consider this use a read. */
282 : :
283 : : tree
284 : 30716784 : mark_lvalue_use_nonread (tree expr)
285 : : {
286 : 30716784 : return mark_use (expr, false, false, input_location, false);
287 : : }
288 : :
289 : : /* Called when expr appears as a discarded-value expression. */
290 : :
291 : : tree
292 : 80145138 : mark_discarded_use (tree expr)
293 : : {
294 : : /* The lvalue-to-rvalue conversion (7.1) is applied if and only if the
295 : : expression is a glvalue of volatile-qualified type and it is one of the
296 : : following:
297 : : * ( expression ), where expression is one of these expressions,
298 : : * id-expression (8.1.4),
299 : : * subscripting (8.2.1),
300 : : * class member access (8.2.5),
301 : : * indirection (8.3.1),
302 : : * pointer-to-member operation (8.5),
303 : : * conditional expression (8.16) where both the second and the third
304 : : operands are one of these expressions, or
305 : : * comma expression (8.19) where the right operand is one of these
306 : : expressions. */
307 : 80145138 : if (expr == NULL_TREE)
308 : : return expr;
309 : :
310 : 80145132 : STRIP_ANY_LOCATION_WRAPPER (expr);
311 : :
312 : 80145132 : switch (TREE_CODE (expr))
313 : : {
314 : 125638 : case COND_EXPR:
315 : 125638 : TREE_OPERAND (expr, 2) = mark_discarded_use (TREE_OPERAND (expr, 2));
316 : 574600 : gcc_fallthrough ();
317 : 574600 : case COMPOUND_EXPR:
318 : 574600 : TREE_OPERAND (expr, 1) = mark_discarded_use (TREE_OPERAND (expr, 1));
319 : 574600 : return expr;
320 : :
321 : : case COMPONENT_REF:
322 : : case ARRAY_REF:
323 : : case INDIRECT_REF:
324 : : case MEMBER_REF:
325 : : break;
326 : 76115103 : default:
327 : 76115103 : if (DECL_P (expr))
328 : : break;
329 : : else
330 : : return expr;
331 : : }
332 : :
333 : : /* Like mark_rvalue_use, but don't reject built-ins. */
334 : 3481170 : return mark_use (expr, true, true, input_location, false);
335 : : }
336 : :
337 : : /* Called whenever an expression is used in a type use context. */
338 : :
339 : : tree
340 : 85183527 : mark_type_use (tree expr)
341 : : {
342 : 85183527 : mark_exp_read (expr);
343 : 85183527 : return expr;
344 : : }
345 : :
346 : : /* Mark EXP as read, not just set, for set but not used -Wunused
347 : : warning purposes. */
348 : :
349 : : void
350 : 5040755679 : mark_exp_read (tree exp)
351 : : {
352 : 7340501730 : if (exp == NULL)
353 : : return;
354 : :
355 : 7338513585 : switch (TREE_CODE (exp))
356 : : {
357 : 871914134 : case VAR_DECL:
358 : 871914134 : if (DECL_DECOMPOSITION_P (exp))
359 : 3530672 : mark_exp_read (DECL_DECOMP_BASE (exp));
360 : 2346618562 : gcc_fallthrough ();
361 : 2346618562 : case PARM_DECL:
362 : 2346618562 : DECL_READ_P (exp) = 1;
363 : 2346618562 : break;
364 : 2272356449 : case ARRAY_REF:
365 : 2272356449 : case COMPONENT_REF:
366 : 2272356449 : case MODIFY_EXPR:
367 : 2272356449 : case REALPART_EXPR:
368 : 2272356449 : case IMAGPART_EXPR:
369 : 2272356449 : CASE_CONVERT:
370 : 2272356449 : case ADDR_EXPR:
371 : 2272356449 : case INDIRECT_REF:
372 : 2272356449 : case FLOAT_EXPR:
373 : 2272356449 : case VIEW_CONVERT_EXPR:
374 : 2272356449 : mark_exp_read (TREE_OPERAND (exp, 0));
375 : 2272356449 : break;
376 : 7625797 : case COMPOUND_EXPR:
377 : 7625797 : mark_exp_read (TREE_OPERAND (exp, 1));
378 : 7625797 : break;
379 : 19763805 : case COND_EXPR:
380 : 19763805 : if (TREE_OPERAND (exp, 1))
381 : 19763748 : mark_exp_read (TREE_OPERAND (exp, 1));
382 : 19763805 : if (TREE_OPERAND (exp, 2))
383 : 19763805 : mark_exp_read (TREE_OPERAND (exp, 2));
384 : : break;
385 : : default:
386 : : break;
387 : : }
388 : : }
389 : :
390 : : /* Fold X for consideration by one of the warning functions when checking
391 : : whether an expression has a constant value. */
392 : :
393 : : tree
394 : 61613402 : fold_for_warn (tree x)
395 : : {
396 : : /* C++ implementation. */
397 : :
398 : 61613402 : if (cp_unevaluated_operand)
399 : : /* In an unevaluated context we don't care about the reduced value
400 : : of an expression, so neither should any warnings. */
401 : : return x;
402 : :
403 : : /* Prevent warning-dependent constexpr evaluation from changing
404 : : DECL_UID (which breaks -fcompare-debug) and from instantiating
405 : : templates. */
406 : 61426218 : uid_sensitive_constexpr_evaluation_sentinel s;
407 : :
408 : : /* It's not generally safe to fully fold inside of a template, so
409 : : call fold_non_dependent_expr instead. */
410 : 61426218 : if (processing_template_decl)
411 : : {
412 : 2976552 : tree f = fold_non_dependent_expr (x, tf_none);
413 : 2976552 : if (f == error_mark_node)
414 : : return x;
415 : : else
416 : 2976550 : return f;
417 : : }
418 : 58449666 : else if (cxx_dialect >= cxx11)
419 : 58057537 : x = maybe_constant_value (x);
420 : :
421 : 58449666 : return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
422 : 61426218 : }
|