LCOV - code coverage report
Current view: top level - gcc/c - c-convert.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.4 % 105 96
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Language-level data type conversion for GNU C.
       2              :    Copyright (C) 1987-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : 
      21              : /* This file contains the functions for converting C expressions
      22              :    to different data types.  The only entry point is `convert'.
      23              :    Every language front end must have a `convert' function
      24              :    but what kind of conversions it does will depend on the language.  */
      25              : 
      26              : #include "config.h"
      27              : #include "system.h"
      28              : #include "coretypes.h"
      29              : #include "target.h"
      30              : #include "c-tree.h"
      31              : #include "convert.h"
      32              : #include "langhooks.h"
      33              : #include "ubsan.h"
      34              : #include "stringpool.h"
      35              : #include "attribs.h"
      36              : #include "asan.h"
      37              : 
      38              : /* Change of width--truncation and extension of integers or reals--
      39              :    is represented with NOP_EXPR.  Proper functioning of many things
      40              :    assumes that no other conversions can be NOP_EXPRs.
      41              : 
      42              :    Conversion between integer and pointer is represented with CONVERT_EXPR.
      43              :    Converting integer to real uses FLOAT_EXPR
      44              :    and real to integer uses FIX_TRUNC_EXPR.
      45              : 
      46              :    Here is a list of all the functions that assume that widening and
      47              :    narrowing is always done with a NOP_EXPR:
      48              :      In convert.cc, convert_to_integer.
      49              :      In c-typeck.cc, build_binary_op (boolean ops), and
      50              :         c_common_truthvalue_conversion.
      51              :      In expr.cc: expand_expr, for operands of a MULT_EXPR.
      52              :      In fold-const.cc: fold.
      53              :      In tree.cc: get_narrower and get_unwidened.  */
      54              : 
      55              : /* Subroutines of `convert'.  */
      56              : 
      57              : 
      58              : 
      59              : /* Create an expression whose value is that of EXPR,
      60              :    converted to type TYPE.  The TREE_TYPE of the value
      61              :    is always TYPE.  This function implements all reasonable
      62              :    conversions; callers should filter out those that are
      63              :    not permitted by the language being compiled.
      64              :    INIT_CONST is true if the conversion is for arithmetic types for a static
      65              :    initializer and folding must apply accordingly (discarding floating-point
      66              :    exceptions and assuming the default rounding mode is in effect).  */
      67              : 
      68              : static tree
      69    602625698 : c_convert (tree type, tree expr, bool init_const)
      70              : {
      71    602625698 :   tree e = expr;
      72    602625698 :   enum tree_code code = TREE_CODE (type);
      73    602625698 :   const char *invalid_conv_diag;
      74    602625698 :   tree ret;
      75    602625698 :   location_t loc = EXPR_LOCATION (expr);
      76              : 
      77    602625698 :   if (type == error_mark_node
      78    602625698 :       || error_operand_p (expr))
      79              :     return error_mark_node;
      80              : 
      81   1205251184 :   if ((invalid_conv_diag
      82    602625592 :        = targetm.invalid_conversion (TREE_TYPE (expr), type)))
      83              :     {
      84            2 :       error (invalid_conv_diag);
      85            2 :       return error_mark_node;
      86              :     }
      87              : 
      88    602625590 :   if (type == TREE_TYPE (expr))
      89              :     return expr;
      90    196661993 :   ret = targetm.convert_to_type (type, expr);
      91    196661993 :   if (ret)
      92              :       return ret;
      93              : 
      94    196708561 :   STRIP_TYPE_NOPS (e);
      95              : 
      96    196661993 :   if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))
      97    196661993 :       && (TREE_CODE (TREE_TYPE (expr)) != COMPLEX_TYPE
      98        37723 :           || TREE_CODE (e) == COMPLEX_EXPR))
      99     62155034 :     return fold_convert_loc (loc, type, expr);
     100    134506959 :   if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
     101            0 :     return error_mark_node;
     102    134506959 :   if (VOID_TYPE_P (TREE_TYPE (expr)))
     103              :     {
     104            0 :       error ("void value not ignored as it ought to be");
     105            0 :       return error_mark_node;
     106              :     }
     107              : 
     108    134506959 :   {
     109    134506959 :     tree false_value, true_value;
     110    134506959 :     if (c_hardbool_type_attr (type, &false_value, &true_value))
     111              :       {
     112         8736 :         bool save = in_late_binary_op;
     113         8736 :         in_late_binary_op = true;
     114         8736 :         expr = c_objc_common_truthvalue_conversion (input_location, expr);
     115         8736 :         in_late_binary_op = save;
     116              : 
     117         8736 :         return fold_build3_loc (loc, COND_EXPR, type,
     118         8736 :                                 expr, true_value, false_value);
     119              :       }
     120              :   }
     121              : 
     122    134498223 :   switch (code)
     123              :     {
     124        63899 :     case VOID_TYPE:
     125        63899 :       return fold_convert_loc (loc, type, e);
     126              : 
     127       124675 :     case ENUMERAL_TYPE:
     128       124675 :       if (ENUM_UNDERLYING_TYPE (type) != NULL_TREE
     129       124675 :           && TREE_CODE (ENUM_UNDERLYING_TYPE (type)) == BOOLEAN_TYPE)
     130          165 :         goto convert_to_boolean;
     131     25565369 :       gcc_fallthrough ();
     132              : 
     133     25565369 :     case INTEGER_TYPE:
     134     25565369 :     case BITINT_TYPE:
     135     25565369 :       if (sanitize_flags_p (SANITIZE_FLOAT_CAST)
     136        82163 :           && current_function_decl != NULL_TREE
     137        82163 :           && SCALAR_FLOAT_TYPE_P (TREE_TYPE (expr))
     138     25577093 :           && COMPLETE_TYPE_P (type))
     139              :         {
     140        11724 :           expr = save_expr (expr);
     141        11724 :           expr = c_fully_fold (expr, init_const, NULL);
     142        11724 :           tree check = ubsan_instrument_float_cast (loc, type, expr);
     143        11724 :           expr = fold_build1 (FIX_TRUNC_EXPR, type, expr);
     144        11724 :           if (check == NULL_TREE)
     145              :             return expr;
     146         7128 :           return fold_build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr);
     147              :         }
     148     25553645 :       ret = convert_to_integer (type, e);
     149     25553645 :       goto maybe_fold;
     150              : 
     151        37821 :     case BOOLEAN_TYPE:
     152        37821 :     convert_to_boolean:
     153        37821 :       return c_objc_common_truthvalue_conversion (input_location, expr, type);
     154              : 
     155      6398067 :     case POINTER_TYPE:
     156              :       /* The type nullptr_t may be converted to a pointer type.  The result is
     157              :          a null pointer value.  */
     158      6398067 :       if (NULLPTR_TYPE_P (TREE_TYPE (e)))
     159              :         {
     160              :           /* To make sure that (void *)nullptr is not a null pointer constant,
     161              :              build_c_cast will create an additional NOP_EXPR around the result
     162              :              of this conversion.  */
     163          103 :           if (TREE_SIDE_EFFECTS (e))
     164           11 :             ret = build2 (COMPOUND_EXPR, type, e, build_int_cst (type, 0));
     165              :           else
     166           92 :             ret = build_int_cst (type, 0);
     167          103 :           goto maybe_fold;
     168              :         }
     169      6397964 :       gcc_fallthrough ();
     170      6397964 :     case REFERENCE_TYPE:
     171      6397964 :       ret = convert_to_pointer (type, e);
     172      6397964 :       goto maybe_fold;
     173              : 
     174           10 :     case NULLPTR_TYPE:
     175              :       /* A null pointer constant or value of type nullptr_t may be
     176              :          converted to nullptr_t.  The latter case has already been
     177              :          handled.  build_c_cast will create an additional NOP_EXPR to
     178              :          ensure the result of the conversion is not itself a null
     179              :          pointer constant.  */
     180           10 :       if (null_pointer_constant_p (expr))
     181              :         {
     182            7 :           ret = build_int_cst (type, 0);
     183            7 :           goto maybe_fold;
     184              :         }
     185              :       break;
     186              : 
     187      1003954 :     case REAL_TYPE:
     188      1003954 :       ret = convert_to_real (type, e);
     189      1003954 :       goto maybe_fold;
     190              : 
     191            0 :     case FIXED_POINT_TYPE:
     192            0 :       ret = convert_to_fixed (type, e);
     193            0 :       goto maybe_fold;
     194              : 
     195       133307 :     case COMPLEX_TYPE:
     196       133307 :       ret = convert_to_complex (type, e);
     197       133307 :       goto maybe_fold;
     198              : 
     199    101295765 :     case VECTOR_TYPE:
     200    101295765 :       if (gnu_vector_type_p (type)
     201            0 :           || gnu_vector_type_p (TREE_TYPE (e))
     202              :           /* Allow conversions between compatible non-GNU vector types
     203              :              when -flax-vector-conversions is passed.  The whole purpose
     204              :              of the option is to bend the normal type rules and accept
     205              :              nonconforming code.  */
     206    101295765 :           || (flag_lax_vector_conversions
     207            0 :               && VECTOR_TYPE_P (TREE_TYPE (e))
     208            0 :               && vector_types_convertible_p (type, TREE_TYPE (e), false)))
     209              :         {
     210    101295765 :           ret = convert_to_vector (type, e);
     211    101295765 :           goto maybe_fold;
     212              :         }
     213              :       break;
     214              : 
     215           31 :     case RECORD_TYPE:
     216           31 :     case UNION_TYPE:
     217           31 :       if (lang_hooks.types_compatible_p (type, TREE_TYPE (expr)))
     218              :         return e;
     219              :       break;
     220              : 
     221              :     default:
     222              :       break;
     223              : 
     224    134384745 :     maybe_fold:
     225    134384745 :       if (TREE_CODE (ret) != C_MAYBE_CONST_EXPR)
     226    134384731 :         ret = init_const ? fold_init (ret) : fold (ret);
     227              :       return ret;
     228              :     }
     229              : 
     230              :   /* If we are converting to nullptr_t, don't say "non-scalar type" because
     231              :      the nullptr_t type is a scalar type.  Only nullptr_t or a null pointer
     232              :      constant shall be converted to nullptr_t.  */
     233           11 :   if (code == NULLPTR_TYPE)
     234              :     {
     235            3 :       error ("conversion from %qT to %qT", TREE_TYPE (e), type);
     236            3 :       inform (input_location,
     237              :               "only %qT or a null pointer constant can be converted to %qT",
     238              :               type, type);
     239              :     }
     240              :   else
     241            8 :     error ("conversion to non-scalar type requested");
     242           11 :   return error_mark_node;
     243              : }
     244              : 
     245              : /* Create an expression whose value is that of EXPR, converted to type TYPE.
     246              :    The TREE_TYPE of the value is always TYPE.  This function implements all
     247              :    reasonable conversions; callers should filter out those that are not
     248              :    permitted by the language being compiled.  */
     249              : 
     250              : tree
     251    602081954 : convert (tree type, tree expr)
     252              : {
     253    602081954 :   return c_convert (type, expr, false);
     254              : }
     255              : 
     256              : /* Create an expression whose value is that of EXPR, converted to type TYPE, in
     257              :    a static initializer.  The TREE_TYPE of the value is always TYPE.  This
     258              :    function implements all reasonable conversions; callers should filter out
     259              :    those that are not permitted by the language being compiled.  */
     260              : 
     261              : tree
     262       543744 : convert_init (tree type, tree expr)
     263              : {
     264       543744 :   return c_convert (type, expr, true);
     265              : }
        

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.