1/* Convert language-specific tree expression to rtl instructions,
2   for GNU compiler.
3   Copyright (C) 1988-2022 Free Software Foundation, Inc.
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GCC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along 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
29tree
30cplus_expand_constant (tree cst)
31{
32  switch (TREE_CODE (cst))
33    {
34    case PTRMEM_CST:
35      {
36	tree type = TREE_TYPE (cst);
37	tree member;
38
39	/* Find the member.  */
40	member = PTRMEM_CST_MEMBER (cst);
41
42	/* We can't lower this until the class is complete.  */
43	if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
44	  return cst;
45
46	if (TREE_CODE (member) == FIELD_DECL)
47	  {
48	    /* Find the offset for the field.  */
49	    cst = byte_position (member);
50	    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		member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
57					    DECL_CONTEXT (member));
58		cst = size_binop (PLUS_EXPR, cst, byte_position (member));
59	      }
60	    cst = fold (build_nop (type, cst));
61	  }
62	else
63	  {
64	    tree delta;
65	    tree pfn;
66
67	    expand_ptrmemfunc_cst (cst, &delta, &pfn);
68	    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	FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt)
78	  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
92tree
93mark_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  if (expr == NULL_TREE || error_operand_p (expr))
100    return expr;
101
102  if (reject_builtin && reject_gcc_builtin (expr, loc))
103    return error_mark_node;
104
105  if (read_p)
106    mark_exp_read (expr);
107
108  tree oexpr = expr;
109  bool recurse_op[3] = { false, false, false };
110  switch (TREE_CODE (expr))
111    {
112    case VAR_DECL:
113    case PARM_DECL:
114      if (rvalue_p && is_normal_capture_proxy (expr))
115	{
116	  /* Look through capture by copy.  */
117	  tree cap = DECL_CAPTURED_VARIABLE (expr);
118	  if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr))
119	      && decl_constant_var_p (cap))
120	    {
121	      tree val = RECUR (cap);
122	      if (!is_capture_proxy (val))
123		{
124		  tree l = current_lambda_expr ();
125		  LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
126		}
127	      return val;
128	    }
129	}
130      if (outer_automatic_var_p (expr)
131	  && decl_constant_var_p (expr))
132	{
133	  if (rvalue_p)
134	    {
135	      tree t = maybe_constant_value (expr);
136	      if (TREE_CONSTANT (t))
137		{
138		  expr = t;
139		  break;
140		}
141	    }
142	  iloc_sentinel l (loc);
143	  expr = process_outer_var_ref (expr, tf_warning_or_error, true);
144	  if (!(TREE_TYPE (oexpr)
145		&& TYPE_REF_P (TREE_TYPE (oexpr))))
146	    expr = convert_from_reference (expr);
147	}
148      break;
149    case COMPONENT_REF:
150    case NON_DEPENDENT_EXPR:
151      recurse_op[0] = true;
152      break;
153    case COMPOUND_EXPR:
154      recurse_op[1] = true;
155      break;
156    case COND_EXPR:
157      recurse_op[2] = true;
158      if (TREE_OPERAND (expr, 1))
159	recurse_op[1] = true;
160      break;
161    case INDIRECT_REF:
162      if (REFERENCE_REF_P (expr))
163	{
164	  /* Try to look through the reference.  */
165	  tree ref = TREE_OPERAND (expr, 0);
166	  if (rvalue_p && is_normal_capture_proxy (ref))
167	    {
168	      /* Look through capture by reference.  */
169	      tree cap = DECL_CAPTURED_VARIABLE (ref);
170	      if (!TYPE_REF_P (TREE_TYPE (cap))
171		  && decl_constant_var_p (cap))
172		{
173		  tree val = RECUR (cap);
174		  if (!is_capture_proxy (val))
175		    {
176		      tree l = current_lambda_expr ();
177		      LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
178		    }
179		  return val;
180		}
181	    }
182	  tree r = mark_rvalue_use (ref, loc, reject_builtin);
183	  if (r != ref)
184	    expr = convert_from_reference (r);
185	}
186      break;
187
188    case VIEW_CONVERT_EXPR:
189      if (location_wrapper_p (expr))
190	{
191	  loc = EXPR_LOCATION (expr);
192	  tree op = TREE_OPERAND (expr, 0);
193	  tree nop = RECUR (op);
194	  if (nop == error_mark_node)
195	    return error_mark_node;
196	  else if (op == nop)
197	    /* No change.  */;
198	  else if (DECL_P (nop) || CONSTANT_CLASS_P (nop))
199	    {
200	      /* Reuse the location wrapper.  */
201	      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	      if (rvalue_p)
205		TREE_SET_CODE (expr, NON_LVALUE_EXPR);
206	    }
207	  else
208	    {
209	      /* Drop the location wrapper.  */
210	      expr = nop;
211	      protected_set_expr_location (expr, loc);
212	    }
213	  return expr;
214	}
215      gcc_fallthrough();
216    CASE_CONVERT:
217      recurse_op[0] = true;
218      break;
219
220    case MODIFY_EXPR:
221	{
222	  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	  if (!cp_unevaluated_operand
228	      && (TREE_THIS_VOLATILE (lhs)
229		  || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs)))
230	      && !TREE_THIS_VOLATILE (expr))
231	    {
232	      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		TREE_THIS_VOLATILE (expr) = true;
238	    }
239	  break;
240	}
241
242    default:
243      break;
244    }
245
246  for (int i = 0; i < 3; ++i)
247    if (recurse_op[i])
248      {
249	tree op = TREE_OPERAND (expr, i);
250	op = RECUR (op);
251	if (op == error_mark_node)
252	  return error_mark_node;
253	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
266tree
267mark_rvalue_use (tree e,
268		 location_t loc /* = UNKNOWN_LOCATION */,
269		 bool reject_builtin /* = true */)
270{
271  return mark_use (e, true, true, loc, reject_builtin);
272}
273
274/* Called whenever an expression is used in an lvalue context.  */
275
276tree
277mark_lvalue_use (tree expr)
278{
279  return mark_use (expr, false, true, input_location, false);
280}
281
282/* As above, but don't consider this use a read.  */
283
284tree
285mark_lvalue_use_nonread (tree expr)
286{
287  return mark_use (expr, false, false, input_location, false);
288}
289
290/* Called when expr appears as a discarded-value expression.  */
291
292tree
293mark_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  if (expr == NULL_TREE)
309    return expr;
310
311  STRIP_ANY_LOCATION_WRAPPER (expr);
312
313  switch (TREE_CODE (expr))
314    {
315    case COND_EXPR:
316      TREE_OPERAND (expr, 2) = mark_discarded_use (TREE_OPERAND (expr, 2));
317      gcc_fallthrough ();
318    case COMPOUND_EXPR:
319      TREE_OPERAND (expr, 1) = mark_discarded_use (TREE_OPERAND (expr, 1));
320      return expr;
321
322    case COMPONENT_REF:
323    case ARRAY_REF:
324    case INDIRECT_REF:
325    case MEMBER_REF:
326      break;
327    default:
328      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  return mark_use (expr, true, true, input_location, false);
336}
337
338/* Called whenever an expression is used in a type use context.  */
339
340tree
341mark_type_use (tree expr)
342{
343  mark_exp_read (expr);
344  return expr;
345}
346
347/* Mark EXP as read, not just set, for set but not used -Wunused
348   warning purposes.  */
349
350void
351mark_exp_read (tree exp)
352{
353  if (exp == NULL)
354    return;
355
356  switch (TREE_CODE (exp))
357    {
358    case VAR_DECL:
359      if (DECL_DECOMPOSITION_P (exp))
360	mark_exp_read (DECL_DECOMP_BASE (exp));
361      gcc_fallthrough ();
362    case PARM_DECL:
363      DECL_READ_P (exp) = 1;
364      break;
365    case ARRAY_REF:
366    case COMPONENT_REF:
367    case MODIFY_EXPR:
368    case REALPART_EXPR:
369    case IMAGPART_EXPR:
370    CASE_CONVERT:
371    case ADDR_EXPR:
372    case INDIRECT_REF:
373    case FLOAT_EXPR:
374    case NON_DEPENDENT_EXPR:
375    case VIEW_CONVERT_EXPR:
376      mark_exp_read (TREE_OPERAND (exp, 0));
377      break;
378    case COMPOUND_EXPR:
379      mark_exp_read (TREE_OPERAND (exp, 1));
380      break;
381    case COND_EXPR:
382      if (TREE_OPERAND (exp, 1))
383	mark_exp_read (TREE_OPERAND (exp, 1));
384      if (TREE_OPERAND (exp, 2))
385	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
395tree
396fold_for_warn (tree x)
397{
398  /* C++ implementation.  */
399
400  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  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  if (processing_template_decl)
413    {
414      tree f = fold_non_dependent_expr (x, tf_none);
415      if (f == error_mark_node)
416	return x;
417      else
418	return f;
419    }
420  else if (cxx_dialect >= cxx11)
421    x = maybe_constant_value (x);
422
423  return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
424}
425