xref: /dflybsd-src/contrib/gcc-8.0/gcc/cp/expr.c (revision 95059079af47f9a66a175f374f2da1a5020e3255)
138fd1498Szrj /* Convert language-specific tree expression to rtl instructions,
238fd1498Szrj    for GNU compiler.
338fd1498Szrj    Copyright (C) 1988-2018 Free Software Foundation, Inc.
438fd1498Szrj 
538fd1498Szrj This file is part of GCC.
638fd1498Szrj 
738fd1498Szrj GCC is free software; you can redistribute it and/or modify
838fd1498Szrj it under the terms of the GNU General Public License as published by
938fd1498Szrj the Free Software Foundation; either version 3, or (at your option)
1038fd1498Szrj any later version.
1138fd1498Szrj 
1238fd1498Szrj GCC is distributed in the hope that it will be useful,
1338fd1498Szrj but WITHOUT ANY WARRANTY; without even the implied warranty of
1438fd1498Szrj MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1538fd1498Szrj GNU General Public License for more details.
1638fd1498Szrj 
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3.  If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>.  */
2038fd1498Szrj 
2138fd1498Szrj 
2238fd1498Szrj #include "config.h"
2338fd1498Szrj #include "system.h"
2438fd1498Szrj #include "coretypes.h"
2538fd1498Szrj #include "cp-tree.h"
2638fd1498Szrj 
2738fd1498Szrj /* Expand C++-specific constants.  Currently, this means PTRMEM_CST.  */
2838fd1498Szrj 
2938fd1498Szrj tree
cplus_expand_constant(tree cst)3038fd1498Szrj cplus_expand_constant (tree cst)
3138fd1498Szrj {
3238fd1498Szrj   switch (TREE_CODE (cst))
3338fd1498Szrj     {
3438fd1498Szrj     case PTRMEM_CST:
3538fd1498Szrj       {
3638fd1498Szrj 	tree type = TREE_TYPE (cst);
3738fd1498Szrj 	tree member;
3838fd1498Szrj 
3938fd1498Szrj 	/* Find the member.  */
4038fd1498Szrj 	member = PTRMEM_CST_MEMBER (cst);
4138fd1498Szrj 
4238fd1498Szrj 	/* We can't lower this until the class is complete.  */
4338fd1498Szrj 	if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
4438fd1498Szrj 	  return cst;
4538fd1498Szrj 
4638fd1498Szrj 	if (TREE_CODE (member) == FIELD_DECL)
4738fd1498Szrj 	  {
4838fd1498Szrj 	    /* Find the offset for the field.  */
4938fd1498Szrj 	    cst = byte_position (member);
5038fd1498Szrj 	    while (!same_type_p (DECL_CONTEXT (member),
5138fd1498Szrj 				 TYPE_PTRMEM_CLASS_TYPE (type)))
5238fd1498Szrj 	      {
5338fd1498Szrj 		/* The MEMBER must have been nestled within an
5438fd1498Szrj 		   anonymous aggregate contained in TYPE.  Find the
5538fd1498Szrj 		   anonymous aggregate.  */
5638fd1498Szrj 		member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
5738fd1498Szrj 					    DECL_CONTEXT (member));
5838fd1498Szrj 		cst = size_binop (PLUS_EXPR, cst, byte_position (member));
5938fd1498Szrj 	      }
6038fd1498Szrj 	    cst = fold (build_nop (type, cst));
6138fd1498Szrj 	  }
6238fd1498Szrj 	else
6338fd1498Szrj 	  {
6438fd1498Szrj 	    tree delta;
6538fd1498Szrj 	    tree pfn;
6638fd1498Szrj 
6738fd1498Szrj 	    expand_ptrmemfunc_cst (cst, &delta, &pfn);
6838fd1498Szrj 	    cst = build_ptrmemfunc1 (type, delta, pfn);
6938fd1498Szrj 	  }
7038fd1498Szrj       }
7138fd1498Szrj       break;
7238fd1498Szrj 
7338fd1498Szrj     case CONSTRUCTOR:
7438fd1498Szrj       {
7538fd1498Szrj 	constructor_elt *elt;
7638fd1498Szrj 	unsigned HOST_WIDE_INT idx;
7738fd1498Szrj 	FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt)
7838fd1498Szrj 	  elt->value = cplus_expand_constant (elt->value);
7938fd1498Szrj       }
8038fd1498Szrj 
8138fd1498Szrj     default:
8238fd1498Szrj       /* There's nothing to do.  */
8338fd1498Szrj       break;
8438fd1498Szrj     }
8538fd1498Szrj 
8638fd1498Szrj   return cst;
8738fd1498Szrj }
8838fd1498Szrj 
8938fd1498Szrj /* We've seen an actual use of EXPR.  Possibly replace an outer variable
9038fd1498Szrj    reference inside with its constant value or a lambda capture.  */
9138fd1498Szrj 
9238fd1498Szrj tree
mark_use(tree expr,bool rvalue_p,bool read_p,location_t loc,bool reject_builtin)9338fd1498Szrj mark_use (tree expr, bool rvalue_p, bool read_p,
9438fd1498Szrj 	  location_t loc /* = UNKNOWN_LOCATION */,
9538fd1498Szrj 	  bool reject_builtin /* = true */)
9638fd1498Szrj {
9738fd1498Szrj #define RECUR(t) mark_use ((t), rvalue_p, read_p, loc, reject_builtin)
9838fd1498Szrj 
9938fd1498Szrj   if (expr == NULL_TREE || expr == error_mark_node)
10038fd1498Szrj     return expr;
10138fd1498Szrj 
10238fd1498Szrj   if (reject_builtin && reject_gcc_builtin (expr, loc))
10338fd1498Szrj     return error_mark_node;
10438fd1498Szrj 
10538fd1498Szrj   if (read_p)
10638fd1498Szrj     mark_exp_read (expr);
10738fd1498Szrj 
10838fd1498Szrj   tree oexpr = expr;
10938fd1498Szrj   bool recurse_op[3] = { false, false, false };
11038fd1498Szrj   switch (TREE_CODE (expr))
11138fd1498Szrj     {
11238fd1498Szrj     case VAR_DECL:
11338fd1498Szrj     case PARM_DECL:
11438fd1498Szrj       if (rvalue_p && is_normal_capture_proxy (expr))
11538fd1498Szrj 	{
11638fd1498Szrj 	  /* Look through capture by copy.  */
11738fd1498Szrj 	  tree cap = DECL_CAPTURED_VARIABLE (expr);
11838fd1498Szrj 	  if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr))
11938fd1498Szrj 	      && decl_constant_var_p (cap))
12038fd1498Szrj 	    {
12138fd1498Szrj 	      tree val = RECUR (cap);
12238fd1498Szrj 	      if (!is_capture_proxy (val))
12338fd1498Szrj 		{
12438fd1498Szrj 		  tree l = current_lambda_expr ();
12538fd1498Szrj 		  LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
12638fd1498Szrj 		}
12738fd1498Szrj 	      return val;
12838fd1498Szrj 	    }
12938fd1498Szrj 	}
13038fd1498Szrj       if (outer_automatic_var_p (expr)
13138fd1498Szrj 	  && decl_constant_var_p (expr))
13238fd1498Szrj 	{
13338fd1498Szrj 	  if (rvalue_p)
13438fd1498Szrj 	    {
13538fd1498Szrj 	      tree t = maybe_constant_value (expr);
13638fd1498Szrj 	      if (TREE_CONSTANT (t))
13738fd1498Szrj 		{
13838fd1498Szrj 		  expr = t;
13938fd1498Szrj 		  break;
14038fd1498Szrj 		}
14138fd1498Szrj 	    }
142*58e805e6Szrj 	  temp_override<location_t> l (input_location);
143*58e805e6Szrj 	  if (loc != UNKNOWN_LOCATION)
144*58e805e6Szrj 	    input_location = loc;
14538fd1498Szrj 	  expr = process_outer_var_ref (expr, tf_warning_or_error, true);
14638fd1498Szrj 	  if (!(TREE_TYPE (oexpr)
14738fd1498Szrj 		&& TREE_CODE (TREE_TYPE (oexpr)) == REFERENCE_TYPE))
14838fd1498Szrj 	    expr = convert_from_reference (expr);
14938fd1498Szrj 	}
15038fd1498Szrj       break;
15138fd1498Szrj     case COMPONENT_REF:
15238fd1498Szrj     case NON_DEPENDENT_EXPR:
15338fd1498Szrj       recurse_op[0] = true;
15438fd1498Szrj       break;
15538fd1498Szrj     case COMPOUND_EXPR:
15638fd1498Szrj       recurse_op[1] = true;
15738fd1498Szrj       break;
15838fd1498Szrj     case COND_EXPR:
15938fd1498Szrj       recurse_op[2] = true;
16038fd1498Szrj       if (TREE_OPERAND (expr, 1))
16138fd1498Szrj 	recurse_op[1] = true;
16238fd1498Szrj       break;
16338fd1498Szrj     case INDIRECT_REF:
16438fd1498Szrj       if (REFERENCE_REF_P (expr))
16538fd1498Szrj 	{
16638fd1498Szrj 	  /* Try to look through the reference.  */
16738fd1498Szrj 	  tree ref = TREE_OPERAND (expr, 0);
16838fd1498Szrj 	  if (rvalue_p && is_normal_capture_proxy (ref))
16938fd1498Szrj 	    {
17038fd1498Szrj 	      /* Look through capture by reference.  */
17138fd1498Szrj 	      tree cap = DECL_CAPTURED_VARIABLE (ref);
17238fd1498Szrj 	      if (TREE_CODE (TREE_TYPE (cap)) != REFERENCE_TYPE
17338fd1498Szrj 		  && decl_constant_var_p (cap))
17438fd1498Szrj 		{
17538fd1498Szrj 		  tree val = RECUR (cap);
17638fd1498Szrj 		  if (!is_capture_proxy (val))
17738fd1498Szrj 		    {
17838fd1498Szrj 		      tree l = current_lambda_expr ();
17938fd1498Szrj 		      LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
18038fd1498Szrj 		    }
18138fd1498Szrj 		  return val;
18238fd1498Szrj 		}
18338fd1498Szrj 	    }
18438fd1498Szrj 	  tree r = mark_rvalue_use (ref, loc, reject_builtin);
18538fd1498Szrj 	  if (r != ref)
18638fd1498Szrj 	    expr = convert_from_reference (r);
18738fd1498Szrj 	}
18838fd1498Szrj       break;
189*58e805e6Szrj 
190*58e805e6Szrj     CASE_CONVERT:
191*58e805e6Szrj     case VIEW_CONVERT_EXPR:
192*58e805e6Szrj       if (location_wrapper_p (expr))
193*58e805e6Szrj 	loc = EXPR_LOCATION (expr);
194*58e805e6Szrj       recurse_op[0] = true;
195*58e805e6Szrj       break;
196*58e805e6Szrj 
19738fd1498Szrj     default:
19838fd1498Szrj       break;
19938fd1498Szrj     }
20038fd1498Szrj 
20138fd1498Szrj   for (int i = 0; i < 3; ++i)
20238fd1498Szrj     if (recurse_op[i])
20338fd1498Szrj       {
20438fd1498Szrj 	tree op = TREE_OPERAND (expr, i);
20538fd1498Szrj 	op = RECUR (op);
20638fd1498Szrj 	if (op == error_mark_node)
20738fd1498Szrj 	  return error_mark_node;
20838fd1498Szrj 	TREE_OPERAND (expr, i) = op;
20938fd1498Szrj       }
21038fd1498Szrj 
21138fd1498Szrj   return expr;
21238fd1498Szrj #undef RECUR
21338fd1498Szrj }
21438fd1498Szrj 
21538fd1498Szrj /* Called whenever the expression EXPR is used in an rvalue context.
21638fd1498Szrj    When REJECT_BUILTIN is true the expression is checked to make sure
21738fd1498Szrj    it doesn't make it possible to obtain the address of a GCC built-in
21838fd1498Szrj    function with no library fallback (or any of its bits, such as in
21938fd1498Szrj    a conversion to bool).  */
22038fd1498Szrj 
22138fd1498Szrj tree
mark_rvalue_use(tree e,location_t loc,bool reject_builtin)22238fd1498Szrj mark_rvalue_use (tree e,
22338fd1498Szrj 		 location_t loc /* = UNKNOWN_LOCATION */,
22438fd1498Szrj 		 bool reject_builtin /* = true */)
22538fd1498Szrj {
22638fd1498Szrj   return mark_use (e, true, true, loc, reject_builtin);
22738fd1498Szrj }
22838fd1498Szrj 
22938fd1498Szrj /* Called whenever an expression is used in an lvalue context.  */
23038fd1498Szrj 
23138fd1498Szrj tree
mark_lvalue_use(tree expr)23238fd1498Szrj mark_lvalue_use (tree expr)
23338fd1498Szrj {
23438fd1498Szrj   return mark_use (expr, false, true, input_location, false);
23538fd1498Szrj }
23638fd1498Szrj 
23738fd1498Szrj /* As above, but don't consider this use a read.  */
23838fd1498Szrj 
23938fd1498Szrj tree
mark_lvalue_use_nonread(tree expr)24038fd1498Szrj mark_lvalue_use_nonread (tree expr)
24138fd1498Szrj {
24238fd1498Szrj   return mark_use (expr, false, false, input_location, false);
24338fd1498Szrj }
24438fd1498Szrj 
24538fd1498Szrj /* Called when expr appears as a discarded-value expression.  */
24638fd1498Szrj 
24738fd1498Szrj tree
mark_discarded_use(tree expr)24838fd1498Szrj mark_discarded_use (tree expr)
24938fd1498Szrj {
25038fd1498Szrj   /* The lvalue-to-rvalue conversion (7.1) is applied if and only if the
25138fd1498Szrj      expression is a glvalue of volatile-qualified type and it is one of the
25238fd1498Szrj      following:
25338fd1498Szrj      * ( expression ), where expression is one of these expressions,
25438fd1498Szrj      * id-expression (8.1.4),
25538fd1498Szrj      * subscripting (8.2.1),
25638fd1498Szrj      * class member access (8.2.5),
25738fd1498Szrj      * indirection (8.3.1),
25838fd1498Szrj      * pointer-to-member operation (8.5),
25938fd1498Szrj      * conditional expression (8.16) where both the second and the third
26038fd1498Szrj        operands are one of these expressions, or
26138fd1498Szrj      * comma expression (8.19) where the right operand is one of these
26238fd1498Szrj        expressions.  */
26338fd1498Szrj   if (expr == NULL_TREE)
26438fd1498Szrj     return expr;
26538fd1498Szrj 
26638fd1498Szrj   switch (TREE_CODE (expr))
26738fd1498Szrj     {
26838fd1498Szrj     case COND_EXPR:
26938fd1498Szrj       TREE_OPERAND (expr, 2) = mark_discarded_use (TREE_OPERAND (expr, 2));
27038fd1498Szrj       gcc_fallthrough ();
27138fd1498Szrj     case COMPOUND_EXPR:
27238fd1498Szrj       TREE_OPERAND (expr, 1) = mark_discarded_use (TREE_OPERAND (expr, 1));
27338fd1498Szrj       return expr;
27438fd1498Szrj 
27538fd1498Szrj     case COMPONENT_REF:
27638fd1498Szrj     case ARRAY_REF:
27738fd1498Szrj     case INDIRECT_REF:
27838fd1498Szrj     case MEMBER_REF:
27938fd1498Szrj       break;
28038fd1498Szrj     default:
28138fd1498Szrj       if (DECL_P (expr))
28238fd1498Szrj 	break;
28338fd1498Szrj       else
28438fd1498Szrj 	return expr;
28538fd1498Szrj     }
28638fd1498Szrj 
28738fd1498Szrj   /* Like mark_rvalue_use, but don't reject built-ins.  */
28838fd1498Szrj   return mark_use (expr, true, true, input_location, false);
28938fd1498Szrj }
29038fd1498Szrj 
29138fd1498Szrj /* Called whenever an expression is used in a type use context.  */
29238fd1498Szrj 
29338fd1498Szrj tree
mark_type_use(tree expr)29438fd1498Szrj mark_type_use (tree expr)
29538fd1498Szrj {
29638fd1498Szrj   mark_exp_read (expr);
29738fd1498Szrj   return expr;
29838fd1498Szrj }
29938fd1498Szrj 
30038fd1498Szrj /* Mark EXP as read, not just set, for set but not used -Wunused
30138fd1498Szrj    warning purposes.  */
30238fd1498Szrj 
30338fd1498Szrj void
mark_exp_read(tree exp)30438fd1498Szrj mark_exp_read (tree exp)
30538fd1498Szrj {
30638fd1498Szrj   if (exp == NULL)
30738fd1498Szrj     return;
30838fd1498Szrj 
30938fd1498Szrj   switch (TREE_CODE (exp))
31038fd1498Szrj     {
31138fd1498Szrj     case VAR_DECL:
31238fd1498Szrj       if (DECL_DECOMPOSITION_P (exp))
31338fd1498Szrj 	mark_exp_read (DECL_DECOMP_BASE (exp));
31438fd1498Szrj       gcc_fallthrough ();
31538fd1498Szrj     case PARM_DECL:
31638fd1498Szrj       DECL_READ_P (exp) = 1;
31738fd1498Szrj       break;
31838fd1498Szrj     case ARRAY_REF:
31938fd1498Szrj     case COMPONENT_REF:
32038fd1498Szrj     case MODIFY_EXPR:
32138fd1498Szrj     case REALPART_EXPR:
32238fd1498Szrj     case IMAGPART_EXPR:
32338fd1498Szrj     CASE_CONVERT:
32438fd1498Szrj     case ADDR_EXPR:
32538fd1498Szrj     case INDIRECT_REF:
32638fd1498Szrj     case FLOAT_EXPR:
32738fd1498Szrj     case NON_DEPENDENT_EXPR:
32838fd1498Szrj     case VIEW_CONVERT_EXPR:
32938fd1498Szrj       mark_exp_read (TREE_OPERAND (exp, 0));
33038fd1498Szrj       break;
33138fd1498Szrj     case COMPOUND_EXPR:
33238fd1498Szrj       mark_exp_read (TREE_OPERAND (exp, 1));
33338fd1498Szrj       break;
33438fd1498Szrj     case COND_EXPR:
33538fd1498Szrj       if (TREE_OPERAND (exp, 1))
33638fd1498Szrj 	mark_exp_read (TREE_OPERAND (exp, 1));
33738fd1498Szrj       if (TREE_OPERAND (exp, 2))
33838fd1498Szrj 	mark_exp_read (TREE_OPERAND (exp, 2));
33938fd1498Szrj       break;
34038fd1498Szrj     default:
34138fd1498Szrj       break;
34238fd1498Szrj     }
34338fd1498Szrj }
34438fd1498Szrj 
34538fd1498Szrj /* Fold X for consideration by one of the warning functions when checking
34638fd1498Szrj    whether an expression has a constant value.  */
34738fd1498Szrj 
34838fd1498Szrj tree
fold_for_warn(tree x)34938fd1498Szrj fold_for_warn (tree x)
35038fd1498Szrj {
35138fd1498Szrj   /* C++ implementation.  */
35238fd1498Szrj 
35338fd1498Szrj   /* It's not generally safe to fully fold inside of a template, so
35438fd1498Szrj      call fold_non_dependent_expr instead.  */
35538fd1498Szrj   if (processing_template_decl)
35638fd1498Szrj     return fold_non_dependent_expr (x);
35738fd1498Szrj 
35838fd1498Szrj   return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
35938fd1498Szrj }
360