Module: AdLint::Cc1::UsualArithmeticTypeConversion
- Included in:
- ScalarDataType
- Defined in:
- lib/adlint/cc1/conv.rb
Overview
Host class of this module must include StandardTypeCatalogAccessor.
Instance Method Summary collapse
Instance Method Details
#do_usual_arithmetic_type_conversion(lhs, rhs) ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 |
# File 'lib/adlint/cc1/conv.rb', line 145 def do_usual_arithmetic_type_conversion(lhs, rhs) # NOTE: The ISO C99 standard says; # # 6.3.1.8 Usual arithmetic conversions # # 1 Many operators that except operands of arithmetic type cause # conversions and yield result types in a similar way. The purpose is # to determine a common real type for the operands and result. For the # specified operands, each operand is converted, without change of type # domain, to a type whose corresponding real type is the common real # type. Unless explicitly stated otherwise, the common real type is # also the corresponding real type of the result, whose type domain is # the type domain of the operands if they are the same, and complex # otherwise. This pattern is called the usual arithmetic conversions: # # First, if the corresponding real type of either operand is long # double, the other operand is converted, without change of type # domain, to a type whose corresponding real type is long double. # # Otherwise, if the corresponding real type of either operand is # double, the other operand is converted, without change of type # domain, to a type whose corresponding real type is double. # # Otherwise, if the corresponding real type of either operand is # float, the other operand is converted, without change of type # domain, to a type whose corresponding real type is float. # # Otherwise, the integer promotions are performed on both operands. # Then the following rules are applied to the promoted operands: # # If both operands have the same type, then no further conversion # is needed. # # Otherwise, if both operands have signed integer types or both # have unsigned integer types, the operand with the type of lesser # integer conversion rank is converted to the type of the operand # with greater rank. # # Otherwise, if the operand that has unsigned integer type has rank # greater or equal to the rank of the type of the other operand, # then the operand with signed integer type is converted to the # type of the operand with unsigned integer type. # # Otherwise, if the type of the operand with signed integer type # can represent all of the values of the type of the operand with # unsigned integer type, then the operand with unsigned integer # type is converted to the type of the operand with signed integer # type. # # Otherwise, both operands are converted to the unsigned integer # type corresponding to the type of the operand with signed integer # type. if lhs.same_as?(long_double_t) || rhs.same_as?(long_double_t) return long_double_t end if lhs.same_as?(double_t) || rhs.same_as?(double_t) return double_t end if lhs.same_as?(float_t) || rhs.same_as?(float_t) return float_t end lhs_promoted = lhs.integer_promoted_type rhs_promoted = rhs.integer_promoted_type return lhs_promoted if lhs_promoted.same_as?(rhs_promoted) lhs_rank = lhs_promoted.integer_conversion_rank rhs_rank = rhs_promoted.integer_conversion_rank case when lhs_promoted.signed? && rhs_promoted.signed? return lhs_rank < rhs_rank ? rhs_promoted : lhs_promoted when lhs_promoted.unsigned? && rhs_promoted.unsigned? return lhs_rank < rhs_rank ? rhs_promoted : lhs_promoted when lhs_promoted.unsigned? && lhs_rank >= rhs_rank return lhs_promoted when rhs_promoted.unsigned? && lhs_rank <= rhs_rank return rhs_promoted when lhs_promoted.signed? && rhs_promoted.compatible?(lhs_promoted) return lhs_promoted when rhs_promoted.signed? && lhs_promoted.compatible?(rhs_promoted) return rhs_promoted when lhs_promoted.signed? return lhs_promoted.corresponding_unsigned_type when rhs_promoted.signed? return rhs_promoted.corresponding_unsigned_type end raise TypeError, "cannot do usual arithmetic conversion." end |