module AdLint::Cc1::ExpressionEvaluator::Impl
Public Instance Methods
eval_additive_expr(node, lhs_obj, rhs_obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 920 def eval_additive_expr(node, lhs_obj, rhs_obj) lhs_var = object_to_variable(lhs_obj, node.lhs_operand) if !lhs_var.type.scalar? && !lhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end rhs_var = object_to_variable(rhs_obj, node.rhs_operand) if !rhs_var.type.scalar? && !rhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end lhs_conved, rhs_conved = do_usual_arithmetic_conversion(lhs_var, rhs_var) unless lhs_conved == lhs_var notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved) end unless rhs_conved == rhs_var notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end lhs_val = lhs_conved.value rhs_val = rhs_conved.value case node.operator.type when "+" # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. rslt_var = create_tmpvar(lhs_conved.type, lhs_val + rhs_val) when "-" # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. rslt_var = create_tmpvar(lhs_conved.type, lhs_val - rhs_val) else __NOTREACHED__ end _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_additive_expr_evaled(node, lhs_var, rhs_var, rslt_var) rslt_var end
eval_address_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 774 def eval_address_expr(node, obj) # NOTE: An address-expression does not read the value of the object. # But value reference should be notified to emphasize global # variable cross-references. _notify_variable_value_referred(node, obj) ptr = object_to_pointer(obj, node) notify_address_expr_evaled(node, obj, ptr) ptr end
eval_and_expr(node, lhs_obj, rhs_obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1106 def eval_and_expr(node, lhs_obj, rhs_obj) lhs_var = object_to_variable(lhs_obj, node.lhs_operand) if !lhs_var.type.scalar? && !lhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end rhs_var = object_to_variable(rhs_obj, node.rhs_operand) if !rhs_var.type.scalar? && !rhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end lhs_conved, rhs_conved = do_usual_arithmetic_conversion(lhs_var, rhs_var) unless lhs_conved == lhs_var notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved) end unless rhs_conved == rhs_var notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end lhs_val = lhs_conved.value rhs_val = rhs_conved.value # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. rslt_var = create_tmpvar(lhs_conved.type, lhs_val & rhs_val) _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_and_expr_evaled(node, lhs_var, rhs_var, rslt_var) rslt_var end
eval_array_subscript_expr(node, obj, subs)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 476 def eval_array_subscript_expr(node, obj, subs) unless obj.variable? and obj.type.array? || obj.type.pointer? return create_tmpvar end rslt_type = obj.type.unqualify.base_type case when obj.type.array? ary = obj # NOTE: An array-subscript-expression with an array object only # refers the array object, never refer the value of the array # object. when obj.type.pointer? ptr = obj if pointee = pointee_of(ptr) and pointee.type.array? ary = pointee end # NOTE: An array-subscript-expression with a pointer object do refers # the value of the pointer object. _notify_variable_value_referred(node, ptr) end unless subs.variable? and subs.value.scalar? && subs.value.exist? or subs.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar(rslt_type) end _notify_variable_value_referred(node, subs) # NOTE: An array subscript converted to `int' implicitly. unless subs.type.same_as?(int_t) if int_subs = do_conversion(subs, int_t) notify_implicit_conv_performed(node.array_subscript, subs, int_subs) subs = int_subs else return create_tmpvar(rslt_type) end end rslt_var = _pick_array_element(node, ary, subs, rslt_type) notify_array_subscript_expr_evaled(node, obj, subs, ary, rslt_var) rslt_var end
eval_bit_access_by_pointer_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 648 def eval_bit_access_by_pointer_expr(node, obj) obj_type = obj.type.unqualify if obj.variable? && obj_type.pointer? && obj_type.base_type.composite? ptr = obj else return create_tmpvar end if pointee = pointee_of(ptr) if pointee.type.array? if first_elem = pointee.inner_variable_at(0) pointee = first_elem else pointee = create_tmpvar(obj_type.base_type) end end end # NOTE: A bit-access-by-pointer-expression do refers the value of the # pointer object. _notify_variable_value_referred(node, ptr) # TODO: Should support the GCC extension. create_tmpvar.tap do |rslt_var| notify_bit_access_expr_evaled(node, ptr, rslt_var) end end
eval_bit_access_by_value_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 635 def eval_bit_access_by_value_expr(node, obj) if obj.variable? && obj.type.composite? outer_var = obj else return create_tmpvar end # TODO: Should support the GCC extension. create_tmpvar.tap do |rslt_var| notify_bit_access_expr_evaled(node, outer_var, rslt_var) end end
eval_cast_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 848 def eval_cast_expr(node, obj) resolve_unresolved_type(node.type_name) var = object_to_variable(obj, node) rslt_var = do_conversion(var, node.type_name.type) || create_tmpvar(node.type_name.type) notify_explicit_conv_performed(node, var, rslt_var) # NOTE: A cast-expression does not refer a source value essentially. # But, to avoid misunderstand that a return value of a function # is discarded when the return value is casted before assigning # to a variable. _notify_variable_value_referred(node, var) notify_cast_expr_evaled(node, var, rslt_var) rslt_var end
eval_compound_assignment_expr(node, lhs_obj, rhs_obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1240 def eval_compound_assignment_expr(node, lhs_obj, rhs_obj) lhs_var = object_to_variable(lhs_obj, node.lhs_operand) if !lhs_var.type.scalar? && !lhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return lhs_obj end rhs_var = object_to_variable(rhs_obj, node.rhs_operand) if !rhs_var.type.scalar? && !rhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return lhs_var end case node.operator.type when "*=" _do_mul_then_assign(node, lhs_var, rhs_var) when "/=" _do_div_then_assign(node, lhs_var, rhs_var) when "%=" _do_mod_then_assign(node, lhs_var, rhs_var) when "+=" _do_add_then_assign(node, lhs_var, rhs_var) when "-=" _do_sub_then_assign(node, lhs_var, rhs_var) when "<<=" _do_shl_then_assign(node, lhs_var, rhs_var) when ">>=" _do_shr_then_assign(node, lhs_var, rhs_var) when "&=" _do_and_then_assign(node, lhs_var, rhs_var) when "^=" _do_xor_then_assign(node, lhs_var, rhs_var) when "|=" _do_ior_then_assign(node, lhs_var, rhs_var) end lhs_var end
eval_compound_literal_expr(node)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 767 def eval_compound_literal_expr(node) # TODO: Should support C99 features. create_tmpvar(node.type_name.type).tap do |rslt_var| notify_compound_literal_expr_evaled(node, rslt_var) end end
eval_equality_expr(node, lhs_obj, rhs_obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1065 def eval_equality_expr(node, lhs_obj, rhs_obj) lhs_var = object_to_variable(lhs_obj, node.lhs_operand) if !lhs_var.type.scalar? && !lhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar(int_t, scalar_value_of_arbitrary) end rhs_var = object_to_variable(rhs_obj, node.rhs_operand) if !rhs_var.type.scalar? && !rhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar(int_t, scalar_value_of_arbitrary) end lhs_conved, rhs_conved = do_usual_arithmetic_conversion(lhs_var, rhs_var) unless lhs_conved == lhs_var notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved) end unless rhs_conved == rhs_var notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end lhs_val = lhs_conved.value rhs_val = rhs_conved.value case node.operator.type when "==" rslt_var = create_tmpvar(int_t, lhs_val == rhs_val) when "!=" rslt_var = create_tmpvar(int_t, lhs_val != rhs_val) else __NOTREACHED__ end _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_equality_expr_evaled(node, lhs_var, rhs_var, rslt_var) rslt_var end
eval_exclusive_or_expr(node, lhs_obj, rhs_obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1142 def eval_exclusive_or_expr(node, lhs_obj, rhs_obj) lhs_var = object_to_variable(lhs_obj, node.lhs_operand) if !lhs_var.type.scalar? && !lhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end rhs_var = object_to_variable(rhs_obj, node.rhs_operand) if !rhs_var.type.scalar? && !rhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end lhs_conved, rhs_conved = do_usual_arithmetic_conversion(lhs_var, rhs_var) unless lhs_conved == lhs_var notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved) end unless rhs_conved == rhs_var notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end lhs_val = lhs_conved.value rhs_val = rhs_conved.value # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. rslt_var = create_tmpvar(lhs_conved.type, lhs_val ^ rhs_val) _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_exclusive_or_expr_evaled(node, lhs_var, rhs_var, rslt_var) rslt_var end
eval_function_call_expr(node, obj, args)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 522 def eval_function_call_expr(node, obj, args) if obj.function? fun = obj else return create_tmpvar unless obj.type.pointer? obj_base_type = obj.type.unqualify.base_type if obj_base_type.function? if pointee = pointee_of(obj) and pointee.function? fun = pointee else fun = define_anonymous_function(obj_base_type) end end end _notify_variable_value_referred(node, obj) # NOTE: The ISO C99 standard says; # # 6.5.2.2 Function calls # # Semantics # # 10 The order of evaluation of the function designator, the actual # arguments, and subexpressions within the actual arguments is # unspecified, but there is a sequence point before the actual call. unless args.empty? notify_sequence_point_reached(SequencePoint.new(node)) end rslt_var = nil break_event = BreakEvent.catch { rslt_var = fun.call(interpreter, node, args) } unless fun.builtin? arg_vars = args.map { |arg_obj, arg_expr| object_to_variable(arg_obj, arg_expr) } notify_function_call_expr_evaled(node, fun, arg_vars, rslt_var) end if break_event break_event.throw else rslt_var end end
eval_inclusive_or_expr(node, lhs_obj, rhs_obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1178 def eval_inclusive_or_expr(node, lhs_obj, rhs_obj) lhs_var = object_to_variable(lhs_obj, node.lhs_operand) if !lhs_var.type.scalar? && !lhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end rhs_var = object_to_variable(rhs_obj, node.rhs_operand) if !rhs_var.type.scalar? && !rhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end lhs_conved, rhs_conved = do_usual_arithmetic_conversion(lhs_var, rhs_var) unless lhs_conved == lhs_var notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved) end unless rhs_conved == rhs_var notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end lhs_val = lhs_conved.value rhs_val = rhs_conved.value # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. rslt_var = create_tmpvar(lhs_conved.type, lhs_val | rhs_val) _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_inclusive_or_expr_evaled(node, lhs_var, rhs_var, rslt_var) rslt_var end
eval_indirection_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 785 def eval_indirection_expr(node, obj) var = object_to_variable(obj, node) if var.type.pointer? ptr = var else return create_tmpvar end pointee = pointee_of(ptr) _notify_variable_value_referred(node, ptr) ptr_base_type = ptr.type.unqualify.base_type case when pointee _notify_object_referred(node, pointee) if pointee.type.array? if first_elem = pointee.inner_variable_at(0) pointee = first_elem else pointee = create_tmpvar(ptr_base_type) end end unless ptr_base_type.same_as?(pointee.type) pointee = do_conversion(pointee, ptr_base_type) || create_tmpvar(ptr_base_type) end when ptr_base_type.function? pointee = define_anonymous_function(ptr_base_type) else pointee = create_tmpvar(ptr_base_type) end notify_indirection_expr_evaled(node, ptr, pointee) pointee end
eval_member_access_by_pointer_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 593 def eval_member_access_by_pointer_expr(node, obj) obj_type = obj.type.unqualify if obj.variable? && obj_type.pointer? && obj_type.base_type.composite? ptr = obj else return create_tmpvar end if pointee = pointee_of(ptr) if pointee.type.array? if first_elem = pointee.inner_variable_at(0) pointee = first_elem else pointee = create_tmpvar(obj_type.base_type) end end end # NOTE: A member-access-by-pointer-expression do refers the value of # the pointer object. _notify_variable_value_referred(node, ptr) if pointee && pointee.type.composite? outer_var = pointee memb_var = outer_var.inner_variable_named(node.identifier.value) else if memb = obj_type.base_type.member_named(node.identifier.value) memb_var = create_tmpvar(memb.type) end end # NOTE: `memb_var' is nil when this expression represents the direct # member access extension. notify_member_access_expr_evaled(node, ptr, memb_var) if memb_var _notify_object_referred(node, memb_var) memb_var else create_tmpvar end end
eval_member_access_by_value_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 570 def eval_member_access_by_value_expr(node, obj) if obj.variable? && obj.type.composite? outer_var = obj else return create_tmpvar end memb_var = outer_var.inner_variable_named(node.identifier.value) # NOTE: A member-access-by-value-expression only refers the composite # object, never refer the value of the composite object. # NOTE: `memb_var' is nil when this expression represents the direct # member access extension. notify_member_access_expr_evaled(node, outer_var, memb_var) if memb_var _notify_object_referred(node, memb_var) memb_var else create_tmpvar end end
eval_multiplicative_expr(node, lhs_obj, rhs_obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 867 def eval_multiplicative_expr(node, lhs_obj, rhs_obj) lhs_var = object_to_variable(lhs_obj, node.lhs_operand) if !lhs_var.type.scalar? && !lhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end rhs_var = object_to_variable(rhs_obj, node.rhs_operand) if !rhs_var.type.scalar? && !rhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end lhs_conved, rhs_conved = do_usual_arithmetic_conversion(lhs_var, rhs_var) unless lhs_conved == lhs_var notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved) end unless rhs_conved == rhs_var notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end lhs_val = lhs_conved.value rhs_val = rhs_conved.value case node.operator.type when "*" # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. rslt_var = create_tmpvar(lhs_conved.type, lhs_val * rhs_val) when "/" # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. # NOTE: "Div by 0" semantics is implemented in value-value # arithmetic. rslt_var = create_tmpvar(lhs_conved.type, lhs_val / rhs_val) when "%" # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. # NOTE: "Div by 0" semantics is implemented in value-value # arithmetic. rslt_var = create_tmpvar(lhs_conved.type, lhs_val % rhs_val) else __NOTREACHED__ end _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, rslt_var) rslt_var end
eval_object_specifier(node)
click to toggle source
NOTE: Host class of this module must include InterpreterMediator
,
NotifierMediator and Conversion.
# File lib/adlint/cc1/expr.rb, line 446 def eval_object_specifier(node) case when var = variable_named(node.identifier.value) var.declarations_and_definitions.each do |dcl_or_def| dcl_or_def.mark_as_referred_by(node.identifier) end _notify_object_referred(node, var) # NOTE: Array object will be converted into its start address by the # outer expression. So, it is correct to return an array # object itself. rslt_obj = var when fun = function_named(node.identifier.value) fun.declarations_and_definitions.each do |dcl_or_def| dcl_or_def.mark_as_referred_by(node.identifier) end _notify_object_referred(node, fun) rslt_obj = fun when enum = enumerator_named(node.identifier.value) enum.mark_as_referred_by(node.identifier) rslt_obj = create_tmpvar(enum.type, scalar_value_of(enum.value)) else fun = declare_implicit_function(node.identifier.value) _notify_implicit_function_declared(node, fun) _notify_object_referred(node, fun) rslt_obj = fun end notify_object_specifier_evaled(node, rslt_obj) rslt_obj end
eval_postfix_decrement_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 698 def eval_postfix_decrement_expr(node, obj) var = object_to_variable(obj, node) if !var.type.scalar? && !var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end rslt_var = create_tmpvar(var.type, var.value.dup) # NOTE: Value of the variable is referred at this point. But value # reference should not be notified not to confuse sequence-point # warnings detections. # _notify_variable_value_referred(node, var) if var.value.scalar? var.assign!(var.value - scalar_value_of(1), node, current_branch) _notify_variable_value_updated(node, var) end notify_postfix_decrement_expr_evaled(node, var, rslt_var) rslt_var end
eval_postfix_increment_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 675 def eval_postfix_increment_expr(node, obj) var = object_to_variable(obj, node) if !var.type.scalar? && !var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end rslt_var = create_tmpvar(var.type, var.value.dup) # NOTE: Value of the variable is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, var) if var.value.scalar? var.assign!(var.value + scalar_value_of(1), node, current_branch) _notify_variable_value_updated(node, var) end notify_postfix_increment_expr_evaled(node, var, rslt_var) rslt_var end
eval_prefix_decrement_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 744 def eval_prefix_decrement_expr(node, obj) var = object_to_variable(obj, node) if !var.type.scalar? && !var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end orig_val = var.value.dup # NOTE: Value of the variable is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, var) if var.value.scalar? var.assign!(var.value - scalar_value_of(1), node, current_branch) _notify_variable_value_updated(node, var) end notify_prefix_decrement_expr_evaled(node, var, orig_val) create_tmpvar(var.type, var.value) end
eval_prefix_increment_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 721 def eval_prefix_increment_expr(node, obj) var = object_to_variable(obj, node) if !var.type.scalar? && !var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end orig_val = var.value.dup # NOTE: Value of the variable is referred at this point. But value # reference should not be notified not to confuse sequence-point # warnings detections. # _notify_variable_value_referred(node, var) if var.value.scalar? var.assign!(var.value + scalar_value_of(1), node, current_branch) _notify_variable_value_updated(node, var) end notify_prefix_increment_expr_evaled(node, var, orig_val) create_tmpvar(var.type, var.value) end
eval_relational_expr(node, lhs_obj, rhs_obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1020 def eval_relational_expr(node, lhs_obj, rhs_obj) lhs_var = object_to_variable(lhs_obj, node.lhs_operand) if !lhs_var.type.scalar? && !lhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar(int_t, scalar_value_of_arbitrary) end rhs_var = object_to_variable(rhs_obj, node.rhs_operand) if !rhs_var.type.scalar? && !rhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar(int_t, scalar_value_of_arbitrary) end lhs_conved, rhs_conved = do_usual_arithmetic_conversion(lhs_var, rhs_var) unless lhs_conved == lhs_var notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved) end unless rhs_conved == rhs_var notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end lhs_val = lhs_conved.value rhs_val = rhs_conved.value case node.operator.type when "<" rslt_var = create_tmpvar(int_t, lhs_val < rhs_val) when ">" rslt_var = create_tmpvar(int_t, lhs_val > rhs_val) when "<=" rslt_var = create_tmpvar(int_t, lhs_val <= rhs_val) when ">=" rslt_var = create_tmpvar(int_t, lhs_val >= rhs_val) else __NOTREACHED__ end _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_relational_expr_evaled(node, lhs_var, rhs_var, rslt_var) rslt_var end
eval_shift_expr(node, lhs_obj, rhs_obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 965 def eval_shift_expr(node, lhs_obj, rhs_obj) lhs_var = object_to_variable(lhs_obj, node.lhs_operand) if !lhs_var.type.scalar? && !lhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end rhs_var = object_to_variable(rhs_obj, node.rhs_operand) if !rhs_var.type.scalar? && !rhs_var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end # NOTE: The ISO C99 standard says; # # 6.5.7 Bitwise shift operators # # 3 The integer promotions are performed on each of the operands. The # type of the result is that of the promoted left operand. If the # value of the right operand is negative or is greater than or equal # to the width of the promoted left operand, the behavior is # undefined. lhs_conved = do_integer_promotion(lhs_var) rhs_conved = do_integer_promotion(rhs_var) unless lhs_conved == lhs_var notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved) end unless rhs_conved == rhs_var notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end lhs_val = lhs_conved.value rhs_val = rhs_conved.value case node.operator.type when "<<" # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. rslt_var = create_tmpvar(lhs_conved.type, lhs_val << rhs_val) when ">>" # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. rslt_var = create_tmpvar(lhs_conved.type, lhs_val >> rhs_val) else __NOTREACHED__ end _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_shift_expr_evaled(node, lhs_var, rhs_var, rslt_var) rslt_var end
eval_simple_assignment_expr(node, lhs_obj, rhs_obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1214 def eval_simple_assignment_expr(node, lhs_obj, rhs_obj) lhs_var = object_to_variable(lhs_obj, node.lhs_operand) rhs_var = object_to_variable(rhs_obj, node.rhs_operand) if rhs_var.type.same_as?(lhs_var.type) rhs_conved = rhs_var else rhs_conved = do_conversion(rhs_var, lhs_var.type) || create_tmpvar(lhs_var.type) notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. # NOTE: Even if rhs_obj is a NamedVariable, new value will be # instantiated in value-coercing. # So, value-aliasing never occurs. defined_val = rhs_conved.value.to_defined_value lhs_var.assign!(defined_val, node, current_branch) _notify_variable_value_referred(node, rhs_var) _notify_variable_value_updated(node, lhs_var) notify_assignment_expr_evaled(node, lhs_var, rhs_var) lhs_var end
eval_unary_arithmetic_expr(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 823 def eval_unary_arithmetic_expr(node, obj) var = object_to_variable(obj, node) if !var.type.scalar? && !var.type.void? # NOTE: To detect bad value reference of `void' expressions. return create_tmpvar end case node.operator.type when "+" rslt_var = create_tmpvar(var.type, +var.value) when "-" rslt_var = create_tmpvar(var.type, -var.value) when "~" rslt_var = create_tmpvar(var.type, ~var.value) when "!" rslt_var = create_tmpvar(int_t, !var.value) else __NOTREACHED__ end _notify_variable_value_referred(node, var) notify_unary_arithmetic_expr_evaled(node, var, rslt_var) rslt_var end
Private Instance Methods
_do_add_then_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1336 def _do_add_then_assign(node, lhs_var, rhs_var) lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var) lhs_val = lhs_conved.value rhs_val = rhs_conved.value rslt_var = create_tmpvar(lhs_conved.type, lhs_val + rhs_val) # NOTE: Value of the lhs_var is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_additive_expr_evaled(node, lhs_var, rhs_var, rslt_var) _do_assign(node, lhs_var, rslt_var) end
_do_and_then_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1426 def _do_and_then_assign(node, lhs_var, rhs_var) lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var) lhs_val = lhs_conved.value rhs_val = rhs_conved.value rslt_var = create_tmpvar(lhs_conved.type, lhs_val & rhs_val) # NOTE: Value of the lhs_var is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_and_expr_evaled(node, lhs_var, rhs_var, rslt_var) _do_assign(node, lhs_var, rslt_var) end
_do_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1508 def _do_assign(node, lhs_var, rhs_var) if rhs_var.type.same_as?(lhs_var.type) rhs_conved = rhs_var else rhs_conved = do_conversion(rhs_var, lhs_var.type) || create_tmpvar(lhs_var.type) notify_implicit_conv_performed(node.lhs_operand, rhs_var, rhs_conved) end # NOTE: Domain of the arithmetic result value will be restricted by # min-max of the variable type. defined_val = rhs_conved.value.to_defined_value lhs_var.assign!(defined_val, node, current_branch) _notify_variable_value_updated(node, lhs_var) notify_assignment_expr_evaled(node, lhs_var, rhs_conved) end
_do_div_then_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1298 def _do_div_then_assign(node, lhs_var, rhs_var) lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var) lhs_val = lhs_conved.value rhs_val = rhs_conved.value # NOTE: "Div by 0" semantics is implemented in value-value arithmetic. rslt_var = create_tmpvar(lhs_conved.type, lhs_val / rhs_val) # NOTE: Value of the lhs_var is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, rslt_var) _do_assign(node, lhs_var, rslt_var) end
_do_integer_promotions(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1494 def _do_integer_promotions(node, lhs_var, rhs_var) lhs_conved = do_integer_promotion(lhs_var) unless lhs_conved == lhs_var notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved) end rhs_conved = do_integer_promotion(rhs_var) unless rhs_conved == rhs_var notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end return lhs_conved, rhs_conved end
_do_ior_then_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1462 def _do_ior_then_assign(node, lhs_var, rhs_var) lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var) lhs_val = lhs_conved.value rhs_val = rhs_conved.value rslt_var = create_tmpvar(lhs_conved.type, lhs_val | rhs_val) # NOTE: Value of the lhs_var is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_inclusive_or_expr_evaled(node, lhs_var, rhs_var, rslt_var) _do_assign(node, lhs_var, rslt_var) end
_do_mod_then_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1317 def _do_mod_then_assign(node, lhs_var, rhs_var) lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var) lhs_val = lhs_conved.value rhs_val = rhs_conved.value # NOTE: "Div by 0" semantics is implemented in value-value arithmetic. rslt_var = create_tmpvar(lhs_conved.type, lhs_val % rhs_val) # NOTE: Value of the lhs_var is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, rslt_var) _do_assign(node, lhs_var, rslt_var) end
_do_mul_then_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1280 def _do_mul_then_assign(node, lhs_var, rhs_var) lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var) lhs_val = lhs_conved.value rhs_val = rhs_conved.value rslt_var = create_tmpvar(lhs_conved.type, lhs_val * rhs_val) # NOTE: Value of the lhs_var is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_multiplicative_expr_evaled(node, lhs_var, rhs_var, rslt_var) _do_assign(node, lhs_var, rslt_var) end
_do_shl_then_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1372 def _do_shl_then_assign(node, lhs_var, rhs_var) # NOTE: The ISO C99 standard says; # # 6.5.7 Bitwise shift operators # # 3 The integer promotions are performed on each of the operands. The # type of the result is that of the promoted left operand. If the # value of the right operand is negative or is greater than or equal # to the width of the promoted left operand, the behavior is # undefined. lhs_conved, rhs_conved = _do_integer_promotions(node, lhs_var, rhs_var) lhs_val = lhs_conved.value rhs_val = rhs_conved.value rslt_var = create_tmpvar(lhs_conved.type, lhs_val << rhs_val) # NOTE: Value of the lhs_var is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_shift_expr_evaled(node, lhs_var, rhs_var, rslt_var) _do_assign(node, lhs_var, rslt_var) end
_do_shr_then_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1399 def _do_shr_then_assign(node, lhs_var, rhs_var) # NOTE: The ISO C99 standard says; # # 6.5.7 Bitwise shift operators # # 3 The integer promotions are performed on each of the operands. The # type of the result is that of the promoted left operand. If the # value of the right operand is negative or is greater than or equal # to the width of the promoted left operand, the behavior is # undefined. lhs_conved, rhs_conved = _do_integer_promotions(node, lhs_var, rhs_var) lhs_val = lhs_conved.value rhs_val = rhs_conved.value rslt_var = create_tmpvar(lhs_conved.type, lhs_val >> rhs_val) # NOTE: Value of the lhs_var is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_shift_expr_evaled(node, lhs_var, rhs_var, rslt_var) _do_assign(node, lhs_var, rslt_var) end
_do_sub_then_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1354 def _do_sub_then_assign(node, lhs_var, rhs_var) lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var) lhs_val = lhs_conved.value rhs_val = rhs_conved.value rslt_var = create_tmpvar(lhs_conved.type, lhs_val - rhs_val) # NOTE: Value of the lhs_var is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_additive_expr_evaled(node, lhs_var, rhs_var, rslt_var) _do_assign(node, lhs_var, rslt_var) end
_do_uarith_conversion(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1480 def _do_uarith_conversion(node, lhs_var, rhs_var) lhs_conved, rhs_conved = do_usual_arithmetic_conversion(lhs_var, rhs_var) unless lhs_conved == lhs_var notify_implicit_conv_performed(node.lhs_operand, lhs_var, lhs_conved) end unless rhs_conved == rhs_var notify_implicit_conv_performed(node.rhs_operand, rhs_var, rhs_conved) end return lhs_conved, rhs_conved end
_do_xor_then_assign(node, lhs_var, rhs_var)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1444 def _do_xor_then_assign(node, lhs_var, rhs_var) lhs_conved, rhs_conved = _do_uarith_conversion(node, lhs_var, rhs_var) lhs_val = lhs_conved.value rhs_val = rhs_conved.value rslt_var = create_tmpvar(lhs_conved.type, lhs_val ^ rhs_val) # NOTE: Value of the lhs_var is referred at this point. But value # reference should not be notified not to confuse sequence-point # warning detections. # _notify_variable_value_referred(node, lhs_var) _notify_variable_value_referred(node, rhs_var) notify_exclusive_or_expr_evaled(node, lhs_var, rhs_var, rslt_var) _do_assign(node, lhs_var, rslt_var) end
_notify_implicit_function_declared(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1576 def _notify_implicit_function_declared(node, obj) if obj.function? && obj.implicit? interpreter.notify_implicit_function_declared(node, obj) end end
_notify_object_referred(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1545 def _notify_object_referred(node, obj) case obj when Variable interpreter.notify_variable_referred(node, obj) when Function interpreter.notify_function_referred(node, obj) end end
_notify_variable_value_referred(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1554 def _notify_variable_value_referred(node, obj) if obj.variable? interpreter.notify_variable_value_referred(node, obj) end # NOTE: When a value of the inner-variable of array or composite object # is referred, notification of the outer variable's value has # already been done in sub expressions. end
_notify_variable_value_updated(node, obj)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1564 def _notify_variable_value_updated(node, obj) if obj.variable? interpreter.notify_variable_value_updated(node, obj) if obj.inner? # NOTE: When a value of the inner-variable of array or composite # object is updated, the outer variable's value should also # be notified to be updated. _notify_variable_value_updated(node, obj.owner) end end end
_pick_array_element(expr, ary, subs, rslt_type)
click to toggle source
# File lib/adlint/cc1/expr.rb, line 1526 def _pick_array_element(expr, ary, subs, rslt_type) if ary if subs.value.definite? inner_var = ary.inner_variable_at(subs.value.unique_sample) if inner_var && inner_var.type.same_as?(rslt_type) _notify_object_referred(expr, inner_var) return inner_var end else # NOTE: To improve heuristics of array subscript evaluation with an # indefinite subscript. inner_var = ary.representative_element _notify_object_referred(expr, inner_var) return inner_var end end create_tmpvar(rslt_type) end