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