LCOV - code coverage report
Current view: top level - gcc/cp - expr.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 192 192
Test Date: 2026-02-28 14:20:25 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    100672139 : cplus_expand_constant (tree cst)
      31              : {
      32    100672139 :   switch (TREE_CODE (cst))
      33              :     {
      34        34326 :     case PTRMEM_CST:
      35        34326 :       {
      36        34326 :         tree type = TREE_TYPE (cst);
      37        34326 :         tree member;
      38              : 
      39              :         /* Find the member.  */
      40        34326 :         member = PTRMEM_CST_MEMBER (cst);
      41              : 
      42              :         /* We can't lower this until the class is complete.  */
      43        34326 :         if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
      44              :           return cst;
      45              : 
      46        34293 :         if (TREE_CODE (member) == FIELD_DECL)
      47              :           {
      48              :             /* Find the offset for the field.  */
      49         2919 :             cst = byte_position (member);
      50         5971 :             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         2919 :             cst = fold (build_nop (type, cst));
      61              :           }
      62              :         else
      63              :           {
      64        31374 :             tree delta;
      65        31374 :             tree pfn;
      66              : 
      67        31374 :             expand_ptrmemfunc_cst (cst, &delta, &pfn);
      68        31374 :             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     71410229 :         FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt)
      78     66050211 :           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   8297778903 : 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   8297778903 :   if (expr == NULL_TREE || error_operand_p (expr))
     100              :     return expr;
     101              : 
     102   8297773940 :   if (reject_builtin && reject_gcc_builtin (expr, loc))
     103           67 :     return error_mark_node;
     104              : 
     105   8297773873 :   if (TREE_TYPE (expr) && VOID_TYPE_P (TREE_TYPE (expr)))
     106              :     read_p = false;
     107              : 
     108   8141647583 :   if (read_p)
     109   8054272398 :     mark_exp_read (expr);
     110              : 
     111   8297773873 :   tree oexpr = expr;
     112   8297773873 :   bool recurse_op[3] = { false, false, false };
     113   8297773873 :   switch (TREE_CODE (expr))
     114              :     {
     115   2007583861 :     case VAR_DECL:
     116   2007583861 :     case PARM_DECL:
     117   2007583861 :       if (rvalue_p && is_normal_capture_proxy (expr))
     118              :         {
     119              :           /* Look through capture by copy.  */
     120     21770755 :           tree cap = DECL_CAPTURED_VARIABLE (expr);
     121     21770755 :           if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr))
     122     21770755 :               && 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   2007583677 :       if (outer_automatic_var_p (expr)
     134   2007583677 :           && decl_constant_var_p (expr))
     135              :         {
     136        84161 :           if (rvalue_p)
     137              :             {
     138        84152 :               tree t = maybe_constant_value (expr);
     139        84152 :               if (TREE_CONSTANT (t))
     140              :                 {
     141              :                   expr = t;
     142   7635021523 :                   break;
     143              :                 }
     144              :             }
     145           69 :           iloc_sentinel l (loc);
     146           69 :           expr = process_outer_var_ref (expr, tf_warning_or_error, true);
     147           69 :           if (!(TREE_TYPE (oexpr)
     148           69 :                 && TYPE_REF_P (TREE_TYPE (oexpr))))
     149           51 :             expr = convert_from_reference (expr);
     150           69 :         }
     151              :       break;
     152    229177134 :     case COMPONENT_REF:
     153    229177134 :       recurse_op[0] = true;
     154    229177134 :       break;
     155     15084493 :     case COMPOUND_EXPR:
     156     15084493 :       recurse_op[1] = true;
     157     15084493 :       break;
     158     20678331 :     case COND_EXPR:
     159     20678331 :       recurse_op[2] = true;
     160     20678331 :       if (TREE_OPERAND (expr, 1))
     161     20678292 :         recurse_op[1] = true;
     162              :       break;
     163    516785148 :     case INDIRECT_REF:
     164    516785148 :       if (REFERENCE_REF_P (expr))
     165              :         {
     166              :           /* Try to look through the reference.  */
     167    290698858 :           tree ref = TREE_OPERAND (expr, 0);
     168    290698858 :           if (rvalue_p && is_normal_capture_proxy (ref))
     169              :             {
     170              :               /* Look through capture by reference.  */
     171      4912512 :               tree cap = DECL_CAPTURED_VARIABLE (ref);
     172      4912512 :               if (!TYPE_REF_P (TREE_TYPE (cap))
     173      4912512 :                   && decl_constant_var_p (cap))
     174              :                 {
     175         1232 :                   tree val = RECUR (cap);
     176         1232 :                   if (!is_capture_proxy (val))
     177              :                     {
     178         1232 :                       tree l = current_lambda_expr ();
     179         1232 :                       LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
     180              :                     }
     181         1232 :                   return val;
     182              :                 }
     183              :             }
     184    290697626 :           tree r = mark_rvalue_use (ref, loc, reject_builtin);
     185    290697626 :           if (r != ref)
     186              :             {
     187           21 :               if (!rvalue_p)
     188              :                 {
     189              :                   /* Make sure we still return an lvalue.  */
     190           12 :                   gcc_assert (TREE_CODE (r) == NOP_EXPR);
     191           12 :                   TREE_TYPE (r) = cp_build_reference_type (TREE_TYPE (r),
     192              :                                                            false);
     193              :                 }
     194           21 :               expr = convert_from_reference (r);
     195              :             }
     196              :         }
     197              :       break;
     198              : 
     199    672904671 :     case VIEW_CONVERT_EXPR:
     200    672904671 :       if (location_wrapper_p (expr))
     201              :         {
     202    662750934 :           loc = EXPR_LOCATION (expr);
     203    662750934 :           tree op = TREE_OPERAND (expr, 0);
     204    662750934 :           tree nop = RECUR (op);
     205    662750934 :           if (nop == error_mark_node)
     206              :             return error_mark_node;
     207    662750922 :           else if (op == nop)
     208              :             /* No change.  */;
     209          356 :           else if (DECL_P (nop) || CONSTANT_CLASS_P (nop))
     210              :             {
     211              :               /* Reuse the location wrapper.  */
     212          327 :               TREE_OPERAND (expr, 0) = nop;
     213              :               /* If we're replacing a DECL with a constant, we also need to
     214              :                  change the TREE_CODE of the location wrapper.  */
     215          327 :               if (rvalue_p)
     216          327 :                 TREE_SET_CODE (expr, NON_LVALUE_EXPR);
     217              :             }
     218              :           else
     219              :             {
     220              :               /* Drop the location wrapper.  */
     221           29 :               expr = nop;
     222           29 :               protected_set_expr_location (expr, loc);
     223              :             }
     224    662750922 :           return expr;
     225              :         }
     226   1040342537 :       gcc_fallthrough ();
     227   1040342537 :     CASE_CONVERT:
     228   1040342537 :       recurse_op[0] = true;
     229   1040342537 :       break;
     230              : 
     231      3379201 :     case MODIFY_EXPR:
     232      3379201 :         {
     233      3379201 :           tree lhs = TREE_OPERAND (expr, 0);
     234              :           /* [expr.ass] "An assignment whose left operand is of
     235              :              a volatile-qualified type is deprecated unless the assignment
     236              :              is either a discarded-value expression or appears in an
     237              :              unevaluated context."  */
     238      3379201 :           if (!cp_unevaluated_operand
     239      3379075 :               && (TREE_THIS_VOLATILE (lhs)
     240      3378108 :                   || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs)))
     241      3380168 :               && !TREE_THIS_VOLATILE (expr))
     242              :             {
     243          581 :               if (warning_at (location_of (expr), OPT_Wvolatile,
     244              :                               "using value of assignment with "
     245              :                               "%<volatile%>-qualified left operand is "
     246              :                               "deprecated"))
     247              :                 /* Make sure not to warn about this assignment again.  */
     248           90 :                 TREE_THIS_VOLATILE (expr) = true;
     249              :             }
     250              :           break;
     251              :         }
     252              : 
     253              :     default:
     254              :       break;
     255              :     }
     256              : 
     257  30540086074 :   for (int i = 0; i < 3; ++i)
     258  22905064557 :     if (recurse_op[i])
     259              :       {
     260   1325960787 :         tree op = TREE_OPERAND (expr, i);
     261   1325960787 :         op = RECUR (op);
     262   1325960787 :         if (op == error_mark_node)
     263              :           return error_mark_node;
     264   1325960781 :         TREE_OPERAND (expr, i) = op;
     265              :       }
     266              : 
     267              :   return expr;
     268              : #undef RECUR
     269              : }
     270              : 
     271              : /* Called whenever the expression EXPR is used in an rvalue context.
     272              :    When REJECT_BUILTIN is true the expression is checked to make sure
     273              :    it doesn't make it possible to obtain the address of a GCC built-in
     274              :    function with no library fallback (or any of its bits, such as in
     275              :    a conversion to bool).  */
     276              : 
     277              : tree
     278   4818499224 : mark_rvalue_use (tree e,
     279              :                  location_t loc /* = UNKNOWN_LOCATION */,
     280              :                  bool reject_builtin /* = true */)
     281              : {
     282   4818499224 :   return mark_use (e, true, true, loc, reject_builtin);
     283              : }
     284              : 
     285              : /* Called whenever an expression is used in an lvalue context.  */
     286              : 
     287              : tree
     288    565915100 : mark_lvalue_use (tree expr)
     289              : {
     290    565915100 :   return mark_use (expr, false, true, input_location, false);
     291              : }
     292              : 
     293              : /* As above, but don't consider this use a read.  */
     294              : 
     295              : tree
     296     47030483 : mark_lvalue_use_nonread (tree expr)
     297              : {
     298     47030483 :   return mark_use (expr, false, false, input_location, false);
     299              : }
     300              : 
     301              : /* Called when expr appears as a discarded-value expression.  */
     302              : 
     303              : tree
     304     92964221 : mark_discarded_use (tree expr)
     305              : {
     306              :   /* The lvalue-to-rvalue conversion (7.1) is applied if and only if the
     307              :      expression is a glvalue of volatile-qualified type and it is one of the
     308              :      following:
     309              :      * ( expression ), where expression is one of these expressions,
     310              :      * id-expression (8.1.4),
     311              :      * subscripting (8.2.1),
     312              :      * class member access (8.2.5),
     313              :      * indirection (8.3.1),
     314              :      * pointer-to-member operation (8.5),
     315              :      * conditional expression (8.16) where both the second and the third
     316              :        operands are one of these expressions, or
     317              :      * comma expression (8.19) where the right operand is one of these
     318              :        expressions.  */
     319     92964221 :   if (expr == NULL_TREE)
     320              :     return expr;
     321              : 
     322     92964215 :   STRIP_ANY_LOCATION_WRAPPER (expr);
     323              : 
     324     92964215 :   switch (TREE_CODE (expr))
     325              :     {
     326       137045 :     case COND_EXPR:
     327       137045 :       TREE_OPERAND (expr, 2) = mark_discarded_use (TREE_OPERAND (expr, 2));
     328       788114 :       gcc_fallthrough ();
     329       788114 :     case COMPOUND_EXPR:
     330       788114 :       TREE_OPERAND (expr, 1) = mark_discarded_use (TREE_OPERAND (expr, 1));
     331       788114 :       return expr;
     332              : 
     333              :     case COMPONENT_REF:
     334              :     case ARRAY_REF:
     335              :     case INDIRECT_REF:
     336              :     case MEMBER_REF:
     337              :       break;
     338     83215464 :     default:
     339     83215464 :       if (DECL_P (expr))
     340              :         break;
     341              :       else
     342              :         return expr;
     343              :     }
     344              : 
     345              :   /* Like mark_rvalue_use, but don't reject built-ins.  */
     346      9054856 :   return mark_use (expr, true, true, input_location, false);
     347              : }
     348              : 
     349              : /* Called whenever an expression is used in a type use context.  */
     350              : 
     351              : tree
     352    147588352 : mark_type_use (tree expr)
     353              : {
     354    147588352 :   mark_exp_read (expr);
     355    147588352 :   return expr;
     356              : }
     357              : 
     358              : /* Mark EXP as read, not just set, for set but not used -Wunused
     359              :    warning purposes.  */
     360              : 
     361              : void
     362   8702725895 : mark_exp_read (tree exp)
     363              : {
     364  13510116549 :   if (exp == NULL)
     365              :     return;
     366              : 
     367  13500000228 :   if (TREE_TYPE (exp) && VOID_TYPE_P (TREE_TYPE (exp)))
     368              :     return;
     369              : 
     370  13322666288 :   switch (TREE_CODE (exp))
     371              :     {
     372   1531804339 :     case VAR_DECL:
     373   1531804339 :       if (DECL_DECOMPOSITION_P (exp))
     374     18227246 :         mark_exp_read (DECL_DECOMP_BASE (exp));
     375   4274338795 :       gcc_fallthrough ();
     376   4274338795 :     case PARM_DECL:
     377   4274338795 :       DECL_READ_P (exp) = 1;
     378   4274338795 :       break;
     379   4755716772 :     CASE_CONVERT:
     380   4755716772 :     case ARRAY_REF:
     381   4755716772 :     case COMPONENT_REF:
     382   4755716772 :     case MODIFY_EXPR:
     383   4755716772 :     case REALPART_EXPR:
     384   4755716772 :     case IMAGPART_EXPR:
     385   4755716772 :     case ADDR_EXPR:
     386   4755716772 :     case INDIRECT_REF:
     387   4755716772 :     case FLOAT_EXPR:
     388   4755716772 :     case VIEW_CONVERT_EXPR:
     389   4755716772 :     case PREINCREMENT_EXPR:
     390   4755716772 :     case PREDECREMENT_EXPR:
     391   4755716772 :     case POSTINCREMENT_EXPR:
     392   4755716772 :     case POSTDECREMENT_EXPR:
     393   4755716772 :       mark_exp_read (TREE_OPERAND (exp, 0));
     394   4755716772 :       break;
     395     23921082 :     case COMPOUND_EXPR:
     396     23921082 :       mark_exp_read (TREE_OPERAND (exp, 1));
     397     23921082 :       break;
     398     27752800 :     case COND_EXPR:
     399     27752800 :       if (TREE_OPERAND (exp, 1))
     400     27752751 :         mark_exp_read (TREE_OPERAND (exp, 1));
     401     27752800 :       if (TREE_OPERAND (exp, 2))
     402     27752800 :         mark_exp_read (TREE_OPERAND (exp, 2));
     403              :       break;
     404              :     default:
     405              :       break;
     406              :     }
     407              : }
     408              : 
     409              : /* Fold X for consideration by one of the warning functions when checking
     410              :    whether an expression has a constant value.  */
     411              : 
     412              : tree
     413     84752294 : fold_for_warn (tree x)
     414              : {
     415              :   /* C++ implementation.  */
     416              : 
     417     84752294 :   if (cp_unevaluated_operand)
     418              :     /* In an unevaluated context we don't care about the reduced value
     419              :        of an expression, so neither should any warnings.  */
     420              :     return x;
     421              : 
     422              :   /* Prevent warning-dependent constexpr evaluation from changing
     423              :      DECL_UID (which breaks -fcompare-debug) and from instantiating
     424              :      templates.  */
     425     84717484 :   uid_sensitive_constexpr_evaluation_sentinel s;
     426              : 
     427              :   /* It's not generally safe to fully fold inside of a template, so
     428              :      call fold_non_dependent_expr instead.  */
     429     84717484 :   if (processing_template_decl)
     430              :     {
     431      3757704 :       tree f = fold_non_dependent_expr (x, tf_none);
     432      3757704 :       if (f == error_mark_node)
     433              :         return x;
     434              :       else
     435      3757702 :         return f;
     436              :     }
     437     80959780 :   else if (cxx_dialect >= cxx11)
     438     80486562 :     x = maybe_constant_value (x);
     439              : 
     440     80959780 :   return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
     441     84717484 : }
     442              : 
     443              : /* Make EXPR only execute during constant evaluation by wrapping it in a
     444              :    statement-expression containing 'if consteval'.  */
     445              : 
     446              : tree
     447            1 : wrap_with_if_consteval (tree expr)
     448              : {
     449            1 :   tree stmtex = begin_stmt_expr ();
     450            1 :   tree ifcev = begin_if_stmt ();
     451            1 :   IF_STMT_CONSTEVAL_P (ifcev) = true;
     452            1 :   finish_if_stmt_cond (boolean_false_node, ifcev);
     453            1 :   finish_expr_stmt (expr);
     454            1 :   finish_then_clause (ifcev);
     455            1 :   finish_if_stmt (ifcev);
     456            1 :   return finish_stmt_expr (stmtex, /*no scope*/true);
     457              : }
        

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.