adlint 1.8.10 → 1.10.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 (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