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