adlint 1.0.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +3 -2
- data/ChangeLog +208 -63
- data/MANIFEST +4 -0
- data/NEWS +24 -5
- data/etc/conf.d/fallback/traits.erb +1 -1
- data/etc/conf.d/i686-cygwin/traits-gcc_4.3.4.erb +1 -1
- data/etc/conf.d/i686-devkit/traits-gcc_4.5.2.erb +1 -1
- data/etc/conf.d/i686-linux/traits-gcc_4.5.1.erb +1 -1
- data/etc/conf.d/i686-mingw/traits-gcc_4.6.1.erb +1 -1
- data/etc/mesg.d/en_US/messages.yml +3 -3
- data/etc/mesg.d/ja_JP/messages.yml +4 -4
- data/lib/adlint/c/builtin.rb +3 -3
- data/lib/adlint/c/ctrlexpr.rb +7 -11
- data/lib/adlint/c/expr.rb +548 -363
- data/lib/adlint/c/interp.rb +233 -525
- data/lib/adlint/c/mediator.rb +1 -0
- data/lib/adlint/c/message.rb +144 -1
- data/lib/adlint/c/object.rb +15 -6
- data/lib/adlint/c/parser.rb +170 -128
- data/lib/adlint/c/parser.y +36 -0
- data/lib/adlint/c/phase.rb +4 -0
- data/lib/adlint/c/seqp.rb +72 -0
- data/lib/adlint/c/syntax.rb +254 -3
- data/lib/adlint/c.rb +1 -0
- data/lib/adlint/cpp/code.rb +2 -2
- data/lib/adlint/cpp/eval.rb +29 -13
- data/lib/adlint/cpp/message.rb +71 -70
- data/lib/adlint/cpp/message_shima.rb +100 -0
- data/lib/adlint/cpp/phase.rb +4 -0
- data/lib/adlint/cpp/syntax.rb +5 -1
- data/lib/adlint/cpp.rb +1 -0
- data/lib/adlint/message.rb +6 -3
- data/lib/adlint/traits.rb +1 -1
- data/lib/adlint/version.rb +5 -5
- data/share/demo/Makefile +3 -1
- data/share/demo/bad_line/bad_line.c +27 -0
- data/share/demo/sequence_point/sequence_point.c +31 -0
- data/share/doc/adlint_on_vim_en.png +0 -0
- data/share/doc/adlint_on_vim_ja.png +0 -0
- data/share/doc/developers_guide_ja.html +3 -3
- data/share/doc/developers_guide_ja.texi +1 -1
- data/share/doc/users_guide_en.html +3118 -41
- data/share/doc/users_guide_en.texi +3090 -37
- data/share/doc/users_guide_ja.html +3120 -47
- data/share/doc/users_guide_ja.texi +3106 -65
- data/share/sample/ctags-5.8/adlint/GNUmakefile +13 -1
- data/share/sample/ctags-5.8/adlint/adlint_cinit.h +14 -2
- data/share/sample/ctags-5.8/adlint/adlint_pinit.h +14 -4
- data/share/sample/ctags-5.8/adlint/adlint_traits.yml +14 -1
- data/share/sample/flex-2.5.35/adlint/GNUmakefile +13 -1
- data/share/sample/flex-2.5.35/adlint/adlint_cinit.h +14 -2
- data/share/sample/flex-2.5.35/adlint/adlint_pinit.h +14 -4
- data/share/sample/flex-2.5.35/adlint/adlint_traits.yml +14 -1
- metadata +6 -2
data/lib/adlint/c/mediator.rb
CHANGED
@@ -240,6 +240,7 @@ module C #:nodoc:
|
|
240
240
|
def_delegator :interpreter, :notify_branch_ended
|
241
241
|
def_delegator :interpreter, :notify_translation_unit_started
|
242
242
|
def_delegator :interpreter, :notify_translation_unit_ended
|
243
|
+
def_delegator :interpreter, :notify_sequence_point_reached
|
243
244
|
|
244
245
|
private
|
245
246
|
def interpreter
|
data/lib/adlint/c/message.rb
CHANGED
@@ -6998,7 +6998,6 @@ module C #:nodoc:
|
|
6998
6998
|
private
|
6999
6999
|
def check(expression, variable)
|
7000
7000
|
return if variable.scope.global? || variable.binding.memory.static?
|
7001
|
-
return if variable.temporary?
|
7002
7001
|
|
7003
7002
|
if variable.named? && variable.value.must_be_undefined?
|
7004
7003
|
W(:W0459, expression.location, variable.name)
|
@@ -10544,6 +10543,150 @@ module C #:nodoc:
|
|
10544
10543
|
end
|
10545
10544
|
end
|
10546
10545
|
|
10546
|
+
class W0597 < PassiveMessageDetection
|
10547
|
+
def initialize(context)
|
10548
|
+
super
|
10549
|
+
interp = context[:c_interpreter]
|
10550
|
+
interp.on_sequence_point_reached += method(:commit_changes)
|
10551
|
+
interp.on_variable_value_updated += method(:update_variable)
|
10552
|
+
@update_count = Hash.new(0)
|
10553
|
+
end
|
10554
|
+
|
10555
|
+
private
|
10556
|
+
def commit_changes(sequence_point)
|
10557
|
+
@update_count.each do |var, count|
|
10558
|
+
W(:W0597, sequence_point.last_node.location, var.name) if count > 1
|
10559
|
+
end
|
10560
|
+
@update_count = Hash.new(0)
|
10561
|
+
end
|
10562
|
+
|
10563
|
+
def update_variable(expression, variable)
|
10564
|
+
@update_count[variable] += 1 if variable.named?
|
10565
|
+
end
|
10566
|
+
end
|
10567
|
+
|
10568
|
+
class W0598 < PassiveMessageDetection
|
10569
|
+
def initialize(context)
|
10570
|
+
super
|
10571
|
+
interp = context[:c_interpreter]
|
10572
|
+
interp.on_sequence_point_reached += method(:commit_changes)
|
10573
|
+
interp.on_variable_value_updated += method(:update_variable)
|
10574
|
+
@update_count = [Hash.new(0)]
|
10575
|
+
end
|
10576
|
+
|
10577
|
+
private
|
10578
|
+
def commit_changes(sequence_point)
|
10579
|
+
if sequence_point.obvious?
|
10580
|
+
updated_vars = @update_count.map { |hash| hash.keys }.flatten.uniq
|
10581
|
+
updated_vars.each do |var|
|
10582
|
+
if @update_count.count { |hash| hash.include?(var) } > 1
|
10583
|
+
if @update_count.map { |hash| hash[var] }.max == 1
|
10584
|
+
W(:W0598, sequence_point.last_node.location, var.name)
|
10585
|
+
end
|
10586
|
+
end
|
10587
|
+
end
|
10588
|
+
@update_count = [Hash.new(0)]
|
10589
|
+
else
|
10590
|
+
@update_count.push(Hash.new(0))
|
10591
|
+
end
|
10592
|
+
end
|
10593
|
+
|
10594
|
+
def update_variable(expression, variable)
|
10595
|
+
@update_count.last[variable] += 1 if variable.named?
|
10596
|
+
end
|
10597
|
+
end
|
10598
|
+
|
10599
|
+
class W0599 < PassiveMessageDetection
|
10600
|
+
def initialize(context)
|
10601
|
+
super
|
10602
|
+
interp = context[:c_interpreter]
|
10603
|
+
interp.on_sequence_point_reached += method(:commit_changes)
|
10604
|
+
interp.on_variable_value_referred += method(:refer_variable)
|
10605
|
+
interp.on_variable_value_updated += method(:update_variable)
|
10606
|
+
@refer_count = Hash.new(0)
|
10607
|
+
@update_count = Hash.new(0)
|
10608
|
+
end
|
10609
|
+
|
10610
|
+
private
|
10611
|
+
def commit_changes(sequence_point)
|
10612
|
+
(@refer_count.keys & @update_count.keys).each do |var|
|
10613
|
+
if @refer_count[var] > 0 && @update_count[var] > 0
|
10614
|
+
W(:W0599, sequence_point.last_node.location, var.name)
|
10615
|
+
end
|
10616
|
+
end
|
10617
|
+
@refer_count = Hash.new(0)
|
10618
|
+
@update_count = Hash.new(0)
|
10619
|
+
end
|
10620
|
+
|
10621
|
+
def refer_variable(expression, variable)
|
10622
|
+
@refer_count[variable] += 1 if variable.named?
|
10623
|
+
end
|
10624
|
+
|
10625
|
+
def update_variable(expression, variable)
|
10626
|
+
if variable.named?
|
10627
|
+
case expression
|
10628
|
+
when SimpleAssignmentExpression, CompoundAssignmentExpression
|
10629
|
+
# NOTE: The expression-statement `i = i + j;' should not be warned.
|
10630
|
+
# But the expression-statement `i = i++ + j;' should be warned.
|
10631
|
+
# So, side-effects of the assignment-expression are given
|
10632
|
+
# special treatment.
|
10633
|
+
else
|
10634
|
+
@update_count[variable] += 1
|
10635
|
+
end
|
10636
|
+
end
|
10637
|
+
end
|
10638
|
+
end
|
10639
|
+
|
10640
|
+
class W0600 < PassiveMessageDetection
|
10641
|
+
def initialize(context)
|
10642
|
+
super
|
10643
|
+
interp = context[:c_interpreter]
|
10644
|
+
interp.on_sequence_point_reached += method(:commit_changes)
|
10645
|
+
interp.on_variable_value_referred += method(:refer_variable)
|
10646
|
+
interp.on_variable_value_updated += method(:update_variable)
|
10647
|
+
@refer_count = [Hash.new(0)]
|
10648
|
+
@update_count = [Hash.new(0)]
|
10649
|
+
end
|
10650
|
+
|
10651
|
+
private
|
10652
|
+
def commit_changes(sequence_point)
|
10653
|
+
if sequence_point.obvious?
|
10654
|
+
updated_vars = @update_count.map { |hash| hash.keys }.flatten.uniq
|
10655
|
+
access_count = @refer_count.zip(@update_count)
|
10656
|
+
|
10657
|
+
updated_vars.each do |var|
|
10658
|
+
count = access_count.count { |rhash, uhash|
|
10659
|
+
rhash.include?(var) && !uhash.include?(var)
|
10660
|
+
}
|
10661
|
+
W(:W0600, sequence_point.last_node.location, var.name) if count > 0
|
10662
|
+
end
|
10663
|
+
@refer_count = [Hash.new(0)]
|
10664
|
+
@update_count = [Hash.new(0)]
|
10665
|
+
else
|
10666
|
+
@refer_count.push(Hash.new(0))
|
10667
|
+
@update_count.push(Hash.new(0))
|
10668
|
+
end
|
10669
|
+
end
|
10670
|
+
|
10671
|
+
def refer_variable(expression, variable)
|
10672
|
+
@refer_count.last[variable] += 1 if variable.named?
|
10673
|
+
end
|
10674
|
+
|
10675
|
+
def update_variable(expression, variable)
|
10676
|
+
if variable.named?
|
10677
|
+
case expression
|
10678
|
+
when SimpleAssignmentExpression, CompoundAssignmentExpression
|
10679
|
+
# NOTE: The expression-statement `i = i + j;' should not be warned.
|
10680
|
+
# But the expression-statement `i = i++ + j;' should be warned.
|
10681
|
+
# So, side-effects of the assignment-expression are given
|
10682
|
+
# special treatment.
|
10683
|
+
else
|
10684
|
+
@update_count.last[variable] += 1
|
10685
|
+
end
|
10686
|
+
end
|
10687
|
+
end
|
10688
|
+
end
|
10689
|
+
|
10547
10690
|
class W0605 < PassiveMessageDetection
|
10548
10691
|
def initialize(context)
|
10549
10692
|
super
|
data/lib/adlint/c/object.rb
CHANGED
@@ -32,6 +32,7 @@
|
|
32
32
|
require "adlint/util"
|
33
33
|
require "adlint/c/value"
|
34
34
|
require "adlint/c/scope"
|
35
|
+
require "adlint/c/seqp"
|
35
36
|
|
36
37
|
module AdLint #:nodoc:
|
37
38
|
module C #:nodoc:
|
@@ -221,7 +222,7 @@ module C #:nodoc:
|
|
221
222
|
|
222
223
|
def inner_variable_at(index)
|
223
224
|
if @type.array?
|
224
|
-
# TODO: If linear
|
225
|
+
# TODO: If linear searching is too slow, use an index of inner
|
225
226
|
# variables.
|
226
227
|
target_name = ArrayElementVariable.component_name_of(index)
|
227
228
|
@inner_variables.find { |iv| iv.component_name == target_name }
|
@@ -232,7 +233,7 @@ module C #:nodoc:
|
|
232
233
|
|
233
234
|
def inner_variable_named(name)
|
234
235
|
if @type.composite?
|
235
|
-
# TODO: If linear
|
236
|
+
# TODO: If linear searching is too slow, use an index of inner
|
236
237
|
# variables.
|
237
238
|
target_name = CompositeMemberVariable.component_name_of(name)
|
238
239
|
@inner_variables.find { |iv| iv.component_name == target_name }
|
@@ -624,9 +625,9 @@ module C #:nodoc:
|
|
624
625
|
subclass_responsibility
|
625
626
|
end
|
626
627
|
|
627
|
-
def call(interpreter, args)
|
628
|
+
def call(interpreter, funcall_expr, args)
|
628
629
|
assign_arguments_to_parameters(interpreter, args)
|
629
|
-
return_values_via_pointer_arguments(interpreter, args)
|
630
|
+
return_values_via_pointer_arguments(interpreter, funcall_expr, args)
|
630
631
|
|
631
632
|
if type.return_type.function?
|
632
633
|
interpreter.temporary_variable
|
@@ -673,7 +674,7 @@ module C #:nodoc:
|
|
673
674
|
end
|
674
675
|
end
|
675
676
|
|
676
|
-
def return_values_via_pointer_arguments(interpreter, args)
|
677
|
+
def return_values_via_pointer_arguments(interpreter, funcall_expr, args)
|
677
678
|
args.zip(type.parameter_types).each do |(arg, expr), param_type|
|
678
679
|
next if param_type && param_type.void?
|
679
680
|
next unless arg.variable? && arg.value.scalar?
|
@@ -686,6 +687,14 @@ module C #:nodoc:
|
|
686
687
|
pointee.designated_by_lvalue? && pointee.variable?
|
687
688
|
pointee.assign!(pointee.type.return_value)
|
688
689
|
interpreter.notify_variable_value_updated(expr, pointee)
|
690
|
+
|
691
|
+
# NOTE: Returning a value via a pointer parameter can be considered
|
692
|
+
# as an evaluation of a statement-expression with a
|
693
|
+
# simple-assignment-expression.
|
694
|
+
# Control will reach to a sequence-point at the end of a full
|
695
|
+
# expression.
|
696
|
+
interpreter.notify_sequence_point_reached(
|
697
|
+
SequencePoint.new(funcall_expr, false))
|
689
698
|
end
|
690
699
|
end
|
691
700
|
end
|
@@ -705,7 +714,7 @@ module C #:nodoc:
|
|
705
714
|
true
|
706
715
|
end
|
707
716
|
|
708
|
-
def call(interpreter, args)
|
717
|
+
def call(interpreter, funcall_expr, args)
|
709
718
|
case name
|
710
719
|
when "exit", "_exit", "abort"
|
711
720
|
BreakEvent.of_return.throw
|