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-07-11 15:47:05 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    101214524 : cplus_expand_constant (tree cst)
      31              : {
      32    101214524 :   switch (TREE_CODE (cst))
      33              :     {
      34        35810 :     case PTRMEM_CST:
      35        35810 :       {
      36        35810 :         tree type = TREE_TYPE (cst);
      37        35810 :         tree member;
      38              : 
      39              :         /* Find the member.  */
      40        35810 :         member = PTRMEM_CST_MEMBER (cst);
      41              : 
      42              :         /* We can't lower this until the class is complete.  */
      43        35810 :         if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
      44              :           return cst;
      45              : 
      46        35771 :         if (TREE_CODE (member) == FIELD_DECL)
      47              :           {
      48              :             /* Find the offset for the field.  */
      49         3054 :             cst = byte_position (member);
      50         6248 :             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          140 :                 member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
      57          140 :                                             DECL_CONTEXT (member));
      58          140 :                 cst = size_binop (PLUS_EXPR, cst, byte_position (member));
      59              :               }
      60         3054 :             cst = fold (build_nop (type, cst));
      61              :           }
      62              :         else
      63              :           {
      64        32717 :             tree delta;
      65        32717 :             tree pfn;
      66              : 
      67        32717 :             expand_ptrmemfunc_cst (cst, &delta, &pfn);
      68        32717 :             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     74944385 :         FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt)
      78     69298404 :           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   7063222751 : 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   7063222751 :   if (expr == NULL_TREE || error_operand_p (expr))
     100              :     return expr;
     101              : 
     102   7063217048 :   if (reject_builtin && reject_gcc_builtin (expr, loc))
     103           67 :     return error_mark_node;
     104              : 
     105   7063216981 :   if (TREE_TYPE (expr) && VOID_TYPE_P (TREE_TYPE (expr)))
     106              :     read_p = false;
     107              : 
     108   6942765923 :   if (read_p)
     109   6869235480 :     mark_exp_read (expr);
     110              : 
     111   7063216981 :   tree oexpr = expr;
     112   7063216981 :   bool recurse_op[3] = { false, false, false };
     113   7063216981 :   switch (TREE_CODE (expr))
     114              :     {
     115   1770892701 :     case VAR_DECL:
     116   1770892701 :     case PARM_DECL:
     117   1770892701 :       if (rvalue_p && is_normal_capture_proxy (expr))
     118              :         {
     119              :           /* Look through capture by copy.  */
     120      8083730 :           tree cap = DECL_CAPTURED_VARIABLE (expr);
     121      8083730 :           if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr))
     122      8083730 :               && decl_constant_var_p (cap))
     123              :             {
     124          223 :               tree val = RECUR (cap);
     125          223 :               if (!is_capture_proxy (val))
     126              :                 {
     127          184 :                   tree l = current_lambda_expr ();
     128          184 :                   LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
     129              :                 }
     130          223 :               return val;
     131              :             }
     132              :         }
     133   1770892478 :       if (outer_automatic_var_p (expr)
     134   1770892478 :           && decl_constant_var_p (expr))
     135              :         {
     136        94515 :           if (rvalue_p)
     137              :             {
     138        94506 :               tree t = maybe_constant_value (expr);
     139        94506 :               if (TREE_CONSTANT (t))
     140              :                 {
     141              :                   expr = t;
     142   6486039879 :                   break;
     143              :                 }
     144              :             }
     145          144 :           iloc_sentinel l (loc);
     146          144 :           expr = process_outer_var_ref (expr, tf_warning_or_error, true);
     147          144 :           if (!(TREE_TYPE (oexpr)
     148          144 :                 && TYPE_REF_P (TREE_TYPE (oexpr))))
     149           51 :             expr = convert_from_reference (expr);
     150          144 :         }
     151              :       break;
     152    160925800 :     case COMPONENT_REF:
     153    160925800 :       recurse_op[0] = true;
     154    160925800 :       break;
     155     14582282 :     case COMPOUND_EXPR:
     156     14582282 :       recurse_op[1] = true;
     157     14582282 :       break;
     158     19123037 :     case COND_EXPR:
     159     19123037 :       recurse_op[2] = true;
     160     19123037 :       if (TREE_OPERAND (expr, 1))
     161     19122998 :         recurse_op[1] = true;
     162              :       break;
     163    382737052 :     case INDIRECT_REF:
     164    382737052 :       if (REFERENCE_REF_P (expr))
     165              :         {
     166              :           /* Try to look through the reference.  */
     167    215310499 :           tree ref = TREE_OPERAND (expr, 0);
     168    215310499 :           if (rvalue_p && is_normal_capture_proxy (ref))
     169              :             {
     170              :               /* Look through capture by reference.  */
     171       939385 :               tree cap = DECL_CAPTURED_VARIABLE (ref);
     172       939385 :               if (!TYPE_REF_P (TREE_TYPE (cap))
     173       939385 :                   && decl_constant_var_p (cap))
     174              :                 {
     175         2870 :                   tree val = RECUR (cap);
     176         2870 :                   if (!is_capture_proxy (val))
     177              :                     {
     178         2870 :                       tree l = current_lambda_expr ();
     179         2870 :                       LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
     180              :                     }
     181         2870 :                   return val;
     182              :                 }
     183              :             }
     184    215307629 :           tree r = mark_rvalue_use (ref, loc, reject_builtin);
     185    215307629 :           if (r == error_mark_node)
     186              :             return error_mark_node;
     187    215307620 :           if (r != ref)
     188              :             {
     189           51 :               if (DECL_P (ref) && !lvalue_p (r))
     190              :                 {
     191              :                   /* Make sure we still return an lvalue.  */
     192            6 :                   gcc_assert (TREE_CODE (r) == NOP_EXPR);
     193            6 :                   TREE_TYPE (r) = cp_build_reference_type (TREE_TYPE (r),
     194              :                                                            false);
     195              :                 }
     196           51 :               expr = convert_from_reference (r);
     197              :             }
     198              :         }
     199              :       break;
     200              : 
     201    586858907 :     case VIEW_CONVERT_EXPR:
     202    586858907 :       if (location_wrapper_p (expr))
     203              :         {
     204    577174000 :           loc = EXPR_LOCATION (expr);
     205    577174000 :           tree op = TREE_OPERAND (expr, 0);
     206    577174000 :           tree nop = RECUR (op);
     207    577174000 :           if (nop == error_mark_node)
     208              :             return error_mark_node;
     209    577173988 :           else if (op == nop)
     210              :             /* No change.  */;
     211         1056 :           else if (DECL_P (nop) || CONSTANT_CLASS_P (nop))
     212              :             {
     213              :               /* Reuse the location wrapper.  */
     214         1013 :               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         1013 :               if (rvalue_p)
     218         1013 :                 TREE_SET_CODE (expr, NON_LVALUE_EXPR);
     219              :             }
     220              :           else
     221              :             {
     222              :               /* Drop the location wrapper.  */
     223           43 :               expr = nop;
     224           43 :               protected_set_expr_location (expr, loc);
     225              :             }
     226    577173988 :           return expr;
     227              :         }
     228    830513392 :       gcc_fallthrough ();
     229    830513392 :     CASE_CONVERT:
     230    830513392 :       recurse_op[0] = true;
     231    830513392 :       break;
     232              : 
     233      3185866 :     case MODIFY_EXPR:
     234      3185866 :         {
     235      3185866 :           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      3185866 :           if (!cp_unevaluated_operand
     241      3185740 :               && (TREE_THIS_VOLATILE (lhs)
     242      3184773 :                   || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs)))
     243      3186833 :               && !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  25944159498 :   for (int i = 0; i < 3; ++i)
     260  19458119625 :     if (recurse_op[i])
     261              :       {
     262   1044267509 :         tree op = TREE_OPERAND (expr, i);
     263   1044267509 :         op = RECUR (op);
     264   1044267509 :         if (op == error_mark_node)
     265              :           return error_mark_node;
     266   1044267503 :         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   4177274379 : mark_rvalue_use (tree e,
     281              :                  location_t loc /* = UNKNOWN_LOCATION */,
     282              :                  bool reject_builtin /* = true */)
     283              : {
     284   4177274379 :   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    437026116 : mark_lvalue_use (tree expr)
     291              : {
     292    437026116 :   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     39291488 : mark_lvalue_use_nonread (tree expr)
     299              : {
     300     39291488 :   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     76794273 : 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     76794273 :   if (expr == NULL_TREE)
     322              :     return expr;
     323              : 
     324     76794267 :   STRIP_ANY_LOCATION_WRAPPER (expr);
     325              : 
     326     76794267 :   switch (TREE_CODE (expr))
     327              :     {
     328       133312 :     case COND_EXPR:
     329       133312 :       TREE_OPERAND (expr, 2) = mark_discarded_use (TREE_OPERAND (expr, 2));
     330       640396 :       gcc_fallthrough ();
     331       640396 :     case COMPOUND_EXPR:
     332       640396 :       TREE_OPERAND (expr, 1) = mark_discarded_use (TREE_OPERAND (expr, 1));
     333       640396 :       return expr;
     334              : 
     335              :     case COMPONENT_REF:
     336              :     case ARRAY_REF:
     337              :     case INDIRECT_REF:
     338              :     case MEMBER_REF:
     339              :       break;
     340     68579292 :     default:
     341     68579292 :       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      7606278 :   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    121916232 : mark_type_use (tree expr)
     355              : {
     356    121916232 :   mark_exp_read (expr);
     357    121916232 :   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   7441764829 : mark_exp_read (tree exp)
     365              : {
     366  11149571965 :   if (exp == NULL)
     367              :     return;
     368              : 
     369  11144465522 :   if (TREE_TYPE (exp) && VOID_TYPE_P (TREE_TYPE (exp)))
     370              :     return;
     371              : 
     372  11009533848 :   switch (TREE_CODE (exp))
     373              :     {
     374   1251066485 :     case VAR_DECL:
     375   1251066485 :       if (DECL_DECOMPOSITION_P (exp))
     376      8934437 :         mark_exp_read (DECL_DECOMP_BASE (exp));
     377   3634036795 :       gcc_fallthrough ();
     378   3634036795 :     case PARM_DECL:
     379   3634036795 :       DECL_READ_P (exp) = 1;
     380   3634036795 :       break;
     381   3657709887 :     CASE_CONVERT:
     382   3657709887 :     case ARRAY_REF:
     383   3657709887 :     case COMPONENT_REF:
     384   3657709887 :     case MODIFY_EXPR:
     385   3657709887 :     case REALPART_EXPR:
     386   3657709887 :     case IMAGPART_EXPR:
     387   3657709887 :     case ADDR_EXPR:
     388   3657709887 :     case INDIRECT_REF:
     389   3657709887 :     case FLOAT_EXPR:
     390   3657709887 :     case VIEW_CONVERT_EXPR:
     391   3657709887 :     case PREINCREMENT_EXPR:
     392   3657709887 :     case PREDECREMENT_EXPR:
     393   3657709887 :     case POSTINCREMENT_EXPR:
     394   3657709887 :     case POSTDECREMENT_EXPR:
     395   3657709887 :       mark_exp_read (TREE_OPERAND (exp, 0));
     396   3657709887 :       break;
     397     23792627 :     case COMPOUND_EXPR:
     398     23792627 :       mark_exp_read (TREE_OPERAND (exp, 1));
     399     23792627 :       break;
     400     26304622 :     case COND_EXPR:
     401     26304622 :       if (TREE_OPERAND (exp, 1))
     402     26304573 :         mark_exp_read (TREE_OPERAND (exp, 1));
     403     26304622 :       if (TREE_OPERAND (exp, 2))
     404     26304622 :         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     80813062 : fold_for_warn (tree x)
     416              : {
     417              :   /* C++ implementation.  */
     418              : 
     419     80813062 :   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     80729966 :   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     80729966 :   if (processing_template_decl)
     432              :     {
     433      3967577 :       tree f = fold_non_dependent_expr (x, tf_none);
     434      3967577 :       if (f == error_mark_node)
     435              :         return x;
     436              :       else
     437      3967575 :         return f;
     438              :     }
     439     76762389 :   else if (cxx_dialect >= cxx11)
     440     76278232 :     x = maybe_constant_value (x);
     441              : 
     442     76762389 :   return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
     443     80729966 : }
     444              : 
     445              : /* Make EXPR only execute during constant evaluation by wrapping it in a
     446              :    statement-expression containing 'if consteval'.  */
     447              : 
     448              : tree
     449            2 : wrap_with_if_consteval (tree expr)
     450              : {
     451            2 :   tree stmtex = begin_stmt_expr ();
     452            2 :   tree ifcev = begin_if_stmt ();
     453            2 :   IF_STMT_CONSTEVAL_P (ifcev) = true;
     454            2 :   finish_if_stmt_cond (boolean_false_node, ifcev);
     455            2 :   finish_expr_stmt (expr);
     456            2 :   finish_then_clause (ifcev);
     457            2 :   finish_if_stmt (ifcev);
     458            2 :   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.