class AdLint::Cc1::Function

DESCRIPTION

Function class hierarchy

Function
  <-- NamedFunction ------> Nameable <<module>>
        <-- ExplicitFunction
        <-- ImplicitFunction
        <-- BuiltinFunction
  <-- AnonymousFunction

Public Class Methods

new(dcl_or_def, type) click to toggle source
Calls superclass method AdLint::Cc1::TypedObject::new
# File lib/adlint/cc1/object.rb, line 900
def initialize(dcl_or_def, type)
  super(type, dcl_or_def)
end

Public Instance Methods

builtin?() click to toggle source
# File lib/adlint/cc1/object.rb, line 932
def builtin?
  subclass_responsibility
end
call(interp, funcall_expr, args) click to toggle source
# File lib/adlint/cc1/object.rb, line 936
def call(interp, funcall_expr, args)
  assign_arguments_to_parameters(interp, args)
  return_values_via_pointer_arguments(interp, funcall_expr, args)

  if type.return_type.function?
    interp.create_tmpvar
  else
    ret_type = type.return_type
    interp.create_tmpvar(ret_type, ret_type.return_value)
  end
end
explicit?() click to toggle source
# File lib/adlint/cc1/object.rb, line 924
def explicit?
  subclass_responsibility
end
function?() click to toggle source
# File lib/adlint/cc1/object.rb, line 920
def function?
  true
end
implicit?() click to toggle source
# File lib/adlint/cc1/object.rb, line 928
def implicit?
  !explicit?
end
name() click to toggle source
# File lib/adlint/cc1/object.rb, line 904
def name
  subclass_responsibility
end
named?() click to toggle source
# File lib/adlint/cc1/object.rb, line 908
def named?
  false
end
signature() click to toggle source
# File lib/adlint/cc1/object.rb, line 948
def signature
  subclass_responsibility
end
temporary?() click to toggle source
# File lib/adlint/cc1/object.rb, line 912
def temporary?
  false
end
variable?() click to toggle source
# File lib/adlint/cc1/object.rb, line 916
def variable?
  false
end

Private Instance Methods

assign_arguments_to_parameters(interp, args) click to toggle source
# File lib/adlint/cc1/object.rb, line 953
def assign_arguments_to_parameters(interp, args)
  args.zip(type.parameter_types).each do |(arg, expr), param_type|
    arg_var = interp.object_to_variable(arg, expr)

    if param_type
      case
      when arg_var.type.pointer? && param_type.array?
        conved = interp.pointee_of(arg_var)
      when !arg_var.type.same_as?(param_type)
        conved = interp.do_conversion(arg_var, param_type) ||
                 interp.create_tmpvar(param_type)
        interp.notify_implicit_conv_performed(expr, arg_var, conved)
      else
        conved = arg_var
      end
    else
      conved = interp.do_default_argument_promotion(arg_var)
      if arg_var != conved
        interp.notify_implicit_conv_performed(expr, arg_var, conved)
      end
    end

    # NOTE: Value of the argument is referred when the assignment to the
    #       parameter is performed.
    interp.notify_variable_value_referred(expr, arg_var)
  end
end
return_values_via_pointer_arguments(interp, funcall_expr, args) click to toggle source
# File lib/adlint/cc1/object.rb, line 981
def return_values_via_pointer_arguments(interp, funcall_expr, args)
  args.zip(type.parameter_types).each do |(arg, expr), param_type|
    next if param_type && param_type.void?
    next unless arg.variable? and arg.type.pointer? || arg.type.array?

    param_type = param_type.unqualify if param_type

    case
    when param_type.nil? && (arg.type.pointer? || arg.type.array?),
         param_type && param_type.pointer? && !param_type.base_type.const?,
         param_type && param_type.array? && !param_type.base_type.const?
    else
      next
    end

    case
    when arg.type.pointer?
      pointee = interp.pointee_of(arg)
      if pointee && pointee.designated_by_lvalue? && pointee.variable?
        sink = pointee
      else
        next
      end
    when arg.type.array?
      sink = arg
    end

    ret_val = sink.type.return_value
    sink.assign!(ret_val, funcall_expr, interp.current_branch)
    interp.notify_variable_value_updated(expr, sink)

    # NOTE: Returning a value via a pointer parameter can be considered as
    #       an evaluation of a statement-expression with a
    #       simple-assignment-expression.
    #       Control will reach to a sequence-point at the end of a full
    #       expression.
    interp.notify_sequence_point_reached(
      SequencePoint.new(funcall_expr, false))
  end
end