adlint 1.8.10 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/ChangeLog +261 -3
  2. data/MANIFEST +25 -1
  3. data/NEWS +25 -5
  4. data/Rakefile +11 -0
  5. data/TODO +0 -1
  6. data/etc/mesg.d/en_US/messages.yml +1 -1
  7. data/etc/mesg.d/ja_JP/messages.yml +1 -1
  8. data/features/message_detection/W0001.feature +41 -0
  9. data/features/message_detection/W0002.feature +68 -0
  10. data/features/message_detection/W0003.feature +134 -0
  11. data/features/message_detection/W0007.feature +264 -0
  12. data/features/message_detection/W0010.feature +75 -0
  13. data/features/message_detection/W0013.feature +189 -0
  14. data/features/message_detection/W0109.feature +50 -0
  15. data/features/message_detection/W0583.feature +30 -0
  16. data/features/message_detection/W0606.feature +20 -0
  17. data/features/message_detection/W0698.feature +20 -0
  18. data/features/message_detection/W0699.feature +21 -0
  19. data/features/message_detection/W0703.feature +73 -0
  20. data/features/message_detection/W0716.feature +67 -0
  21. data/features/message_detection/W0717.feature +64 -0
  22. data/features/message_detection/W0718.feature +64 -0
  23. data/features/message_detection/W0723.feature +18 -0
  24. data/features/message_detection/W1031.feature +328 -0
  25. data/features/step_definitions/message_detection_steps.rb +45 -0
  26. data/features/support/env.rb +58 -0
  27. data/lib/adlint/c/branch.rb +16 -23
  28. data/lib/adlint/c/code.rb +1 -12
  29. data/lib/adlint/c/conv.rb +4 -4
  30. data/lib/adlint/c/ctrlexpr.rb +10 -6
  31. data/lib/adlint/c/domain.rb +2 -2
  32. data/lib/adlint/c/expr.rb +11 -33
  33. data/lib/adlint/c/format.rb +6 -6
  34. data/lib/adlint/c/interp.rb +137 -80
  35. data/lib/adlint/c/mediator.rb +5 -2
  36. data/lib/adlint/c/message.rb +123 -140
  37. data/lib/adlint/c/message_shima.rb +44 -0
  38. data/lib/adlint/c/object.rb +93 -26
  39. data/lib/adlint/c/option.rb +53 -0
  40. data/lib/adlint/c/phase.rb +4 -1
  41. data/lib/adlint/c/type.rb +112 -46
  42. data/lib/adlint/c.rb +1 -0
  43. data/lib/adlint/version.rb +3 -3
  44. data/share/doc/developers_guide_ja.html +3 -3
  45. data/share/doc/developers_guide_ja.texi +1 -1
  46. data/share/doc/users_guide_en.html +35 -28
  47. data/share/doc/users_guide_en.texi +30 -22
  48. data/share/doc/users_guide_ja.html +35 -31
  49. data/share/doc/users_guide_ja.texi +30 -24
  50. data/spec/adlint/c/type_spec.rb +110 -0
  51. data/spec/conf.d/default_traits.yml +216 -0
  52. data/spec/conf.d/empty_cinit.h +11 -0
  53. data/spec/conf.d/empty_pinit.h +11 -0
  54. data/spec/spec_helper.rb +49 -0
  55. metadata +27 -3
  56. data/spec/MUST_WRITE_SPECS_WITH_RSPEC +0 -0
@@ -36,14 +36,45 @@ require "adlint/c/mediator"
36
36
  require "adlint/c/syntax"
37
37
  require "adlint/c/expr"
38
38
  require "adlint/c/conv"
39
+ require "adlint/c/option"
39
40
  require "adlint/c/util"
40
41
 
41
42
  module AdLint #:nodoc:
42
43
  module C #:nodoc:
43
44
 
45
+ class Program
46
+ def initialize(interpreter, translation_unit)
47
+ @interpreter = interpreter
48
+ @translation_unit = translation_unit
49
+ end
50
+
51
+ def execute
52
+ @interpreter.notify_translation_unit_started(@translation_unit)
53
+ @translation_unit.accept(ExecutionDriver.new(@interpreter))
54
+ @interpreter.notify_translation_unit_ended(@translation_unit)
55
+ end
56
+
57
+ class ExecutionDriver < SyntaxTreeVisitor
58
+ include InterpreterMediator
59
+
60
+ def initialize(interpreter)
61
+ @interpreter = interpreter
62
+ end
63
+
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
70
+ end
71
+ private_constant :ExecutionDriver
72
+ end
73
+
44
74
  class Interpreter
45
75
  include InterpreterMediator
46
76
  include Conversion
77
+ include InterpreterOptions
47
78
 
48
79
  def initialize(type_table)
49
80
  type_table = type_table
@@ -51,7 +82,6 @@ module C #:nodoc:
51
82
  @type_resolver = DynamicTypeResolver.new(type_table, self)
52
83
 
53
84
  @sub_interpreters = [
54
- TranslationUnitInterpreter.new(self),
55
85
  DeclarationInterpreter.new(self),
56
86
  ParameterDefinitionInterpreter.new(self),
57
87
  FunctionInterpreter.new(self),
@@ -60,7 +90,7 @@ module C #:nodoc:
60
90
  ExpressionInterpreter.new(self)
61
91
  ]
62
92
 
63
- @suppress_notification = false
93
+ @options_stack = []
64
94
 
65
95
  # NOTE: Active (executing) function may be nested if the nested
66
96
  # function-definition of the GCC extension is used.
@@ -76,7 +106,7 @@ module C #:nodoc:
76
106
  class_eval <<-EOS
77
107
  def_plugin :on_#{event_name}
78
108
  def notify_#{event_name}(#{arg_names.join(",")})
79
- unless @suppress_notification
109
+ unless quiet?
80
110
  on_#{event_name}.invoke(#{arg_names.join(",")})
81
111
  end
82
112
  end
@@ -84,21 +114,24 @@ module C #:nodoc:
84
114
  end
85
115
  private_class_method :def_plugin_and_notifier
86
116
 
117
+ # NOTE: Notified when the interpreter evaluates a variable-declaration.
118
+ def_plugin_and_notifier :variable_declared,
119
+ :variable_declaration, :variable
120
+
121
+ # NOTE: Notified when the interpreter evaluates a variable-definition.
122
+ def_plugin_and_notifier :variable_defined, :variable_definition, :variable
123
+
87
124
  # NOTE: Notified when the interpreter evaluates an initializer of
88
125
  # variable-definition.
89
126
  def_plugin_and_notifier :variable_initialized,
90
127
  :variable_definition, :variable, :init_variable
91
128
 
92
- # NOTE: Notified when the interpreter evaluates a variable-definition.
93
- def_plugin_and_notifier :variable_defined, :variable_definition, :variable
94
-
95
129
  # NOTE: Notified when the interpreter evaluates a function-declaration.
96
130
  def_plugin_and_notifier :function_declared,
97
131
  :function_declaration, :function
98
132
 
99
- # NOTE: Notified when the interpreter evaluates a variable-declaration.
100
- def_plugin_and_notifier :variable_declared,
101
- :variable_declaration, :variable
133
+ # NOTE: Notified when the interpreter evaluates a function-definition.
134
+ def_plugin_and_notifier :function_defined, :function_definition, :function
102
135
 
103
136
  # NOTE: Notified when the interpreter evaluates a struct-type-declaration.
104
137
  def_plugin_and_notifier :struct_declared, :struct_type_declaration
@@ -235,7 +268,7 @@ module C #:nodoc:
235
268
 
236
269
  # NOTE: Notified when the interpreter evaluates a conditional-expression.
237
270
  def_plugin_and_notifier :conditional_expr_evaled,
238
- :conditional_expression, :condition_variable,
271
+ :conditional_expression, :controlling_variable,
239
272
  :result_variable
240
273
 
241
274
  # NOTE: Notified when the interpreter evaluates an address-expression.
@@ -393,16 +426,10 @@ module C #:nodoc:
393
426
  def_plugin_and_notifier :sequence_point_reached, :sequence_point
394
427
 
395
428
  def execute(node, *options)
396
- if options.include?(:suppress_notification)
397
- @suppress_notification = true
398
- end
399
-
429
+ @options_stack.push(current_options + options)
400
430
  node.accept(interpreter_for(node))
401
-
402
431
  ensure
403
- if options.include?(:suppress_notification)
404
- @suppress_notification = false
405
- end
432
+ @options_stack.pop
406
433
  end
407
434
 
408
435
  def object_to_variable(object)
@@ -429,9 +456,17 @@ module C #:nodoc:
429
456
  ScalarValue.of(object.binding.memory.address)
430
457
  end
431
458
 
432
- def _suppress_notification=(suppress_notification)
459
+ def quiet?
460
+ current_options.include?(QUIET)
461
+ end
462
+
463
+ def _quiet=(quiet)
433
464
  # NOTE: This method is called only from ControllingExpression.
434
- @suppress_notification = suppress_notification
465
+ if quiet
466
+ current_options.add(QUIET)
467
+ else
468
+ current_options.delete(QUIET)
469
+ end
435
470
  end
436
471
 
437
472
  def _active_function
@@ -459,6 +494,10 @@ module C #:nodoc:
459
494
  end
460
495
  end
461
496
 
497
+ def current_options
498
+ @options_stack.last || Set.new
499
+ end
500
+
462
501
  def interpreter
463
502
  # NOTE: This method is of the requirement for including
464
503
  # InterpreterMediator.
@@ -471,6 +510,7 @@ module C #:nodoc:
471
510
  include NotifierMediator
472
511
  include Conversion
473
512
  include MonitorUtil
513
+ include InterpreterOptions
474
514
 
475
515
  def initialize(owner, target_node_class)
476
516
  @owner = owner
@@ -485,38 +525,6 @@ module C #:nodoc:
485
525
  end
486
526
  end
487
527
 
488
- class TranslationUnitInterpreter < SubInterpreter
489
- def initialize(owner)
490
- super(owner, TranslationUnit)
491
- end
492
-
493
- def visit_declaration(node)
494
- checkpoint(node.location)
495
-
496
- interpret(node)
497
- end
498
-
499
- def visit_translation_unit(node)
500
- checkpoint(node.location)
501
-
502
- notify_translation_unit_started(node)
503
- super
504
- notify_translation_unit_ended(node)
505
- end
506
-
507
- def visit_ansi_function_definition(node)
508
- checkpoint(node.location)
509
-
510
- interpret(node)
511
- end
512
-
513
- def visit_kandr_function_definition(node)
514
- checkpoint(node.location)
515
-
516
- interpret(node)
517
- end
518
- end
519
-
520
528
  class DeclarationInterpreter < SubInterpreter
521
529
  def initialize(owner)
522
530
  super(owner, Declaration)
@@ -531,7 +539,8 @@ module C #:nodoc:
531
539
  decl.mark_as_referred_by(node.identifier)
532
540
  end
533
541
 
534
- function = define_explicit_function(node)
542
+ function = declare_function(node)
543
+
535
544
  notify_function_declared(node, function)
536
545
 
537
546
  evaluate_sequence_point(node.init_declarator.declarator)
@@ -562,12 +571,12 @@ module C #:nodoc:
562
571
  end
563
572
 
564
573
  if initializer = node.initializer
565
- init_variable, converted = evaluate_initializer(initializer, node.type)
574
+ init_var, converted = evaluate_initializer(initializer, node.type)
566
575
  variable = define_variable(node, converted.value.to_defined_value)
567
576
 
568
- notify_variable_value_referred(node, init_variable)
577
+ notify_variable_value_referred(node, init_var)
569
578
  notify_variable_defined(node, variable)
570
- notify_variable_initialized(node, variable, init_variable)
579
+ notify_variable_initialized(node, variable, init_var)
571
580
  else
572
581
  notify_variable_defined(node, define_variable(node))
573
582
  end
@@ -809,8 +818,6 @@ module C #:nodoc:
809
818
  def interpret_function(node)
810
819
  checkpoint(node.location)
811
820
 
812
- interpreter._enter_function(node)
813
-
814
821
  reset_environment
815
822
  resolve_unresolved_type(node)
816
823
 
@@ -823,27 +830,32 @@ module C #:nodoc:
823
830
  function = define_explicit_function(node)
824
831
  end
825
832
 
826
- scoped_eval do
827
- notify_function_started(node, function)
828
- notify_block_started(node.function_body)
833
+ notify_function_defined(node, function)
829
834
 
830
- node.parameter_definitions.each { |pdef| interpret(pdef) }
835
+ begin
836
+ interpreter._enter_function(node)
837
+ scoped_eval do
838
+ notify_function_started(node, function)
839
+ notify_block_started(node.function_body)
831
840
 
832
- BreakEvent.catch do
833
- node.function_body.block_items.each { |item| interpret(item) }
834
- end
841
+ node.parameter_definitions.each { |pdef| interpret(pdef) }
842
+
843
+ BreakEvent.catch do
844
+ node.function_body.block_items.each { |item| interpret(item) }
845
+ end
835
846
 
836
- notify_block_ended(node.function_body)
837
- notify_function_ended(node, function)
847
+ notify_block_ended(node.function_body)
848
+ notify_function_ended(node, function)
849
+ end
850
+ ensure
851
+ interpreter._leave_function(node)
838
852
  end
839
- ensure
840
- interpreter._leave_function(node)
841
853
  end
842
854
  end
843
855
 
844
856
  class StatementInterpreter < SubInterpreter
845
- include BranchGroup::Option
846
- include Branch::Option
857
+ include BranchOptions
858
+ include BranchGroupOptions
847
859
  include SyntaxNodeCollector
848
860
 
849
861
  def initialize(owner)
@@ -865,8 +877,7 @@ module C #:nodoc:
865
877
 
866
878
  node.executed = true
867
879
  ctrlexpr = node.expression
868
- ctrlexpr_result = object_to_variable(interpret(ctrlexpr,
869
- :suppress_notification))
880
+ ctrlexpr_result = object_to_variable(interpret(ctrlexpr, QUIET))
870
881
  notify_case_ctrlexpr_evaled(node, ctrlexpr_result)
871
882
 
872
883
  interpret(node.statement)
@@ -905,7 +916,7 @@ module C #:nodoc:
905
916
 
906
917
  node.executed = true
907
918
  ctrlexpr = node.expression
908
- ctrlexpr_value = value_of(interpret(ctrlexpr, :suppress_notification))
919
+ ctrlexpr_value = value_of(interpret(ctrlexpr, QUIET))
909
920
  notify_if_ctrlexpr_evaled(node, ctrlexpr_value)
910
921
 
911
922
  case
@@ -931,7 +942,7 @@ module C #:nodoc:
931
942
 
932
943
  node.executed = true
933
944
  ctrlexpr = node.expression
934
- ctrlexpr_value = value_of(interpret(ctrlexpr, :suppress_notification))
945
+ ctrlexpr_value = value_of(interpret(ctrlexpr, QUIET))
935
946
  notify_if_else_ctrlexpr_evaled(node, ctrlexpr_value)
936
947
 
937
948
  case
@@ -1303,8 +1314,8 @@ module C #:nodoc:
1303
1314
  end
1304
1315
 
1305
1316
  class SwitchStatementInterpreter < SubInterpreter
1306
- include BranchGroup::Option
1307
- include Branch::Option
1317
+ include BranchOptions
1318
+ include BranchGroupOptions
1308
1319
 
1309
1320
  def initialize(owner)
1310
1321
  super(owner, SwitchStatement)
@@ -1367,7 +1378,7 @@ module C #:nodoc:
1367
1378
 
1368
1379
  def execute_branch(labeled_statement, block_items, index, branch_options)
1369
1380
  ctrlexpr = labeled_statement.normalized_expression
1370
- ctrlexpr_value = value_of(interpret(ctrlexpr, :suppress_notification))
1381
+ ctrlexpr_value = value_of(interpret(ctrlexpr, QUIET))
1371
1382
 
1372
1383
  case
1373
1384
  when ctrlexpr_value.must_be_true?
@@ -1411,7 +1422,7 @@ module C #:nodoc:
1411
1422
 
1412
1423
  branch.restart_versioning do
1413
1424
  ctrlexpr = labeled_statement.normalized_expression
1414
- ctrlexpr_value = value_of(interpret(ctrlexpr, :suppress_notification))
1425
+ ctrlexpr_value = value_of(interpret(ctrlexpr, QUIET))
1415
1426
 
1416
1427
  case
1417
1428
  when ctrlexpr_value.must_be_true?
@@ -1481,6 +1492,8 @@ module C #:nodoc:
1481
1492
 
1482
1493
  class ExpressionInterpreter < SubInterpreter
1483
1494
  include ExpressionEvaluator
1495
+ include BranchOptions
1496
+ include BranchGroupOptions
1484
1497
 
1485
1498
  def initialize(owner)
1486
1499
  super(owner, Expression)
@@ -1534,10 +1547,54 @@ module C #:nodoc:
1534
1547
  def_eval_with_sequence_point :visit_inclusive_or_expression
1535
1548
  def_eval_with_sequence_point :visit_logical_and_expression
1536
1549
  def_eval_with_sequence_point :visit_logical_or_expression
1537
- def_eval_with_sequence_point :visit_conditional_expression
1538
1550
  def_eval_with_sequence_point :visit_simple_assignment_expression
1539
1551
  def_eval_with_sequence_point :visit_compound_assignment_expression
1540
1552
  def_eval_with_sequence_point :visit_comma_separated_expression
1553
+
1554
+ def visit_conditional_expression(node)
1555
+ checkpoint(node.location)
1556
+
1557
+ ctrlexpr = node.condition
1558
+ ctrlexpr_variable = interpret(ctrlexpr, QUIET)
1559
+ ctrlexpr_value = value_of(ctrlexpr_variable)
1560
+
1561
+ then_var = nil
1562
+ if ctrlexpr_value.may_be_true?
1563
+ branched_eval(ctrlexpr, NARROWING) do
1564
+ then_var = object_to_variable(interpret(node.then_expression))
1565
+ end
1566
+ end
1567
+
1568
+ else_var = nil
1569
+ if ctrlexpr_value.may_be_false?
1570
+ branched_eval(nil, NARROWING, FINAL, COMPLETE) do
1571
+ else_var = object_to_variable(interpret(node.else_expression))
1572
+ end
1573
+ else
1574
+ branched_eval(nil, NARROWING, FINAL, COMPLETE) {}
1575
+ end
1576
+
1577
+ case
1578
+ when then_var && else_var
1579
+ result_val = then_var.value.single_value_unified_with(else_var.value)
1580
+ result = temporary_variable(then_var.type, result_val)
1581
+ when then_var
1582
+ result = then_var
1583
+ when else_var
1584
+ result = else_var
1585
+ else
1586
+ # FIXME: Nevertheless, the then-expression is not reachable, the branch
1587
+ # execution check may fail in evaluation of the else branch.
1588
+ result = temporary_variable
1589
+ end
1590
+
1591
+ notify_conditional_expr_evaled(node, ctrlexpr_variable, result)
1592
+ result
1593
+ ensure
1594
+ if sequence_point = node.subsequent_sequence_point
1595
+ notify_sequence_point_reached(sequence_point)
1596
+ end
1597
+ end
1541
1598
  end
1542
1599
 
1543
1600
  end
@@ -106,6 +106,7 @@ module C #:nodoc:
106
106
  def_delegator :variable_table, :lookup, :variable_named
107
107
  def_delegator :variable_table, :declare, :declare_variable
108
108
  def_delegator :variable_table, :define, :define_variable
109
+ def_delegator :variable_table, :storage_duration_of
109
110
 
110
111
  def local_variables
111
112
  variable_table.all_named_variables.select { |variable|
@@ -132,6 +133,7 @@ module C #:nodoc:
132
133
  extend Forwardable
133
134
 
134
135
  def_delegator :function_table, :lookup, :function_named
136
+ def_delegator :function_table, :declare, :declare_function
135
137
  def_delegator :function_table, :define, :define_function
136
138
 
137
139
  def define_explicit_function(function_declaration_or_definition)
@@ -177,10 +179,11 @@ module C #:nodoc:
177
179
 
178
180
  extend Forwardable
179
181
 
180
- def_delegator :interpreter, :notify_variable_initialized
182
+ def_delegator :interpreter, :notify_variable_declared
181
183
  def_delegator :interpreter, :notify_variable_defined
184
+ def_delegator :interpreter, :notify_variable_initialized
182
185
  def_delegator :interpreter, :notify_function_declared
183
- def_delegator :interpreter, :notify_variable_declared
186
+ def_delegator :interpreter, :notify_function_defined
184
187
  def_delegator :interpreter, :notify_struct_declared
185
188
  def_delegator :interpreter, :notify_union_declared
186
189
  def_delegator :interpreter, :notify_enum_declared