LCOV - code coverage report
Current view: top level - src/compiler - coerce.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 55 127 43.3 %
Date: 2016-11-30 13:12:14 Functions: 1 1 100.0 %
Branches: 51 96 53.1 %

           Branch data     Line data    Source code
       1                 :            : #include "coerce.h"
       2                 :            : 
       3                 :            : /*
       4                 :            :  * Be aware that some value variants represents actual values (e.g.
       5                 :            :  * vt_int), and others represent a type (e.g. vt_scalar) which holds a
       6                 :            :  * type identifier token. Here we implicitly expect a vt_scalar type as
       7                 :            :  * first argument, but only receive the token. The second argument is a
       8                 :            :  * value literal.  Our job is to decide if the value fits within the
       9                 :            :  * given type. Our internal representation already ensures that value
      10                 :            :  * fits within a 64bit signed or unsigned integer, or double; otherwise
      11                 :            :  * the parser would have set vt_invalid type on the value.
      12                 :            :  *
      13                 :            :  * If the value is invalid, success is returned because the
      14                 :            :  * error is presumably already generated. If the value is some other
      15                 :            :  * type than expect, an error is generated.
      16                 :            :  *
      17                 :            :  * Symbolic names are not allowed as values here.
      18                 :            :  *
      19                 :            :  * Converts positive integers to signed type and unsigned integers to
      20                 :            :  * signed type, integers to floats and floats to integers.
      21                 :            :  *
      22                 :            :  * Optionally allows 1 to be assigned as true and 0 as false, and vice
      23                 :            :  * versa when allow_boolean_conversion is enabled.
      24                 :            :  *
      25                 :            :  * Returns 0 on success, -1 on error.
      26                 :            :  */
      27                 :        288 : int fb_coerce_scalar_type(fb_parser_t *P, fb_symbol_t *sym, fb_scalar_type_t st, fb_value_t *value)
      28                 :            : {
      29                 :            :     double d;
      30                 :            :     float f;
      31                 :            : 
      32         [ +  - ]:        288 :     if (!value->type) {
      33                 :            :         return 0;
      34                 :            :     }
      35                 :            :     /*
      36                 :            :      * The parser only produces negative vt_int values, which simplifies
      37                 :            :      * the logic, but to make this operation robust against multiple
      38                 :            :      * coercion steps, we first convert back to uint if the assumption turns
      39                 :            :      * out false.
      40                 :            :      */
      41 [ +  + ][ +  + ]:        288 :     if (value->type == vt_int && value->i >= 0) {
      42                 :         70 :         value->type = vt_uint;
      43                 :         70 :         value->u = (uint64_t)value->i;
      44                 :            :     }
      45         [ +  - ]:        288 :     if (value->type == vt_invalid) {
      46                 :            :         /* Silently ignore past errors. */
      47                 :            :         return 0;
      48                 :            :     }
      49 [ +  + ][ -  + ]:        288 :     if (value->type == vt_bool && st != fb_bool  && P->opts.allow_boolean_conversion) {
                 [ #  # ]
      50                 :          0 :         value->type = vt_uint;
      51                 :          0 :         value->u = (uint64_t)value->b;
      52                 :            :         assert(value->u == 1 || value->u == 0);
      53                 :            :     }
      54   [ +  +  +  +  :        288 :     switch (st) {
          +  +  +  +  +  
                +  +  - ]
      55                 :            :     case fb_ulong:
      56         [ -  + ]:         16 :         if (value->type != vt_uint) {
      57                 :            :             error_sym(P, sym, "64-bit uint32_t type only accepts unsigned integers");
      58                 :          0 :             value->type = vt_invalid;
      59                 :          0 :             return -1;
      60                 :            :         }
      61                 :            :         return 0;
      62                 :            :     case fb_uint:
      63         [ -  + ]:         32 :         if (value->type != vt_uint) {
      64                 :            :             error_sym(P, sym, "32-bit unsigned int type only accepts unsigned integers");
      65                 :          0 :             value->type = vt_invalid;
      66                 :          0 :             return -1;
      67                 :            :         }
      68         [ -  + ]:         32 :         if (value->u > UINT32_MAX) {
      69                 :            :             error_sym(P, sym, "32-bit unsigned int overflow");
      70                 :          0 :             value->type = vt_invalid;
      71                 :          0 :             return -1;
      72                 :            :         }
      73                 :            :         return 0;
      74                 :            :     case fb_ushort:
      75         [ -  + ]:          8 :         if (value->type != vt_uint) {
      76                 :            :             error_sym(P, sym, "16-bit unsigned short type only accepts unsigned integers");
      77                 :          0 :             value->type = vt_invalid;
      78                 :          0 :             return -1;
      79                 :            :         }
      80         [ -  + ]:          8 :         if (value->u > UINT16_MAX) {
      81                 :            :             error_sym(P, sym, "16-bit unsigned short overflow");
      82                 :          0 :             value->type = vt_invalid;
      83                 :          0 :             return -1;
      84                 :            :         }
      85                 :            :         return 0;
      86                 :            :     case fb_ubyte:
      87         [ -  + ]:         31 :         if (value->type != vt_uint) {
      88                 :            :             error_sym(P, sym, "8-bit unsigned byte type only accepts unsigned integers");
      89                 :          0 :             value->type = vt_invalid;
      90                 :          0 :             return -1;
      91                 :            :         }
      92         [ -  + ]:         31 :         if (value->u > UINT8_MAX) {
      93                 :            :             error_sym(P, sym, "8-bit unsigned byte overflow");
      94                 :          0 :             value->type = vt_invalid;
      95                 :          0 :             return -1;
      96                 :            :         }
      97                 :            :         return 0;
      98                 :            :     case fb_long:
      99         [ +  - ]:         65 :         if (value->type == vt_int) {
     100                 :            :             /* Native format is always ok, or parser would have failed. */
     101                 :            :             return 0;
     102                 :            :         }
     103         [ +  - ]:         65 :         if (value->type == vt_uint) {
     104         [ -  + ]:         65 :             if (value->u >= (1ULL << 63)) {
     105                 :            :                 error_sym(P, sym, "64-bit signed int32_t overflow");
     106                 :          0 :                 value->type = vt_invalid;
     107                 :          0 :                 return -1;
     108                 :            :             }
     109                 :         65 :             value->i = (int64_t)value->u;
     110                 :         65 :             value->type = vt_int;
     111                 :         65 :             return 0;
     112                 :            :         }
     113                 :            :         error_sym(P, sym, "64-bit int32_t type only accepts integers");
     114                 :          0 :         value->type = vt_invalid;
     115                 :          0 :         return -1;
     116                 :            :     case fb_int:
     117         [ -  + ]:         38 :         if (value->type == vt_int) {
     118         [ #  # ]:          0 :             if (value->i < INT32_MIN) {
     119                 :            :                 error_sym(P, sym, "32-bit signed int underflow");
     120                 :          0 :                 value->type = vt_invalid;
     121                 :          0 :                 return -1;
     122                 :            :             }
     123                 :            :             return 0;
     124                 :            :         }
     125         [ +  - ]:         38 :         if (value->type == vt_uint) {
     126         [ -  + ]:         38 :             if (value->i > INT32_MAX) {
     127                 :            :                 error_sym(P, sym, "32-bit signed int overflow");
     128                 :          0 :                 value->type = vt_invalid;
     129                 :          0 :                 return -1;
     130                 :            :             }
     131                 :         38 :             value->i = (int64_t)value->u;
     132                 :         38 :             value->type = vt_int;
     133                 :         38 :             return 0;
     134                 :            :         }
     135                 :            :         error_sym(P, sym, "32-bit signed int type only accepts integers");
     136                 :          0 :         value->type = vt_invalid;
     137                 :          0 :         return -1;
     138                 :            :     case fb_short:
     139         [ +  + ]:         31 :         if (value->type == vt_int) {
     140         [ -  + ]:          1 :             if (value->i < INT16_MIN) {
     141                 :            :                 error_sym(P, sym, "16-bit signed short underflow");
     142                 :          0 :                 value->type = vt_invalid;
     143                 :          0 :                 return -1;
     144                 :            :             }
     145                 :            :             return 0;
     146                 :            :         }
     147         [ +  - ]:         30 :         if (value->type == vt_uint) {
     148         [ -  + ]:         30 :             if (value->i > INT16_MAX) {
     149                 :            :                 error_sym(P, sym, "16-bit signed short overflow");
     150                 :          0 :                 value->type = vt_invalid;
     151                 :          0 :                 return -1;
     152                 :            :             }
     153                 :         30 :             value->i = (int64_t)value->u;
     154                 :         30 :             value->type = vt_int;
     155                 :         30 :             return 0;
     156                 :            :         }
     157                 :            :         error_sym(P, sym, "16-bit signed short type only accepts integers");
     158                 :          0 :         value->type = vt_invalid;
     159                 :          0 :         return -1;
     160                 :            :     case fb_byte:
     161         [ -  + ]:         40 :         if (value->type == vt_int) {
     162         [ #  # ]:          0 :             if (value->i < INT8_MIN) {
     163                 :            :                 error_sym(P, sym, "8-bit signed byte underflow");
     164                 :          0 :                 value->type = vt_invalid;
     165                 :          0 :                 return -1;
     166                 :            :             }
     167                 :            :             return 0;
     168                 :            :         }
     169         [ +  - ]:         40 :         if (value->type == vt_uint) {
     170         [ -  + ]:         40 :             if (value->i > INT8_MAX) {
     171                 :            :                 error_sym(P, sym, "8-bit signed byte overflow");
     172                 :          0 :                 value->type = vt_invalid;
     173                 :          0 :                 return -1;
     174                 :            :             }
     175                 :         40 :             value->i = (int64_t)value->u;
     176                 :         40 :             value->type = vt_int;
     177                 :         40 :             return 0;
     178                 :            :         }
     179                 :            :         error_sym(P, sym, "8-bit signed byte type only accepts integers");
     180                 :          0 :         value->type = vt_invalid;
     181                 :          0 :         return -1;
     182                 :            :     case fb_bool:
     183 [ +  + ][ +  - ]:         21 :         if (value->type == vt_uint && P->opts.allow_boolean_conversion) {
     184         [ -  + ]:          9 :             if (value->u > 1) {
     185                 :            :                 error_sym(P, sym, "boolean integer conversion only accepts 0 (false) or 1 (true)");
     186                 :          0 :                 value->type = vt_invalid;
     187                 :          0 :                 return -1;
     188                 :            :             }
     189         [ -  + ]:         12 :         } else if (value->type != vt_bool) {
     190                 :            :             error_sym(P, sym, "boolean type only accepts 'true' or 'false' as values");
     191                 :          0 :             value->type = vt_invalid;
     192                 :          0 :             return -1;
     193                 :            :         }
     194                 :            :         return 0;
     195                 :            :     case fb_double:
     196   [ -  +  -  + ]:          3 :         switch (value->type) {
     197                 :            :         case vt_int:
     198                 :          0 :             d = (double)value->i;
     199         [ #  # ]:          0 :             if ((int64_t)d != value->i) {
     200                 :            :                 /* We could make this a warning. */
     201                 :            :                 error_sym(P, sym, "precision loss in 64-bit double type assignment");
     202                 :          0 :                 value->type = vt_invalid;
     203                 :          0 :                 return -1;
     204                 :            :             }
     205                 :          0 :             value->f = d;
     206                 :          0 :             value->type = vt_float;
     207                 :          0 :             return 0;
     208                 :            :         case vt_uint:
     209                 :          2 :             d = (double)value->u;
     210         [ -  + ]:          2 :             if ((uint64_t)d != value->u) {
     211                 :            :                 /* We could make this a warning. */
     212                 :            :                 error_sym(P, sym, "precision loss in 64-bit double type assignment");
     213                 :          0 :                 value->type = vt_invalid;
     214                 :          0 :                 return -1;
     215                 :            :             }
     216                 :          2 :             value->f = d;
     217                 :          2 :             value->type = vt_float;
     218                 :          2 :             return 0;
     219                 :            :         case vt_float:
     220                 :            :             /* Double is our internal repr., so not loss at this point. */
     221                 :            :             return 0;
     222                 :            :         default:
     223                 :            :             error_sym(P, sym, "64-bit double type only accepts integer and float values");
     224                 :          0 :             value->type = vt_invalid;
     225                 :          0 :             return -1;
     226                 :            :         }
     227                 :            :     case fb_float:
     228   [ -  +  -  - ]:          3 :         switch (value->type) {
     229                 :            :         case vt_int:
     230                 :          0 :             f = (float)value->i;
     231         [ #  # ]:          0 :             if ((int64_t)f != value->i) {
     232                 :            :                 /* We could make this a warning. */
     233                 :            :                 error_sym(P, sym, "precision loss in 32-bit float type assignment");
     234                 :          0 :                 value->type = vt_invalid;
     235                 :          0 :                 return -1;
     236                 :            :             }
     237                 :          0 :             value->f = f;
     238                 :          0 :             value->type = vt_float;
     239                 :          0 :             return 0;
     240                 :            :         case vt_uint:
     241                 :          3 :             f = (float)value->u;
     242         [ -  + ]:          3 :             if ((uint64_t)f != value->u) {
     243                 :            :                 /* We could make this a warning. */
     244                 :            :                 error_sym(P, sym, "precision loss in 32-bit float type assignment");
     245                 :          0 :                 value->type = vt_invalid;
     246                 :          0 :                 return -1;
     247                 :            :             }
     248                 :          3 :             value->f = f;
     249                 :          3 :             value->type = vt_float;
     250                 :          3 :             return 0;
     251                 :            :         case vt_float:
     252                 :          0 :             f = (float)value->f;
     253         [ #  # ]:          0 :             if ((double)f != value->f) {
     254                 :            :                 /* We could make this a warning. */
     255                 :            :                 error_sym(P, sym, "precision loss in 32-bit float type assignment");
     256                 :          0 :                 value->type = vt_invalid;
     257                 :          0 :                 return -1;
     258                 :            :             }
     259                 :            :             return 0;
     260                 :            :         default:
     261                 :            :             error_sym(P, sym, "32-bit float type only accepts integer and float values");
     262                 :          0 :             value->type = vt_invalid;
     263                 :          0 :             return -1;
     264                 :            :         }
     265                 :            :     default:
     266                 :            :         error_sym(P, sym, "scalar type expected");
     267                 :          0 :         value->type = vt_invalid;
     268                 :          0 :         return -1;
     269                 :            :     }
     270                 :            : }
     271                 :            : 

Generated by: LCOV version 1.12