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 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 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 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 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 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 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 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 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 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