adlint 1.10.0 → 1.12.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.
Files changed (49) hide show
  1. data/ChangeLog +197 -4
  2. data/MANIFEST +17 -0
  3. data/NEWS +23 -4
  4. data/etc/mesg.d/en_US/messages.yml +14 -1
  5. data/etc/mesg.d/ja_JP/messages.yml +14 -1
  6. data/features/message_detection/W0093.feature +87 -0
  7. data/features/message_detection/W0687.feature +25 -0
  8. data/features/message_detection/W0688.feature +63 -0
  9. data/features/message_detection/W0689.feature +46 -0
  10. data/features/message_detection/W0690.feature +35 -0
  11. data/features/message_detection/W0698.feature +3 -2
  12. data/features/message_detection/W0703.feature +1 -0
  13. data/features/message_detection/W0723.feature +34 -0
  14. data/features/message_detection/W0732.feature +158 -0
  15. data/features/message_detection/W0733.feature +158 -0
  16. data/features/message_detection/W0734.feature +322 -0
  17. data/features/message_detection/W0735.feature +322 -0
  18. data/features/message_detection/W1052.feature +66 -0
  19. data/features/message_detection/W9001.feature +33 -0
  20. data/features/message_detection/W9003.feature +131 -0
  21. data/lib/adlint/c/ctrlexpr.rb +51 -50
  22. data/lib/adlint/c/domain.rb +237 -223
  23. data/lib/adlint/c/expr.rb +6 -8
  24. data/lib/adlint/c/interp.rb +8 -11
  25. data/lib/adlint/c/message.rb +20 -0
  26. data/lib/adlint/c/message_shima.rb +63 -0
  27. data/lib/adlint/c/object.rb +5 -4
  28. data/lib/adlint/c/operator.rb +99 -0
  29. data/lib/adlint/c/parser.rb +2 -2
  30. data/lib/adlint/c/parser.y +2 -2
  31. data/lib/adlint/c/phase.rb +6 -1
  32. data/lib/adlint/c/syntax.rb +442 -30
  33. data/lib/adlint/c/type.rb +449 -363
  34. data/lib/adlint/c/value.rb +96 -25
  35. data/lib/adlint/c.rb +1 -0
  36. data/lib/adlint/prelude.rb +16 -18
  37. data/lib/adlint/version.rb +2 -2
  38. data/share/doc/developers_guide_ja.html +11 -5
  39. data/share/doc/developers_guide_ja.texi +9 -3
  40. data/share/doc/users_guide_en.html +697 -131
  41. data/share/doc/users_guide_en.texi +491 -41
  42. data/share/doc/users_guide_ja.html +709 -139
  43. data/share/doc/users_guide_ja.texi +499 -45
  44. data/spec/adlint/c/ctrlexpr_spec.rb +168 -0
  45. data/spec/adlint/c/domain_spec.rb +835 -0
  46. data/spec/adlint/c/operator_spec.rb +406 -0
  47. data/spec/adlint/c/syntax_spec.rb +717 -0
  48. data/spec/adlint/c/type_spec.rb +55 -30
  49. metadata +19 -2
@@ -37,6 +37,7 @@ require "adlint/c/syntax"
37
37
  require "adlint/c/expr"
38
38
  require "adlint/c/conv"
39
39
  require "adlint/c/option"
40
+ require "adlint/c/operator"
40
41
  require "adlint/c/util"
41
42
 
42
43
  module AdLint #:nodoc:
@@ -55,18 +56,13 @@ module C #:nodoc:
55
56
  end
56
57
 
57
58
  class ExecutionDriver < SyntaxTreeVisitor
58
- include InterpreterMediator
59
-
60
59
  def initialize(interpreter)
61
60
  @interpreter = interpreter
62
61
  end
63
62
 
64
- def visit_declaration(node) interpret(node) end
65
- def visit_ansi_function_definition(node) interpret(node) end
66
- def visit_kandr_function_definition(node) interpret(node) end
67
-
68
- private
69
- def interpreter; @interpreter end
63
+ def visit_declaration(node) @interpreter.execute(node) end
64
+ def visit_ansi_function_definition(node) @interpreter.execute(node) end
65
+ def visit_kandr_function_definition(node) @interpreter.execute(node) end
70
66
  end
71
67
  private_constant :ExecutionDriver
72
68
  end
@@ -1216,16 +1212,17 @@ module C #:nodoc:
1216
1212
  iteration_statement.varying_variable_names.each do |name|
1217
1213
  if variable = variable_named(name)
1218
1214
  varying_vars[variable] = variable.value.dup
1219
- variable.widen_value_domain!(:==, variable.type.arbitrary_value)
1215
+ variable.widen_value_domain!(Operator::EQ,
1216
+ variable.type.arbitrary_value)
1220
1217
  end
1221
1218
  end
1222
1219
 
1223
1220
  varying_vars.each do |variable, orig_value|
1224
1221
  case deduct_variable_varying_path(variable, iteration_statement)
1225
1222
  when :increase
1226
- variable.narrow_value_domain!(:>=, orig_value)
1223
+ variable.narrow_value_domain!(Operator::GE, orig_value)
1227
1224
  when :decrease
1228
- variable.narrow_value_domain!(:<=, orig_value)
1225
+ variable.narrow_value_domain!(Operator::LE, orig_value)
1229
1226
  end
1230
1227
  end
1231
1228
  end
@@ -15024,5 +15024,25 @@ module C #:nodoc:
15024
15024
  end
15025
15025
  end
15026
15026
 
15027
+ class W9003 < PassiveMessageDetection
15028
+ def initialize(context)
15029
+ super
15030
+ interp = context[:c_interpreter]
15031
+ interp.on_implicit_conv_performed += method(:check)
15032
+ end
15033
+
15034
+ private
15035
+ def check(initializer_or_expression, original_variable, result_variable)
15036
+ from_type = original_variable.type
15037
+ to_type = result_variable.type
15038
+
15039
+ unless from_type.standard? && to_type.standard?
15040
+ unless from_type.convertible?(to_type)
15041
+ W(:W9003, initializer_or_expression.location, from_type.brief_image)
15042
+ end
15043
+ end
15044
+ end
15045
+ end
15046
+
15027
15047
  end
15028
15048
  end
@@ -308,6 +308,69 @@ module C #:nodoc:
308
308
  end
309
309
  end
310
310
 
311
+ class W0732 < PassiveMessageDetection
312
+ def initialize(context)
313
+ super
314
+ visitor = context[:c_visitor]
315
+ visitor.enter_logical_and_expression += method(:check)
316
+ end
317
+
318
+ private
319
+ def check(expr)
320
+ if expr.lhs_operand.arithmetic? || expr.lhs_operand.bitwise?
321
+ if expr.rhs_operand.arithmetic? || expr.rhs_operand.bitwise?
322
+ W(:W0732, expr.location)
323
+ end
324
+ end
325
+ end
326
+ end
327
+
328
+ class W0733 < PassiveMessageDetection
329
+ def initialize(context)
330
+ super
331
+ visitor = context[:c_visitor]
332
+ visitor.enter_logical_or_expression += method(:check)
333
+ end
334
+
335
+ private
336
+ def check(expr)
337
+ if expr.lhs_operand.arithmetic? || expr.lhs_operand.bitwise?
338
+ if expr.rhs_operand.arithmetic? || expr.rhs_operand.bitwise?
339
+ W(:W0733, expr.location)
340
+ end
341
+ end
342
+ end
343
+ end
344
+
345
+ class W0734 < PassiveMessageDetection
346
+ def initialize(context)
347
+ super
348
+ visitor = context[:c_visitor]
349
+ visitor.enter_logical_and_expression += method(:check)
350
+ visitor.enter_logical_or_expression += method(:check)
351
+ end
352
+
353
+ private
354
+ def check(expr)
355
+ if expr.lhs_operand.arithmetic? || expr.lhs_operand.bitwise?
356
+ unless expr.rhs_operand.arithmetic? || expr.rhs_operand.bitwise?
357
+ W(:W0734, expr.lhs_operand.location)
358
+ end
359
+ end
360
+ end
361
+ end
362
+
363
+ class W0735 < W0734
364
+ private
365
+ def check(expr)
366
+ if expr.rhs_operand.arithmetic? || expr.rhs_operand.bitwise?
367
+ unless expr.lhs_operand.arithmetic? || expr.lhs_operand.bitwise?
368
+ W(:W0735, expr.rhs_operand.location)
369
+ end
370
+ end
371
+ end
372
+ end
373
+
311
374
  class W0781 < PassiveMessageDetection
312
375
  def initialize(context)
313
376
  super
@@ -34,6 +34,7 @@ require "adlint/c/syntax"
34
34
  require "adlint/c/value"
35
35
  require "adlint/c/scope"
36
36
  require "adlint/c/seqp"
37
+ require "adlint/c/operator"
37
38
 
38
39
  module AdLint #:nodoc:
39
40
  module C #:nodoc:
@@ -209,23 +210,23 @@ module C #:nodoc:
209
210
  assign!(self.type.undefined_value)
210
211
  end
211
212
 
212
- def narrow_value_domain!(operator_symbol, value)
213
+ def narrow_value_domain!(operator, value)
213
214
  unless self_value = modifiable_value
214
215
  assign!(type.arbitrary_value)
215
216
  self_value = modifiable_value
216
217
  end
217
218
 
218
- self_value.narrow_domain!(operator_symbol, value.coerce_to(type))
219
+ self_value.narrow_domain!(operator, value.coerce_to(type))
219
220
  self_value.exist?
220
221
  end
221
222
 
222
- def widen_value_domain!(operator_symbol, value)
223
+ def widen_value_domain!(operator, value)
223
224
  unless self_value = modifiable_value
224
225
  assign!(type.nil_value)
225
226
  self_value = modifiable_value
226
227
  end
227
228
 
228
- self_value.widen_domain!(operator_symbol, value.coerce_to(type))
229
+ self_value.widen_domain!(operator, value.coerce_to(type))
229
230
  self_value.exist?
230
231
  end
231
232
 
@@ -0,0 +1,99 @@
1
+ # Comparison operator of controlling expressions.
2
+ #
3
+ # Author:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
4
+ # Copyright:: Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
5
+ # License:: GPLv3+: GNU General Public License version 3 or later
6
+ #
7
+ # Owner:: Yutaka Yanoh <mailto:yanoh@users.sourceforge.net>
8
+
9
+ #--
10
+ # ___ ____ __ ___ _________
11
+ # / | / _ |/ / / / | / /__ __/ Source Code Static Analyzer
12
+ # / /| | / / / / / / / |/ / / / AdLint - Advanced Lint
13
+ # / __ |/ /_/ / /___/ / /| / / /
14
+ # /_/ |_|_____/_____/_/_/ |_/ /_/ Copyright (C) 2010-2012, OGIS-RI Co.,Ltd.
15
+ #
16
+ # This file is part of AdLint.
17
+ #
18
+ # AdLint is free software: you can redistribute it and/or modify it under the
19
+ # terms of the GNU General Public License as published by the Free Software
20
+ # Foundation, either version 3 of the License, or (at your option) any later
21
+ # version.
22
+ #
23
+ # AdLint is distributed in the hope that it will be useful, but WITHOUT ANY
24
+ # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
25
+ # A PARTICULAR PURPOSE. See the GNU General Public License for more details.
26
+ #
27
+ # You should have received a copy of the GNU General Public License along with
28
+ # AdLint. If not, see <http://www.gnu.org/licenses/>.
29
+ #
30
+ #++
31
+
32
+ module AdLint #:nodoc:
33
+ module C #:nodoc:
34
+
35
+ class Operator
36
+ def initialize(token_or_symbol)
37
+ case token_or_symbol
38
+ when Token
39
+ @sym = token_or_symbol.type.to_sym
40
+ when ::Symbol
41
+ @sym = token_or_symbol
42
+ end
43
+ end
44
+
45
+ def to_sym
46
+ @sym
47
+ end
48
+
49
+ def eql?(rhs)
50
+ case rhs
51
+ when Operator
52
+ @sym == rhs.to_sym
53
+ else
54
+ super
55
+ end
56
+ end
57
+
58
+ alias :== :eql?
59
+
60
+ def hash
61
+ @sym.hash
62
+ end
63
+ end
64
+
65
+ class ComparisonOperator < Operator
66
+ def for_complement
67
+ case self
68
+ when Operator::EQ then Operator::NE
69
+ when Operator::NE then Operator::EQ
70
+ when Operator::LT then Operator::GE
71
+ when Operator::GT then Operator::LE
72
+ when Operator::LE then Operator::GT
73
+ when Operator::GE then Operator::LT
74
+ else self
75
+ end
76
+ end
77
+
78
+ def for_commutation
79
+ case self
80
+ when Operator::LT then Operator::GT
81
+ when Operator::GT then Operator::LT
82
+ when Operator::LE then Operator::GE
83
+ when Operator::GE then Operator::LE
84
+ else self
85
+ end
86
+ end
87
+ end
88
+
89
+ class Operator
90
+ EQ = ComparisonOperator.new(:==)
91
+ NE = ComparisonOperator.new(:!=)
92
+ LT = ComparisonOperator.new(:<)
93
+ GT = ComparisonOperator.new(:>)
94
+ LE = ComparisonOperator.new(:<=)
95
+ GE = ComparisonOperator.new(:>=)
96
+ end
97
+
98
+ end
99
+ end
@@ -1387,7 +1387,7 @@ module_eval(<<'.,.,', 'parser.y', 195)
1387
1387
  def _reduce_15(val, _values, result)
1388
1388
  checkpoint(val[0].location)
1389
1389
 
1390
- result = PostfixIncrementExpression.new(val[0], val[1])
1390
+ result = PostfixIncrementExpression.new(val[1], val[0])
1391
1391
  result.head_token = val[0].head_token
1392
1392
  result.tail_token = val[1]
1393
1393
 
@@ -1399,7 +1399,7 @@ module_eval(<<'.,.,', 'parser.y', 203)
1399
1399
  def _reduce_16(val, _values, result)
1400
1400
  checkpoint(val[0].location)
1401
1401
 
1402
- result = PostfixDecrementExpression.new(val[0], val[1])
1402
+ result = PostfixDecrementExpression.new(val[1], val[0])
1403
1403
  result.head_token = val[0].head_token
1404
1404
  result.tail_token = val[1]
1405
1405
 
@@ -195,7 +195,7 @@ postfix_expression
195
195
  {
196
196
  checkpoint(val[0].location)
197
197
 
198
- result = PostfixIncrementExpression.new(val[0], val[1])
198
+ result = PostfixIncrementExpression.new(val[1], val[0])
199
199
  result.head_token = val[0].head_token
200
200
  result.tail_token = val[1]
201
201
  }
@@ -203,7 +203,7 @@ postfix_expression
203
203
  {
204
204
  checkpoint(val[0].location)
205
205
 
206
- result = PostfixDecrementExpression.new(val[0], val[1])
206
+ result = PostfixDecrementExpression.new(val[1], val[0])
207
207
  result.head_token = val[0].head_token
208
208
  result.tail_token = val[1]
209
209
  }
@@ -654,6 +654,10 @@ module C #:nodoc:
654
654
  W0729.new(context),
655
655
  W0730.new(context),
656
656
  W0731.new(context),
657
+ W0732.new(context),
658
+ W0733.new(context),
659
+ W0734.new(context),
660
+ W0735.new(context),
657
661
  W0736.new(context),
658
662
  W0737.new(context),
659
663
  W0738.new(context),
@@ -741,7 +745,8 @@ module C #:nodoc:
741
745
  W1063.new(context),
742
746
  W1064.new(context),
743
747
  W1065.new(context),
744
- W9001.new(context)
748
+ W9001.new(context),
749
+ W9003.new(context)
745
750
  ]
746
751
  end
747
752
  end