class AdLint::Cc1::InitializerInterpreter

Public Class Methods

new(interp) click to toggle source
# File lib/adlint/cc1/interp.rb, line 724
def initialize(interp)
  @interpreter = interp
end

Public Instance Methods

execute(var_def) click to toggle source
# File lib/adlint/cc1/interp.rb, line 728
def execute(var_def)
  checkpoint(var_def.initializer.location)

  case
  when expr = var_def.initializer.expression
    # NOTE: An implicit conversion is already notified in
    #       #evaluate_expression.
    return evaluate_expression(expr, var_def.type)
  when inits = var_def.initializer.initializers
    var = evaluate_initializers(inits, var_def.type)

    # NOTE: Size deduction of an incomplete array type have been done by
    #       #evaluate_initializers.
    if var_def.type.array? && var.type.array?
      var_def.type = var.type unless var_def.type.length
    end

    if var.type.same_as?(var_def.type)
      conved = var
    else
      conved = do_conversion(var, var_def.type) ||
               create_tmpvar(var_def.type)
      notify_implicit_conv_performed(inits, var, conved)
    end
  else
    var = conved = create_tmpvar(var_def.type)
  end

  return var, conved
end

Private Instance Methods

deduct_array_length_from_initializers(orig_ary_type, inits) click to toggle source
# File lib/adlint/cc1/interp.rb, line 855
def deduct_array_length_from_initializers(orig_ary_type, inits)
  unless orig_ary_type.length
    if orig_ary_type.user?
      orig_ary_type = orig_ary_type.dup
    end
    orig_ary_type.length = inits.size
  end
  orig_ary_type
end
evaluate_expression(expr, type) click to toggle source
# File lib/adlint/cc1/interp.rb, line 760
def evaluate_expression(expr, type)
  checkpoint(expr.location)

  var = object_to_variable(interpret(expr), expr)

  if var.type.same_as?(type)
    conved = var
  else
    conved = do_conversion(var, type) || create_tmpvar(type)
    notify_implicit_conv_performed(expr, var, conved)
  end

  return var, conved
end
evaluate_initializers(inits, type) click to toggle source
# File lib/adlint/cc1/interp.rb, line 775
def evaluate_initializers(inits, type)
  case
  when type.union?
    # NOTE: The ISO C99 standard says;
    #
    # 6.7.8 Initialization
    #
    # Semantics
    #
    # 10 If an object that has automatic storage duration is not
    #    initialized explicitly, its value is indeterminate.  If an object
    #    that has static storage duration is not initialized explicitly,
    #    then:
    #    -- if it has pointer type, it is initialized to a null pointer;
    #    -- if it has arithmetic type, it is initialized to (positive or
    #       unsigned) zero;
    #    -- if it is an aggregate, every member is initialized
    #       (recursively) according to these rules;
    #    -- if it is a union, the first named member is initialized
    #       (recursively) according to these rules.
    if fst_memb = type.members.first
      fst_obj = evaluate_initializers(inits, fst_memb.type)
      return create_tmpvar(type, value_of(fst_obj))
    else
      return create_tmpvar(type)
    end
  when type.array?
    # NOTE: The ISO C99 standard says;
    #
    # 6.7.2.1 Structure and union specifiers
    #
    # Constraints
    #
    # 2 A structure or union shall not contain a member with incomplete
    #   or function type (hence, a structure shall not contain an
    #   instance of itself, but may contain a pointer to an instance of
    #   itself), except that the last member of a structure with more
    #   than one named member may have incomplete array type; such a
    #   structure (and any union containing, possibly recursively, a
    #   member that is such a structure) shall not be a member of a
    #   structure or an element of an array.
    #
    # NOTE: Size of the last incomplete array member should not be
    #       deducted in initialization.  It is treated as a pointer.
    #
    # NOTE: ISO C90 does not support flexible array members.
    type = deduct_array_length_from_initializers(type, inits)
    memb_types = [type.unqualify.base_type] * type.impl_length
  when type.struct?
    memb_types = type.members.map { |memb| memb.type }
  else
    memb_types = [type]
  end

  vals = memb_types.zip(inits).map { |memb_type, init|
    if init
      checkpoint(init.location)
      case
      when expr = init.expression
        value_of(evaluate_expression(expr, memb_type).last)
      when inits = init.initializers
        value_of(evaluate_initializers(inits, memb_type))
      else
        memb_type.undefined_value
      end
    else
      memb_type.undefined_value
    end
  }

  case
  when type.array?
    create_tmpvar(type, ArrayValue.new(vals))
  when type.composite?
    create_tmpvar(type, CompositeValue.new(vals))
  else
    create_tmpvar(type, vals.first)
  end
end
interpreter() click to toggle source
# File lib/adlint/cc1/interp.rb, line 865
def interpreter
  # NOTE: This is private attr_reader for InterpreterMediator.
  #       This attribute is read via a normal method to suppress
  #       `private attribute?' warning.
  @interpreter
end