LCOV - code coverage report
Current view: top level - gcc/cp - expr.cc (source / functions) Hit Total Coverage
Test: gcc.info Lines: 176 177 99.4 %
Date: 2023-07-19 08:18:47 Functions: 9 9 100.0 %

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

Generated by: LCOV version 1.16