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