LCOV - code coverage report
Current view: top level - gcc/cp - expr.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 193 193
Test Date: 2026-05-30 15:37:04 Functions: 100.0 % 10 10
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Convert language-specific tree expression to rtl instructions,
       2              :    for GNU compiler.
       3              :    Copyright (C) 1988-2026 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     95800300 : cplus_expand_constant (tree cst)
      31              : {
      32     95800300 :   switch (TREE_CODE (cst))
      33              :     {
      34        34601 :     case PTRMEM_CST:
      35        34601 :       {
      36        34601 :         tree type = TREE_TYPE (cst);
      37        34601 :         tree member;
      38              : 
      39              :         /* Find the member.  */
      40        34601 :         member = PTRMEM_CST_MEMBER (cst);
      41              : 
      42              :         /* We can't lower this until the class is complete.  */
      43        34601 :         if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
      44              :           return cst;
      45              : 
      46        34565 :         if (TREE_CODE (member) == FIELD_DECL)
      47              :           {
      48              :             /* Find the offset for the field.  */
      49         2895 :             cst = byte_position (member);
      50         5923 :             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          133 :                 member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
      57          133 :                                             DECL_CONTEXT (member));
      58          133 :                 cst = size_binop (PLUS_EXPR, cst, byte_position (member));
      59              :               }
      60         2895 :             cst = fold (build_nop (type, cst));
      61              :           }
      62              :         else
      63              :           {
      64        31670 :             tree delta;
      65        31670 :             tree pfn;
      66              : 
      67        31670 :             expand_ptrmemfunc_cst (cst, &delta, &pfn);
      68        31670 :             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     71161760 :         FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt)
      78     66020698 :           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   6616618326 : 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   6616618326 :   if (expr == NULL_TREE || error_operand_p (expr))
     100              :     return expr;
     101              : 
     102   6616613278 :   if (reject_builtin && reject_gcc_builtin (expr, loc))
     103           67 :     return error_mark_node;
     104              : 
     105   6616613211 :   if (TREE_TYPE (expr) && VOID_TYPE_P (TREE_TYPE (expr)))
     106              :     read_p = false;
     107              : 
     108   6503232604 :   if (read_p)
     109   6433426061 :     mark_exp_read (expr);
     110              : 
     111   6616613211 :   tree oexpr = expr;
     112   6616613211 :   bool recurse_op[3] = { false, false, false };
     113   6616613211 :   switch (TREE_CODE (expr))
     114              :     {
     115   1678898072 :     case VAR_DECL:
     116   1678898072 :     case PARM_DECL:
     117   1678898072 :       if (rvalue_p && is_normal_capture_proxy (expr))
     118              :         {
     119              :           /* Look through capture by copy.  */
     120      6701435 :           tree cap = DECL_CAPTURED_VARIABLE (expr);
     121      6701435 :           if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr))
     122      6701435 :               && decl_constant_var_p (cap))
     123              :             {
     124          184 :               tree val = RECUR (cap);
     125          184 :               if (!is_capture_proxy (val))
     126              :                 {
     127          145 :                   tree l = current_lambda_expr ();
     128          145 :                   LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
     129              :                 }
     130          184 :               return val;
     131              :             }
     132              :         }
     133   1678897888 :       if (outer_automatic_var_p (expr)
     134   1678897888 :           && decl_constant_var_p (expr))
     135              :         {
     136        86977 :           if (rvalue_p)
     137              :             {
     138        86968 :               tree t = maybe_constant_value (expr);
     139        86968 :               if (TREE_CONSTANT (t))
     140              :                 {
     141              :                   expr = t;
     142   6071062046 :                   break;
     143              :                 }
     144              :             }
     145           84 :           iloc_sentinel l (loc);
     146           84 :           expr = process_outer_var_ref (expr, tf_warning_or_error, true);
     147           84 :           if (!(TREE_TYPE (oexpr)
     148           84 :                 && TYPE_REF_P (TREE_TYPE (oexpr))))
     149           51 :             expr = convert_from_reference (expr);
     150           84 :         }
     151              :       break;
     152    151873785 :     case COMPONENT_REF:
     153    151873785 :       recurse_op[0] = true;
     154    151873785 :       break;
     155     13919114 :     case COMPOUND_EXPR:
     156     13919114 :       recurse_op[1] = true;
     157     13919114 :       break;
     158     18079055 :     case COND_EXPR:
     159     18079055 :       recurse_op[2] = true;
     160     18079055 :       if (TREE_OPERAND (expr, 1))
     161     18079016 :         recurse_op[1] = true;
     162              :       break;
     163    352623894 :     case INDIRECT_REF:
     164    352623894 :       if (REFERENCE_REF_P (expr))
     165              :         {
     166              :           /* Try to look through the reference.  */
     167    194720643 :           tree ref = TREE_OPERAND (expr, 0);
     168    194720643 :           if (rvalue_p && is_normal_capture_proxy (ref))
     169              :             {
     170              :               /* Look through capture by reference.  */
     171       720997 :               tree cap = DECL_CAPTURED_VARIABLE (ref);
     172       720997 :               if (!TYPE_REF_P (TREE_TYPE (cap))
     173       720997 :                   && decl_constant_var_p (cap))
     174              :                 {
     175         1733 :                   tree val = RECUR (cap);
     176         1733 :                   if (!is_capture_proxy (val))
     177              :                     {
     178         1733 :                       tree l = current_lambda_expr ();
     179         1733 :                       LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
     180              :                     }
     181         1733 :                   return val;
     182              :                 }
     183              :             }
     184    194718910 :           tree r = mark_rvalue_use (ref, loc, reject_builtin);
     185    194718910 :           if (r == error_mark_node)
     186              :             return error_mark_node;
     187    194718901 :           if (r != ref)
     188              :             {
     189           33 :               if (!rvalue_p)
     190              :                 {
     191              :                   /* Make sure we still return an lvalue.  */
     192           30 :                   gcc_assert (TREE_CODE (r) == NOP_EXPR);
     193           30 :                   TREE_TYPE (r) = cp_build_reference_type (TREE_TYPE (r),
     194              :                                                            false);
     195              :                 }
     196           33 :               expr = convert_from_reference (r);
     197              :             }
     198              :         }
     199              :       break;
     200              : 
     201    555088703 :     case VIEW_CONVERT_EXPR:
     202    555088703 :       if (location_wrapper_p (expr))
     203              :         {
     204    545549239 :           loc = EXPR_LOCATION (expr);
     205    545549239 :           tree op = TREE_OPERAND (expr, 0);
     206    545549239 :           tree nop = RECUR (op);
     207    545549239 :           if (nop == error_mark_node)
     208              :             return error_mark_node;
     209    545549227 :           else if (op == nop)
     210              :             /* No change.  */;
     211          610 :           else if (DECL_P (nop) || CONSTANT_CLASS_P (nop))
     212              :             {
     213              :               /* Reuse the location wrapper.  */
     214          581 :               TREE_OPERAND (expr, 0) = nop;
     215              :               /* If we're replacing a DECL with a constant, we also need to
     216              :                  change the TREE_CODE of the location wrapper.  */
     217          581 :               if (rvalue_p)
     218          581 :                 TREE_SET_CODE (expr, NON_LVALUE_EXPR);
     219              :             }
     220              :           else
     221              :             {
     222              :               /* Drop the location wrapper.  */
     223           29 :               expr = nop;
     224           29 :               protected_set_expr_location (expr, loc);
     225              :             }
     226    545549227 :           return expr;
     227              :         }
     228    781168302 :       gcc_fallthrough ();
     229    781168302 :     CASE_CONVERT:
     230    781168302 :       recurse_op[0] = true;
     231    781168302 :       break;
     232              : 
     233      2994424 :     case MODIFY_EXPR:
     234      2994424 :         {
     235      2994424 :           tree lhs = TREE_OPERAND (expr, 0);
     236              :           /* [expr.ass] "An assignment whose left operand is of
     237              :              a volatile-qualified type is deprecated unless the assignment
     238              :              is either a discarded-value expression or appears in an
     239              :              unevaluated context."  */
     240      2994424 :           if (!cp_unevaluated_operand
     241      2994298 :               && (TREE_THIS_VOLATILE (lhs)
     242      2993331 :                   || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs)))
     243      2995391 :               && !TREE_THIS_VOLATILE (expr))
     244              :             {
     245          581 :               if (warning_at (location_of (expr), OPT_Wvolatile,
     246              :                               "using value of assignment with "
     247              :                               "%<volatile%>-qualified left operand is "
     248              :                               "deprecated"))
     249              :                 /* Make sure not to warn about this assignment again.  */
     250           90 :                 TREE_THIS_VOLATILE (expr) = true;
     251              :             }
     252              :           break;
     253              :         }
     254              : 
     255              :     default:
     256              :       break;
     257              :     }
     258              : 
     259  24284248166 :   for (int i = 0; i < 3; ++i)
     260  18213186126 :     if (recurse_op[i])
     261              :       {
     262    983119272 :         tree op = TREE_OPERAND (expr, i);
     263    983119272 :         op = RECUR (op);
     264    983119272 :         if (op == error_mark_node)
     265              :           return error_mark_node;
     266    983119266 :         TREE_OPERAND (expr, i) = op;
     267              :       }
     268              : 
     269              :   return expr;
     270              : #undef RECUR
     271              : }
     272              : 
     273              : /* Called whenever the expression EXPR is used in an rvalue context.
     274              :    When REJECT_BUILTIN is true the expression is checked to make sure
     275              :    it doesn't make it possible to obtain the address of a GCC built-in
     276              :    function with no library fallback (or any of its bits, such as in
     277              :    a conversion to bool).  */
     278              : 
     279              : tree
     280   3925228715 : mark_rvalue_use (tree e,
     281              :                  location_t loc /* = UNKNOWN_LOCATION */,
     282              :                  bool reject_builtin /* = true */)
     283              : {
     284   3925228715 :   return mark_use (e, true, true, loc, reject_builtin);
     285              : }
     286              : 
     287              : /* Called whenever an expression is used in an lvalue context.  */
     288              : 
     289              : tree
     290    393414425 : mark_lvalue_use (tree expr)
     291              : {
     292    393414425 :   return mark_use (expr, false, true, input_location, false);
     293              : }
     294              : 
     295              : /* As above, but don't consider this use a read.  */
     296              : 
     297              : tree
     298     37269933 : mark_lvalue_use_nonread (tree expr)
     299              : {
     300     37269933 :   return mark_use (expr, false, false, input_location, false);
     301              : }
     302              : 
     303              : /* Called when expr appears as a discarded-value expression.  */
     304              : 
     305              : tree
     306     72620422 : mark_discarded_use (tree expr)
     307              : {
     308              :   /* The lvalue-to-rvalue conversion (7.1) is applied if and only if the
     309              :      expression is a glvalue of volatile-qualified type and it is one of the
     310              :      following:
     311              :      * ( expression ), where expression is one of these expressions,
     312              :      * id-expression (8.1.4),
     313              :      * subscripting (8.2.1),
     314              :      * class member access (8.2.5),
     315              :      * indirection (8.3.1),
     316              :      * pointer-to-member operation (8.5),
     317              :      * conditional expression (8.16) where both the second and the third
     318              :        operands are one of these expressions, or
     319              :      * comma expression (8.19) where the right operand is one of these
     320              :        expressions.  */
     321     72620422 :   if (expr == NULL_TREE)
     322              :     return expr;
     323              : 
     324     72620416 :   STRIP_ANY_LOCATION_WRAPPER (expr);
     325              : 
     326     72620416 :   switch (TREE_CODE (expr))
     327              :     {
     328       122513 :     case COND_EXPR:
     329       122513 :       TREE_OPERAND (expr, 2) = mark_discarded_use (TREE_OPERAND (expr, 2));
     330       593572 :       gcc_fallthrough ();
     331       593572 :     case COMPOUND_EXPR:
     332       593572 :       TREE_OPERAND (expr, 1) = mark_discarded_use (TREE_OPERAND (expr, 1));
     333       593572 :       return expr;
     334              : 
     335              :     case COMPONENT_REF:
     336              :     case ARRAY_REF:
     337              :     case INDIRECT_REF:
     338              :     case MEMBER_REF:
     339              :       break;
     340     64760186 :     default:
     341     64760186 :       if (DECL_P (expr))
     342              :         break;
     343              :       else
     344              :         return expr;
     345              :     }
     346              : 
     347              :   /* Like mark_rvalue_use, but don't reject built-ins.  */
     348      7295158 :   return mark_use (expr, true, true, input_location, false);
     349              : }
     350              : 
     351              : /* Called whenever an expression is used in a type use context.  */
     352              : 
     353              : tree
     354    114985073 : mark_type_use (tree expr)
     355              : {
     356    114985073 :   mark_exp_read (expr);
     357    114985073 :   return expr;
     358              : }
     359              : 
     360              : /* Mark EXP as read, not just set, for set but not used -Wunused
     361              :    warning purposes.  */
     362              : 
     363              : void
     364   6969857200 : mark_exp_read (tree exp)
     365              : {
     366  10451734085 :   if (exp == NULL)
     367              :     return;
     368              : 
     369  10447155498 :   if (TREE_TYPE (exp) && VOID_TYPE_P (TREE_TYPE (exp)))
     370              :     return;
     371              : 
     372  10320386589 :   switch (TREE_CODE (exp))
     373              :     {
     374   1183117515 :     case VAR_DECL:
     375   1183117515 :       if (DECL_DECOMPOSITION_P (exp))
     376      7970593 :         mark_exp_read (DECL_DECOMP_BASE (exp));
     377   3439207014 :       gcc_fallthrough ();
     378   3439207014 :     case PARM_DECL:
     379   3439207014 :       DECL_READ_P (exp) = 1;
     380   3439207014 :       break;
     381   3434270909 :     CASE_CONVERT:
     382   3434270909 :     case ARRAY_REF:
     383   3434270909 :     case COMPONENT_REF:
     384   3434270909 :     case MODIFY_EXPR:
     385   3434270909 :     case REALPART_EXPR:
     386   3434270909 :     case IMAGPART_EXPR:
     387   3434270909 :     case ADDR_EXPR:
     388   3434270909 :     case INDIRECT_REF:
     389   3434270909 :     case FLOAT_EXPR:
     390   3434270909 :     case VIEW_CONVERT_EXPR:
     391   3434270909 :     case PREINCREMENT_EXPR:
     392   3434270909 :     case PREDECREMENT_EXPR:
     393   3434270909 :     case POSTINCREMENT_EXPR:
     394   3434270909 :     case POSTDECREMENT_EXPR:
     395   3434270909 :       mark_exp_read (TREE_OPERAND (exp, 0));
     396   3434270909 :       break;
     397     22690962 :     case COMPOUND_EXPR:
     398     22690962 :       mark_exp_read (TREE_OPERAND (exp, 1));
     399     22690962 :       break;
     400     24915014 :     case COND_EXPR:
     401     24915014 :       if (TREE_OPERAND (exp, 1))
     402     24914965 :         mark_exp_read (TREE_OPERAND (exp, 1));
     403     24915014 :       if (TREE_OPERAND (exp, 2))
     404     24915014 :         mark_exp_read (TREE_OPERAND (exp, 2));
     405              :       break;
     406              :     default:
     407              :       break;
     408              :     }
     409              : }
     410              : 
     411              : /* Fold X for consideration by one of the warning functions when checking
     412              :    whether an expression has a constant value.  */
     413              : 
     414              : tree
     415     76860890 : fold_for_warn (tree x)
     416              : {
     417              :   /* C++ implementation.  */
     418              : 
     419     76860890 :   if (cp_unevaluated_operand)
     420              :     /* In an unevaluated context we don't care about the reduced value
     421              :        of an expression, so neither should any warnings.  */
     422              :     return x;
     423              : 
     424              :   /* Prevent warning-dependent constexpr evaluation from changing
     425              :      DECL_UID (which breaks -fcompare-debug) and from instantiating
     426              :      templates.  */
     427     76807774 :   uid_sensitive_constexpr_evaluation_sentinel s;
     428              : 
     429              :   /* It's not generally safe to fully fold inside of a template, so
     430              :      call fold_non_dependent_expr instead.  */
     431     76807774 :   if (processing_template_decl)
     432              :     {
     433      3821398 :       tree f = fold_non_dependent_expr (x, tf_none);
     434      3821398 :       if (f == error_mark_node)
     435              :         return x;
     436              :       else
     437      3821396 :         return f;
     438              :     }
     439     72986376 :   else if (cxx_dialect >= cxx11)
     440     72505605 :     x = maybe_constant_value (x);
     441              : 
     442     72986376 :   return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
     443     76807774 : }
     444              : 
     445              : /* Make EXPR only execute during constant evaluation by wrapping it in a
     446              :    statement-expression containing 'if consteval'.  */
     447              : 
     448              : tree
     449            1 : wrap_with_if_consteval (tree expr)
     450              : {
     451            1 :   tree stmtex = begin_stmt_expr ();
     452            1 :   tree ifcev = begin_if_stmt ();
     453            1 :   IF_STMT_CONSTEVAL_P (ifcev) = true;
     454            1 :   finish_if_stmt_cond (boolean_false_node, ifcev);
     455            1 :   finish_expr_stmt (expr);
     456            1 :   finish_then_clause (ifcev);
     457            1 :   finish_if_stmt (ifcev);
     458            1 :   return finish_stmt_expr (stmtex, /*no scope*/true);
     459              : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.