class AdLint::Exam::CBuiltin::W0100

Public Class Methods

new(phase_ctxt) click to toggle source
Calls superclass method AdLint::Examination::new
# File lib/adlint/exam/c_builtin/cc1_check.rb, line 2189
def initialize(phase_ctxt)
  super
  interp = phase_ctxt[:cc1_interpreter]
  interp.on_variable_defined       += T(:define_variable)
  interp.on_variable_initialized   += T(:init_variable)
  interp.on_variable_value_updated += T(:write_variable)
  interp.on_block_started          += T(:enter_block)
  interp.on_block_ended            += T(:leave_block)
  interp.on_while_stmt_started     += T(:enter_iteration)
  interp.on_while_stmt_ended       += T(:leave_iteration)
  interp.on_do_stmt_started        += T(:enter_iteration)
  interp.on_do_stmt_ended          += T(:leave_iteration)
  interp.on_for_stmt_started       += T(:enter_iteration)
  interp.on_for_stmt_ended         += T(:leave_iteration)
  interp.on_c99_for_stmt_started   += T(:enter_iteration)
  interp.on_c99_for_stmt_ended     += T(:leave_iteration)
  @var_stack = [{}]
  @iter_stmt_stack = []
end

Private Instance Methods

check_constant_variables(vars) click to toggle source
# File lib/adlint/exam/c_builtin/cc1_check.rb, line 2257
def check_constant_variables(vars)
  vars.each do |var, (loc, assign_cnt)|
    case
    when var.type.pointer? && var.type.unqualify.base_type.function?
      next
    when var.type.array?
      if assign_cnt <= 1
        base_type = var.type.base_type
        while base_type.array? || base_type.pointer?
          base_type = base_type.base_type
        end
        W(loc, var.name) unless base_type.const?
      end
    when !var.type.const?
      W(loc, var.name) if assign_cnt <= 1
    end
  end
end
define_variable(var_def, var) click to toggle source
# File lib/adlint/exam/c_builtin/cc1_check.rb, line 2219
def define_variable(var_def, var)
  if var.named?
    @var_stack.last[var] = [var_def.location, 0]
  end
end
enter_block(*) click to toggle source
# File lib/adlint/exam/c_builtin/cc1_check.rb, line 2210
def enter_block(*)
  @var_stack.push({})
end
enter_iteration(iter_stmt) click to toggle source
# File lib/adlint/exam/c_builtin/cc1_check.rb, line 2249
def enter_iteration(iter_stmt)
  @iter_stmt_stack.push(iter_stmt)
end
init_variable(var_def, var, *) click to toggle source
# File lib/adlint/exam/c_builtin/cc1_check.rb, line 2225
def init_variable(var_def, var, *)
  if rec = @var_stack.last[var]
    rec[1] += 1
  end
end
leave_block(*) click to toggle source
# File lib/adlint/exam/c_builtin/cc1_check.rb, line 2214
def leave_block(*)
  check_constant_variables(@var_stack.last)
  @var_stack.pop
end
leave_iteration(*) click to toggle source
# File lib/adlint/exam/c_builtin/cc1_check.rb, line 2253
def leave_iteration(*)
  @iter_stmt_stack.pop
end
write_variable(*, var) click to toggle source
# File lib/adlint/exam/c_builtin/cc1_check.rb, line 2231
def write_variable(*, var)
  var = var.owner while var.inner?
  return unless var.named?

  @var_stack.reverse_each do |vars|
    if rec = vars[var]
      if @iter_stmt_stack.empty?
        rec[1] += 1
      else
        # NOTE: Update twice in order not to over-warn about this variable,
        #       because an iteration is treated as a normal selection by
        #       the abstract interpreter.
        rec[1] += 2
      end
    end
  end
end