module AdLint::Cc1::ExpressionEvaluator

Public Instance Methods

visit_additive_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 253
def visit_additive_expression(node)
  checkpoint(node.location)
  eval_additive_expr(node, node.lhs_operand.accept(self),
                     node.rhs_operand.accept(self))
end
visit_address_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 159
def visit_address_expression(node)
  checkpoint(node.location)
  eval_address_expr(node, node.operand.accept(self))
end
visit_alignof_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 208
def visit_alignof_expression(node)
  checkpoint(node.location)

  ope_obj = rslt_var = nil
  eval_quietly_without_side_effects do
    rslt_type = type_of(UserTypeId.new("size_t")) || unsigned_long_t
    ope_obj = node.operand.accept(self)
    if ope_obj.variable?
      align = ope_obj.type.byte_alignment
      rslt_var = create_tmpvar(rslt_type, scalar_value_of(align))
    else
      rslt_var = create_tmpvar(rslt_type)
    end
  end

  notify_alignof_expr_evaled(node, ope_obj, rslt_var)
  rslt_var
end
visit_alignof_type_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 227
def visit_alignof_type_expression(node)
  checkpoint(node.location)
  resolve_unresolved_type(node.operand)

  rslt_var = nil
  eval_quietly_without_side_effects do
    rslt_type = type_of(UserTypeId.new("size_t")) || unsigned_long_t
    align = node.operand.type.aligned_byte_size
    rslt_var = create_tmpvar(rslt_type, scalar_value_of(align))
  end

  notify_alignof_type_expr_evaled(node, node.operand.type, rslt_var)
  rslt_var
end
visit_and_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 277
def visit_and_expression(node)
  checkpoint(node.location)
  eval_and_expr(node, node.lhs_operand.accept(self),
                node.rhs_operand.accept(self))
end
visit_array_subscript_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 102
def visit_array_subscript_expression(node)
  checkpoint(node.location)
  eval_array_subscript_expr(node, node.expression.accept(self),
                            node.array_subscript.accept(self))
end
visit_bit_access_by_pointer_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 129
def visit_bit_access_by_pointer_expression(node)
  checkpoint(node.location)
  eval_bit_access_by_pointer_expr(node, node.expression.accept(self))
end
visit_bit_access_by_value_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 124
def visit_bit_access_by_value_expression(node)
  checkpoint(node.location)
  eval_bit_access_by_value_expr(node, node.expression.accept(self))
end
visit_cast_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 242
def visit_cast_expression(node)
  checkpoint(node.location)
  eval_cast_expr(node, node.operand.accept(self))
end
visit_comma_separated_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 411
def visit_comma_separated_expression(node)
  checkpoint(node.location)
  node.expressions.map { |expr| expr.accept(self) }.last
end
visit_compound_assignment_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 405
def visit_compound_assignment_expression(node)
  checkpoint(node.location)
  eval_compound_assignment_expr(node, node.lhs_operand.accept(self),
                                node.rhs_operand.accept(self))
end
visit_compound_literal_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 144
def visit_compound_literal_expression(node)
  checkpoint(node.location)
  eval_compound_literal_expr(node)
end
visit_constant_specifier(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 58
def visit_constant_specifier(node)
  checkpoint(node.location)

  if const_var = eval_constant(node)
    notify_constant_referred(node, const_var)
    rslt_var = const_var
  else
    rslt_var = create_tmpvar
  end

  notify_constant_specifier_evaled(node, rslt_var)
  rslt_var
end
visit_equality_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 271
def visit_equality_expression(node)
  checkpoint(node.location)
  eval_equality_expr(node, node.lhs_operand.accept(self),
                     node.rhs_operand.accept(self))
end
visit_error_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 48
def visit_error_expression(node)
  checkpoint(node.location)
  create_tmpvar.tap { |rslt_var| notify_error_expr_evaled(node, rslt_var) }
end
visit_exclusive_or_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 283
def visit_exclusive_or_expression(node)
  checkpoint(node.location)
  eval_exclusive_or_expr(node, node.lhs_operand.accept(self),
                         node.rhs_operand.accept(self))
end
visit_function_call_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 108
def visit_function_call_expression(node)
  checkpoint(node.location)
  args = node.argument_expressions.map { |expr| [expr.accept(self), expr] }
  eval_function_call_expr(node, node.expression.accept(self), args)
end
visit_grouped_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 97
def visit_grouped_expression(node)
  checkpoint(node.location)
  node.expression.accept(self)
end
visit_inclusive_or_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 289
def visit_inclusive_or_expression(node)
  checkpoint(node.location)
  eval_inclusive_or_expr(node, node.lhs_operand.accept(self),
                         node.rhs_operand.accept(self))
end
visit_indirection_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 164
def visit_indirection_expression(node)
  checkpoint(node.location)
  eval_indirection_expr(node, node.operand.accept(self))
end
visit_logical_and_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 295
def visit_logical_and_expression(node)
  checkpoint(node.location)

  lhs_obj = node.lhs_operand.accept(self)
  if lhs_obj.variable?
    lhs_var = lhs_obj
  else
    return create_tmpvar(int_t)
  end

  # NOTE: The ISO C99 standard says;
  #
  # 6.5.13 Logical AND operator
  #
  # Semantics
  #
  # 4 Unlike the bitwise binary & operator, the && operator guarantees
  #   left-to-right evaluation; there is a sequence point after the
  #   evaluation of the first operand.  If the first operand compares equal
  #   to 0, the second operand is not evaluated.
  notify_sequence_point_reached(SequencePoint.new(node.lhs_operand))
  lhs_val = lhs_var.value

  if lhs_val.scalar? && lhs_val.test_must_be_false.true?
    # NOTE: Doing the short-circuit evaluation.
    notify_variable_value_referred(node, lhs_var)
    return create_tmpvar(int_t, scalar_value_of_false)
  end

  rhs_obj = node.rhs_operand.accept(self)
  if rhs_obj.variable?
    rhs_var = rhs_obj
  else
    return create_tmpvar(int_t)
  end

  notify_sequence_point_reached(SequencePoint.new(node.rhs_operand))
  rhs_val = rhs_var.value

  if lhs_val.scalar? && rhs_val.scalar?
    # NOTE: No usual-arithmetic-conversion.
    rslt_var = create_tmpvar(int_t, lhs_val.logical_and(rhs_val))
  else
    rslt_var = create_tmpvar(int_t)
  end
  notify_variable_value_referred(node, lhs_var)
  notify_variable_value_referred(node, rhs_var)

  notify_logical_and_expr_evaled(node, lhs_var, rhs_var, rslt_var)
  rslt_var
end
visit_logical_or_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 347
def visit_logical_or_expression(node)
  checkpoint(node.location)

  lhs_obj = node.lhs_operand.accept(self)
  if lhs_obj.variable?
    lhs_var = lhs_obj
  else
    return create_tmpvar(int_t)
  end

  # NOTE: The ISO C99 standard says;
  #
  # 6.5.14 Logical OR operator
  #
  # Semantics
  #
  # 4 Unlike the bitwise | operator, the || operator guarantees
  #   left-to-right evaluation; there is a sequence point after the
  #   evaluation of the first operand.  If the first operand compares
  #   unequal to 0, the second operand is not evaluated.
  notify_sequence_point_reached(SequencePoint.new(node.lhs_operand))
  lhs_val = lhs_var.value

  if lhs_val.scalar? && lhs_val.test_must_be_true.true?
    # NOTE: Doing the short-circuit evaluation.
    notify_variable_value_referred(node, lhs_var)
    return create_tmpvar(int_t, scalar_value_of_true)
  end

  rhs_obj = node.rhs_operand.accept(self)
  if rhs_obj.variable?
    rhs_var = rhs_obj
  else
    return create_tmpvar(int_t)
  end

  notify_sequence_point_reached(SequencePoint.new(node.rhs_operand))
  rhs_val = rhs_var.value

  if lhs_val.scalar? && rhs_val.scalar?
    # NOTE: No usual-arithmetic-conversion.
    rslt_var = create_tmpvar(int_t, lhs_val.logical_or(rhs_val))
  else
    rslt_var = create_tmpvar(int_t)
  end
  notify_variable_value_referred(node, lhs_var)
  notify_variable_value_referred(node, rhs_var)

  notify_logical_or_expr_evaled(node, lhs_var, rhs_var, rslt_var)
  rslt_var
end
visit_member_access_by_pointer_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 119
def visit_member_access_by_pointer_expression(node)
  checkpoint(node.location)
  eval_member_access_by_pointer_expr(node,node.expression.accept(self))
end
visit_member_access_by_value_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 114
def visit_member_access_by_value_expression(node)
  checkpoint(node.location)
  eval_member_access_by_value_expr(node, node.expression.accept(self))
end
visit_multiplicative_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 247
def visit_multiplicative_expression(node)
  checkpoint(node.location)
  eval_multiplicative_expr(node, node.lhs_operand.accept(self),
                           node.rhs_operand.accept(self))
end
visit_null_constant_specifier(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 90
def visit_null_constant_specifier(node)
  checkpoint(node.location)
  rslt_var = create_tmpvar(pointer_type(void_t), scalar_value_of_null)
  notify_null_constant_specifier_evaled(node, rslt_var)
  rslt_var
end
visit_object_specifier(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 53
def visit_object_specifier(node)
  checkpoint(node.location)
  eval_object_specifier(node)
end
visit_postfix_decrement_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 139
def visit_postfix_decrement_expression(node)
  checkpoint(node.location)
  eval_postfix_decrement_expr(node, node.operand.accept(self))
end
visit_postfix_increment_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 134
def visit_postfix_increment_expression(node)
  checkpoint(node.location)
  eval_postfix_increment_expr(node, node.operand.accept(self))
end
visit_prefix_decrement_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 154
def visit_prefix_decrement_expression(node)
  checkpoint(node.location)
  eval_prefix_decrement_expr(node, node.operand.accept(self))
end
visit_prefix_increment_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 149
def visit_prefix_increment_expression(node)
  checkpoint(node.location)
  eval_prefix_increment_expr(node, node.operand.accept(self))
end
visit_relational_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 265
def visit_relational_expression(node)
  checkpoint(node.location)
  eval_relational_expr(node, node.lhs_operand.accept(self),
                       node.rhs_operand.accept(self))
end
visit_shift_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 259
def visit_shift_expression(node)
  checkpoint(node.location)
  eval_shift_expr(node, node.lhs_operand.accept(self),
                  node.rhs_operand.accept(self))
end
visit_simple_assignment_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 399
def visit_simple_assignment_expression(node)
  checkpoint(node.location)
  eval_simple_assignment_expr(node, node.lhs_operand.accept(self),
                              node.rhs_operand.accept(self))
end
visit_sizeof_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 174
def visit_sizeof_expression(node)
  checkpoint(node.location)

  ope_obj = rslt_var = nil
  eval_quietly_without_side_effects do
    rslt_type = type_of(UserTypeId.new("size_t")) || unsigned_long_t
    ope_obj = node.operand.accept(self)
    if ope_obj.variable?
      size = ope_obj.type.aligned_byte_size
      rslt_var = create_tmpvar(rslt_type, scalar_value_of(size))
    else
      rslt_var = create_tmpvar(rslt_type)
    end
  end

  notify_sizeof_expr_evaled(node, ope_obj, rslt_var)
  rslt_var
end
visit_sizeof_type_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 193
def visit_sizeof_type_expression(node)
  checkpoint(node.location)
  resolve_unresolved_type(node.operand)

  rslt_var = nil
  eval_quietly_without_side_effects do
    rslt_type = type_of(UserTypeId.new("size_t")) || unsigned_long_t
    size = node.operand.type.aligned_byte_size
    rslt_var = create_tmpvar(rslt_type, scalar_value_of(size))
  end

  notify_sizeof_type_expr_evaled(node, node.operand.type, rslt_var)
  rslt_var
end
visit_string_literal_specifier(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 72
def visit_string_literal_specifier(node)
  checkpoint(node.location)

  case node.literal.value
  when /\A"(.*)"\z/
    rslt_var = create_tmpvar(array_type(char_t, $1.length + 1),
                             create_array_value_of_string($1))
  when /\AL"(.*)"\z/i
    rslt_var = create_tmpvar(array_type(wchar_t, $1.length + 1),
                             create_array_value_of_string($1))
  else
    rslt_var = create_tmpvar(array_type(char_t))
  end

  notify_string_literal_specifier_evaled(node, rslt_var)
  rslt_var
end
visit_unary_arithmetic_expression(node) click to toggle source
# File lib/adlint/cc1/expr.rb, line 169
def visit_unary_arithmetic_expression(node)
  checkpoint(node.location)
  eval_unary_arithmetic_expr(node, node.operand.accept(self))
end

Private Instance Methods

create_array_value_of_string(str) click to toggle source
# File lib/adlint/cc1/expr.rb, line 437
def create_array_value_of_string(str)
  ArrayValue.new(str.chars.map { |ch| scalar_value_of(ch.ord) } +
                 [scalar_value_of("\0".ord)])
end
eval_quietly_without_side_effects() { || ... } click to toggle source
# File lib/adlint/cc1/expr.rb, line 417
def eval_quietly_without_side_effects(&block)
  unless orig_quiet = interpreter.quiet?
    interpreter._quiet = true
  end
  unless orig_without_side_effects = interpreter.without_side_effects?
    interpreter._without_side_effects = true
  end
  yield
ensure
  unless orig_quiet
    interpreter._quiet = false
    # FIXME: Evaluation of an object-specifier doesn't refer to value
    #        of a variable.  Thus, no cross-reference record on a
    #        sizeof-expression because cross-reference extraction
    #        watches variable value reference not variable reference.
    # collect_object_specifiers(node).each { |os| os.accept(self) }
  end
  interpreter._without_side_effects = orig_without_side_effects
end