module AdLint::Cc1::UsualArithmeticTypeConversion
Host class of this module must include StandardTypeCatalogAccessor
.
Public Instance Methods
do_usual_arithmetic_type_conversion(lhs, rhs)
click to toggle source
# 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