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: 2025-10-18 14:39:06 Functions: 100.0 % 10 10
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Convert language-specific tree expression to rtl instructions,
       2                 :             :    for GNU compiler.
       3                 :             :    Copyright (C) 1988-2025 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                 :    51684378 : cplus_expand_constant (tree cst)
      31                 :             : {
      32                 :    51684378 :   switch (TREE_CODE (cst))
      33                 :             :     {
      34                 :       37281 :     case PTRMEM_CST:
      35                 :       37281 :       {
      36                 :       37281 :         tree type = TREE_TYPE (cst);
      37                 :       37281 :         tree member;
      38                 :             : 
      39                 :             :         /* Find the member.  */
      40                 :       37281 :         member = PTRMEM_CST_MEMBER (cst);
      41                 :             : 
      42                 :             :         /* We can't lower this until the class is complete.  */
      43                 :       37281 :         if (!COMPLETE_TYPE_P (DECL_CONTEXT (member)))
      44                 :             :           return cst;
      45                 :             : 
      46                 :       37248 :         if (TREE_CODE (member) == FIELD_DECL)
      47                 :             :           {
      48                 :             :             /* Find the offset for the field.  */
      49                 :        3722 :             cst = byte_position (member);
      50                 :        7570 :             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                 :         126 :                 member = lookup_anon_field (TYPE_PTRMEM_CLASS_TYPE (type),
      57                 :         126 :                                             DECL_CONTEXT (member));
      58                 :         126 :                 cst = size_binop (PLUS_EXPR, cst, byte_position (member));
      59                 :             :               }
      60                 :        3722 :             cst = fold (build_nop (type, cst));
      61                 :             :           }
      62                 :             :         else
      63                 :             :           {
      64                 :       33526 :             tree delta;
      65                 :       33526 :             tree pfn;
      66                 :             : 
      67                 :       33526 :             expand_ptrmemfunc_cst (cst, &delta, &pfn);
      68                 :       33526 :             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                 :    37618528 :         FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (cst), idx, elt)
      78                 :    33258351 :           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                 :  4900189936 : 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                 :  4900189936 :   if (expr == NULL_TREE || error_operand_p (expr))
     100                 :             :     return expr;
     101                 :             : 
     102                 :  4900185207 :   if (reject_builtin && reject_gcc_builtin (expr, loc))
     103                 :          66 :     return error_mark_node;
     104                 :             : 
     105                 :  4900185141 :   if (TREE_TYPE (expr) && VOID_TYPE_P (TREE_TYPE (expr)))
     106                 :             :     read_p = false;
     107                 :             : 
     108                 :  4815556423 :   if (read_p)
     109                 :  4752515173 :     mark_exp_read (expr);
     110                 :             : 
     111                 :  4900185141 :   tree oexpr = expr;
     112                 :  4900185141 :   bool recurse_op[3] = { false, false, false };
     113                 :  4900185141 :   switch (TREE_CODE (expr))
     114                 :             :     {
     115                 :  1238489622 :     case VAR_DECL:
     116                 :  1238489622 :     case PARM_DECL:
     117                 :  1238489622 :       if (rvalue_p && is_normal_capture_proxy (expr))
     118                 :             :         {
     119                 :             :           /* Look through capture by copy.  */
     120                 :     6428405 :           tree cap = DECL_CAPTURED_VARIABLE (expr);
     121                 :     6428405 :           if (TREE_CODE (TREE_TYPE (cap)) == TREE_CODE (TREE_TYPE (expr))
     122                 :     6428405 :               && decl_constant_var_p (cap))
     123                 :             :             {
     124                 :         162 :               tree val = RECUR (cap);
     125                 :         162 :               if (!is_capture_proxy (val))
     126                 :             :                 {
     127                 :         120 :                   tree l = current_lambda_expr ();
     128                 :         120 :                   LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
     129                 :             :                 }
     130                 :         162 :               return val;
     131                 :             :             }
     132                 :             :         }
     133                 :  1238489460 :       if (outer_automatic_var_p (expr)
     134                 :  1238489460 :           && decl_constant_var_p (expr))
     135                 :             :         {
     136                 :       86714 :           if (rvalue_p)
     137                 :             :             {
     138                 :       86705 :               tree t = maybe_constant_value (expr);
     139                 :       86705 :               if (TREE_CONSTANT (t))
     140                 :             :                 {
     141                 :             :                   expr = t;
     142                 :  4493312821 :                   break;
     143                 :             :                 }
     144                 :             :             }
     145                 :          72 :           iloc_sentinel l (loc);
     146                 :          72 :           expr = process_outer_var_ref (expr, tf_warning_or_error, true);
     147                 :          72 :           if (!(TREE_TYPE (oexpr)
     148                 :          72 :                 && TYPE_REF_P (TREE_TYPE (oexpr))))
     149                 :          54 :             expr = convert_from_reference (expr);
     150                 :          72 :         }
     151                 :             :       break;
     152                 :   114499351 :     case COMPONENT_REF:
     153                 :   114499351 :       recurse_op[0] = true;
     154                 :   114499351 :       break;
     155                 :     6246183 :     case COMPOUND_EXPR:
     156                 :     6246183 :       recurse_op[1] = true;
     157                 :     6246183 :       break;
     158                 :    13675438 :     case COND_EXPR:
     159                 :    13675438 :       recurse_op[2] = true;
     160                 :    13675438 :       if (TREE_OPERAND (expr, 1))
     161                 :    13675399 :         recurse_op[1] = true;
     162                 :             :       break;
     163                 :   255344558 :     case INDIRECT_REF:
     164                 :   255344558 :       if (REFERENCE_REF_P (expr))
     165                 :             :         {
     166                 :             :           /* Try to look through the reference.  */
     167                 :   134882071 :           tree ref = TREE_OPERAND (expr, 0);
     168                 :   134882071 :           if (rvalue_p && is_normal_capture_proxy (ref))
     169                 :             :             {
     170                 :             :               /* Look through capture by reference.  */
     171                 :     1208654 :               tree cap = DECL_CAPTURED_VARIABLE (ref);
     172                 :     1208654 :               if (!TYPE_REF_P (TREE_TYPE (cap))
     173                 :     1208654 :                   && decl_constant_var_p (cap))
     174                 :             :                 {
     175                 :        1061 :                   tree val = RECUR (cap);
     176                 :        1061 :                   if (!is_capture_proxy (val))
     177                 :             :                     {
     178                 :        1061 :                       tree l = current_lambda_expr ();
     179                 :        1061 :                       LAMBDA_EXPR_CAPTURE_OPTIMIZED (l) = true;
     180                 :             :                     }
     181                 :        1061 :                   return val;
     182                 :             :                 }
     183                 :             :             }
     184                 :   134881010 :           tree r = mark_rvalue_use (ref, loc, reject_builtin);
     185                 :   134881010 :           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                 :   414854838 :     case VIEW_CONVERT_EXPR:
     200                 :   414854838 :       if (location_wrapper_p (expr))
     201                 :             :         {
     202                 :   406871097 :           loc = EXPR_LOCATION (expr);
     203                 :   406871097 :           tree op = TREE_OPERAND (expr, 0);
     204                 :   406871097 :           tree nop = RECUR (op);
     205                 :   406871097 :           if (nop == error_mark_node)
     206                 :             :             return error_mark_node;
     207                 :   406871085 :           else if (op == nop)
     208                 :             :             /* No change.  */;
     209                 :         318 :           else if (DECL_P (nop) || CONSTANT_CLASS_P (nop))
     210                 :             :             {
     211                 :             :               /* Reuse the location wrapper.  */
     212                 :         306 :               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                 :         306 :               if (rvalue_p)
     216                 :         306 :                 TREE_SET_CODE (expr, NON_LVALUE_EXPR);
     217                 :             :             }
     218                 :             :           else
     219                 :             :             {
     220                 :             :               /* Drop the location wrapper.  */
     221                 :          12 :               expr = nop;
     222                 :          12 :               protected_set_expr_location (expr, loc);
     223                 :             :             }
     224                 :   406871085 :           return expr;
     225                 :             :         }
     226                 :   520864692 :       gcc_fallthrough ();
     227                 :   520864692 :     CASE_CONVERT:
     228                 :   520864692 :       recurse_op[0] = true;
     229                 :   520864692 :       break;
     230                 :             : 
     231                 :     2541469 :     case MODIFY_EXPR:
     232                 :     2541469 :         {
     233                 :     2541469 :           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                 :     2541469 :           if (!cp_unevaluated_operand
     239                 :     2541343 :               && (TREE_THIS_VOLATILE (lhs)
     240                 :     2540700 :                   || CP_TYPE_VOLATILE_P (TREE_TYPE (lhs)))
     241                 :     2542112 :               && !TREE_THIS_VOLATILE (expr))
     242                 :             :             {
     243                 :         446 :               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                 :          80 :                 TREE_THIS_VOLATILE (expr) = true;
     249                 :             :             }
     250                 :             :           break;
     251                 :             :         }
     252                 :             : 
     253                 :             :     default:
     254                 :             :       break;
     255                 :             :     }
     256                 :             : 
     257                 : 17973251266 :   for (int i = 0; i < 3; ++i)
     258                 : 13479938451 :     if (recurse_op[i])
     259                 :             :       {
     260                 :   668961063 :         tree op = TREE_OPERAND (expr, i);
     261                 :   668961063 :         op = RECUR (op);
     262                 :   668961063 :         if (op == error_mark_node)
     263                 :             :           return error_mark_node;
     264                 :   668961057 :         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                 :  2857130740 : mark_rvalue_use (tree e,
     279                 :             :                  location_t loc /* = UNKNOWN_LOCATION */,
     280                 :             :                  bool reject_builtin /* = true */)
     281                 :             : {
     282                 :  2857130740 :   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                 :   332304809 : mark_lvalue_use (tree expr)
     289                 :             : {
     290                 :   332304809 :   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                 :    33464031 : mark_lvalue_use_nonread (tree expr)
     297                 :             : {
     298                 :    33464031 :   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                 :    58191025 : 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                 :    58191025 :   if (expr == NULL_TREE)
     320                 :             :     return expr;
     321                 :             : 
     322                 :    58191019 :   STRIP_ANY_LOCATION_WRAPPER (expr);
     323                 :             : 
     324                 :    58191019 :   switch (TREE_CODE (expr))
     325                 :             :     {
     326                 :      129407 :     case COND_EXPR:
     327                 :      129407 :       TREE_OPERAND (expr, 2) = mark_discarded_use (TREE_OPERAND (expr, 2));
     328                 :      517745 :       gcc_fallthrough ();
     329                 :      517745 :     case COMPOUND_EXPR:
     330                 :      517745 :       TREE_OPERAND (expr, 1) = mark_discarded_use (TREE_OPERAND (expr, 1));
     331                 :      517745 :       return expr;
     332                 :             : 
     333                 :             :     case COMPONENT_REF:
     334                 :             :     case ARRAY_REF:
     335                 :             :     case INDIRECT_REF:
     336                 :             :     case MEMBER_REF:
     337                 :             :       break;
     338                 :    53451631 :     default:
     339                 :    53451631 :       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                 :     4263060 :   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                 :    95105072 : mark_type_use (tree expr)
     353                 :             : {
     354                 :    95105072 :   mark_exp_read (expr);
     355                 :    95105072 :   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                 :  5178514187 : mark_exp_read (tree exp)
     363                 :             : {
     364                 :  7677226970 :   if (exp == NULL)
     365                 :             :     return;
     366                 :             : 
     367                 :  7674830372 :   if (TREE_TYPE (exp) && VOID_TYPE_P (TREE_TYPE (exp)))
     368                 :             :     return;
     369                 :             : 
     370                 :  7571025836 :   switch (TREE_CODE (exp))
     371                 :             :     {
     372                 :   910040089 :     case VAR_DECL:
     373                 :   910040089 :       if (DECL_DECOMPOSITION_P (exp))
     374                 :     4260020 :         mark_exp_read (DECL_DECOMP_BASE (exp));
     375                 :  2489228164 :       gcc_fallthrough ();
     376                 :  2489228164 :     case PARM_DECL:
     377                 :  2489228164 :       DECL_READ_P (exp) = 1;
     378                 :  2489228164 :       break;
     379                 :  2470787977 :     CASE_CONVERT:
     380                 :  2470787977 :     case ARRAY_REF:
     381                 :  2470787977 :     case COMPONENT_REF:
     382                 :  2470787977 :     case MODIFY_EXPR:
     383                 :  2470787977 :     case REALPART_EXPR:
     384                 :  2470787977 :     case IMAGPART_EXPR:
     385                 :  2470787977 :     case ADDR_EXPR:
     386                 :  2470787977 :     case INDIRECT_REF:
     387                 :  2470787977 :     case FLOAT_EXPR:
     388                 :  2470787977 :     case VIEW_CONVERT_EXPR:
     389                 :  2470787977 :     case PREINCREMENT_EXPR:
     390                 :  2470787977 :     case PREDECREMENT_EXPR:
     391                 :  2470787977 :     case POSTINCREMENT_EXPR:
     392                 :  2470787977 :     case POSTDECREMENT_EXPR:
     393                 :  2470787977 :       mark_exp_read (TREE_OPERAND (exp, 0));
     394                 :  2470787977 :       break;
     395                 :     8656036 :     case COMPOUND_EXPR:
     396                 :     8656036 :       mark_exp_read (TREE_OPERAND (exp, 1));
     397                 :     8656036 :       break;
     398                 :    19268770 :     case COND_EXPR:
     399                 :    19268770 :       if (TREE_OPERAND (exp, 1))
     400                 :    19268721 :         mark_exp_read (TREE_OPERAND (exp, 1));
     401                 :    19268770 :       if (TREE_OPERAND (exp, 2))
     402                 :    19268770 :         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                 :    66228085 : fold_for_warn (tree x)
     414                 :             : {
     415                 :             :   /* C++ implementation.  */
     416                 :             : 
     417                 :    66228085 :   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                 :    66191833 :   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                 :    66191833 :   if (processing_template_decl)
     430                 :             :     {
     431                 :     3257235 :       tree f = fold_non_dependent_expr (x, tf_none);
     432                 :     3257235 :       if (f == error_mark_node)
     433                 :             :         return x;
     434                 :             :       else
     435                 :     3257233 :         return f;
     436                 :             :     }
     437                 :    62934598 :   else if (cxx_dialect >= cxx11)
     438                 :    62547954 :     x = maybe_constant_value (x);
     439                 :             : 
     440                 :    62934598 :   return c_fully_fold (x, /*for_init*/false, /*maybe_constp*/NULL);
     441                 :    66191833 : }
     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.1-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.