adlint 1.0.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|