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