adlint 1.4.0 → 1.6.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 (46) hide show
  1. data/ChangeLog +413 -5
  2. data/MANIFEST +6 -0
  3. data/NEWS +43 -4
  4. data/etc/mesg.d/en_US/messages.yml +1 -1
  5. data/etc/mesg.d/ja_JP/messages.yml +1 -1
  6. data/lib/adlint/c.rb +1 -0
  7. data/lib/adlint/c/enum.rb +52 -0
  8. data/lib/adlint/c/expr.rb +43 -102
  9. data/lib/adlint/c/interp.rb +1 -1
  10. data/lib/adlint/c/mediator.rb +1 -0
  11. data/lib/adlint/c/message.rb +831 -49
  12. data/lib/adlint/c/message_shima.rb +236 -0
  13. data/lib/adlint/c/metric.rb +9 -0
  14. data/lib/adlint/c/object.rb +37 -32
  15. data/lib/adlint/c/parser.rb +7 -7
  16. data/lib/adlint/c/parser.y +7 -7
  17. data/lib/adlint/c/phase.rb +21 -0
  18. data/lib/adlint/c/syntax.rb +11 -4
  19. data/lib/adlint/c/type.rb +1 -1
  20. data/lib/adlint/cpp.rb +1 -0
  21. data/lib/adlint/cpp/asm.rb +73 -0
  22. data/lib/adlint/cpp/message.rb +13 -0
  23. data/lib/adlint/cpp/message_shima.rb +36 -0
  24. data/lib/adlint/cpp/phase.rb +3 -0
  25. data/lib/adlint/cpp/source.rb +9 -0
  26. data/lib/adlint/version.rb +3 -3
  27. data/share/demo/Makefile +4 -0
  28. data/share/demo/bad_conv/bad_conv.c +12 -0
  29. data/share/demo/bad_enum/bad_enum.c +48 -2
  30. data/share/demo/bad_label/bad_label.c +26 -0
  31. data/share/demo/bad_macro/bad_macro.c +3 -0
  32. data/share/demo/implicit_conv/implicit_conv.c +1 -0
  33. data/share/demo/inline_asm/inline_asm.c +18 -0
  34. data/share/demo/invalid_call/invalid_call.c +5 -0
  35. data/share/demo/multi_decl/multi_decl_1.c +30 -0
  36. data/share/demo/overflow/overflow.c +3 -3
  37. data/share/demo/redundant_select/redundant_select.c +25 -0
  38. data/share/demo/reserved_ident/reserved_ident.c +98 -0
  39. data/share/doc/developers_guide_ja.html +3 -3
  40. data/share/doc/developers_guide_ja.texi +1 -1
  41. data/share/doc/users_guide_en.html +234 -126
  42. data/share/doc/users_guide_en.texi +207 -98
  43. data/share/doc/users_guide_ja.html +247 -156
  44. data/share/doc/users_guide_ja.texi +221 -130
  45. data/share/sample/vim-7.3/adlint/xxd/adlint_traits.yml +1 -1
  46. metadata +8 -2
@@ -127,7 +127,7 @@ module C #:nodoc:
127
127
 
128
128
  # NOTE: Notified when the interpreter evaluates an expression which results
129
129
  # a named variable.
130
- def_plugin_and_notifier :variable_referred, :object_specifier, :variable
130
+ def_plugin_and_notifier :variable_referred, :expression, :variable
131
131
 
132
132
  # NOTE: Notified when the interpreter evaluates an expression which results
133
133
  # a constant temporary variable.
@@ -31,6 +31,7 @@
31
31
 
32
32
  require "adlint/c/type"
33
33
  require "adlint/c/object"
34
+ require "adlint/c/enum"
34
35
  require "adlint/c/syntax"
35
36
 
36
37
  module AdLint #:nodoc:
@@ -440,6 +440,9 @@ module C #:nodoc:
440
440
  private
441
441
  def check_comparison(binary_expression,
442
442
  lhs_variable, rhs_variable, result)
443
+ return if binary_expression.lhs_operand.kind_of?(NullConstantSpecifier)
444
+ return if binary_expression.rhs_operand.kind_of?(NullConstantSpecifier)
445
+
443
446
  if lhs_variable.type.pointer? || rhs_variable.type.pointer?
444
447
  W(:W0027, binary_expression.location)
445
448
  end
@@ -453,11 +456,12 @@ module C #:nodoc:
453
456
  interp.on_indirection_expr_evaled += method(:check_indirection)
454
457
  interp.on_member_access_expr_evaled += method(:check_member_access)
455
458
  interp.on_array_subscript_expr_evaled += method(:check_array_subscript)
459
+ @enum_tbl = interp.environment.enumerator_table
456
460
  end
457
461
 
458
462
  private
459
463
  def check_indirection(indirection_expression, variable, dereferenced)
460
- return unless indirection_expression.operand.constant?
464
+ return unless indirection_expression.operand.constant?(@enum_tbl)
461
465
 
462
466
  if variable.value.scalar? &&
463
467
  variable.value.must_be_equal_to?(ScalarValue.of(0))
@@ -468,7 +472,7 @@ module C #:nodoc:
468
472
  def check_member_access(member_access_expression,
469
473
  outer_variable, member_variable)
470
474
  return unless outer_variable.type.pointer?
471
- return unless member_access_expression.expression.constant?
475
+ return unless member_access_expression.expression.constant?(@enum_tbl)
472
476
  if outer_variable.value.scalar? &&
473
477
  outer_variable.value.must_be_equal_to?(ScalarValue.of(0))
474
478
  W(:W0028, member_access_expression.location)
@@ -479,7 +483,7 @@ module C #:nodoc:
479
483
  pointer_variable, subscript_variable,
480
484
  array_variable, result_variable)
481
485
  return unless pointer_variable.type.pointer?
482
- return unless array_subscript_expression.expression.constant?
486
+ return unless array_subscript_expression.expression.constant?(@enum_tbl)
483
487
  if pointer_variable.value.scalar? &&
484
488
  pointer_variable.value.must_be_equal_to?(ScalarValue.of(0))
485
489
  W(:W0028, array_subscript_expression.location)
@@ -501,6 +505,7 @@ module C #:nodoc:
501
505
  interp.on_postfix_increment_expr_evaled += method(:check_unary_postfix)
502
506
  interp.on_prefix_decrement_expr_evaled += method(:check_unary_prefix)
503
507
  interp.on_postfix_decrement_expr_evaled += method(:check_unary_postfix)
508
+ @enum_tbl = interp.environment.enumerator_table
504
509
  end
505
510
 
506
511
  private
@@ -508,12 +513,12 @@ module C #:nodoc:
508
513
  lhs_type, lhs_value = lhs_variable.type, lhs_variable.value
509
514
  rhs_type, rhs_value = rhs_variable.type, rhs_variable.value
510
515
 
511
- if binary_expression.lhs_operand.constant? &&
516
+ if binary_expression.lhs_operand.constant?(@enum_tbl) &&
512
517
  lhs_type.pointer? && lhs_value.must_be_equal_to?(ScalarValue.of(0))
513
518
  W(:W0030, binary_expression.lhs_operand.location)
514
519
  end
515
520
 
516
- if binary_expression.rhs_operand.constant? &&
521
+ if binary_expression.rhs_operand.constant?(@enum_tbl) &&
517
522
  rhs_type.pointer? && rhs_value.must_be_equal_to?(ScalarValue.of(0))
518
523
  W(:W0030, binary_expression.rhs_operand.location)
519
524
  end
@@ -522,7 +527,7 @@ module C #:nodoc:
522
527
  def check_unary_prefix(unary_expression, operand_variable, original_value)
523
528
  type, value = operand_variable.type, original_value
524
529
 
525
- if unary_expression.operand.constant? &&
530
+ if unary_expression.operand.constant?(@enum_tbl) &&
526
531
  type.pointer? && value.must_be_equal_to?(ScalarValue.of(0))
527
532
  W(:W0030, unary_expression.operand.location)
528
533
  end
@@ -532,7 +537,7 @@ module C #:nodoc:
532
537
  operand_variable, result_variable)
533
538
  type, value = operand_variable.type, operand_variable.value
534
539
 
535
- if postfix_expression.operand.constant? &&
540
+ if postfix_expression.operand.constant?(@enum_tbl) &&
536
541
  type.pointer? && value.must_be_equal_to?(ScalarValue.of(0))
537
542
  W(:W0030, postfix_expression.operand.location)
538
543
  end
@@ -546,6 +551,7 @@ module C #:nodoc:
546
551
  interp.on_function_started += method(:start_function)
547
552
  interp.on_parameter_defined += method(:add_parameter)
548
553
  interp.on_variable_referred += method(:use_parameter)
554
+ interp.on_variable_value_referred += method(:use_parameter)
549
555
  interp.on_function_ended += method(:check_unused_parameter)
550
556
  @parameters = nil
551
557
  end
@@ -563,7 +569,7 @@ module C #:nodoc:
563
569
  end
564
570
  end
565
571
 
566
- def use_parameter(object_specifier, variable)
572
+ def use_parameter(expression, variable)
567
573
  return unless @parameters
568
574
 
569
575
  if variable.named?
@@ -1773,12 +1779,13 @@ module C #:nodoc:
1773
1779
  super
1774
1780
  interp = context[:c_interpreter]
1775
1781
  interp.on_multiplicative_expr_evaled += method(:check)
1782
+ @enum_tbl = interp.environment.enumerator_table
1776
1783
  end
1777
1784
 
1778
1785
  private
1779
1786
  def check(multiplicative_expression, lhs_variable, rhs_variable, result)
1780
1787
  return if multiplicative_expression.operator.type == "*"
1781
- return if multiplicative_expression.rhs_operand.constant?
1788
+ return if multiplicative_expression.rhs_operand.constant?(@enum_tbl)
1782
1789
 
1783
1790
  return unless rhs_variable.type.scalar? && rhs_variable.value.scalar?
1784
1791
  return if rhs_variable.value.must_be_equal_to?(ScalarValue.of(0))
@@ -1794,12 +1801,13 @@ module C #:nodoc:
1794
1801
  super
1795
1802
  interp = context[:c_interpreter]
1796
1803
  interp.on_multiplicative_expr_evaled += method(:check)
1804
+ @enum_tbl = interp.environment.enumerator_table
1797
1805
  end
1798
1806
 
1799
1807
  private
1800
1808
  def check(multiplicative_expression, lhs_variable, rhs_variable, result)
1801
1809
  return if multiplicative_expression.operator.type == "*"
1802
- return unless multiplicative_expression.rhs_operand.constant?
1810
+ return unless multiplicative_expression.rhs_operand.constant?(@enum_tbl)
1803
1811
 
1804
1812
  return unless rhs_variable.type.scalar? && rhs_variable.value.scalar?
1805
1813
 
@@ -1814,12 +1822,13 @@ module C #:nodoc:
1814
1822
  super
1815
1823
  interp = context[:c_interpreter]
1816
1824
  interp.on_multiplicative_expr_evaled += method(:check)
1825
+ @enum_tbl = interp.environment.enumerator_table
1817
1826
  end
1818
1827
 
1819
1828
  private
1820
1829
  def check(multiplicative_expression, lhs_variable, rhs_variable, result)
1821
1830
  return if multiplicative_expression.operator.type == "*"
1822
- return if multiplicative_expression.rhs_operand.constant?
1831
+ return if multiplicative_expression.rhs_operand.constant?(@enum_tbl)
1823
1832
 
1824
1833
  return unless rhs_variable.type.scalar? && rhs_variable.value.scalar?
1825
1834
 
@@ -2059,6 +2068,8 @@ module C #:nodoc:
2059
2068
 
2060
2069
  @parameters.each do |name, (written, variable, location)|
2061
2070
  next if variable.type.const?
2071
+ next if variable.type.array? && variable.type.base_type.const?
2072
+
2062
2073
  W(:W0104, location, name) unless written
2063
2074
  end
2064
2075
 
@@ -6041,11 +6052,12 @@ module C #:nodoc:
6041
6052
  interp.on_indirection_expr_evaled += method(:check_indirection)
6042
6053
  interp.on_member_access_expr_evaled += method(:check_member_access)
6043
6054
  interp.on_array_subscript_expr_evaled += method(:check_array_subscript)
6055
+ @enum_tbl = interp.environment.enumerator_table
6044
6056
  end
6045
6057
 
6046
6058
  private
6047
6059
  def check_indirection(indirection_expression, variable, dereferenced)
6048
- return if indirection_expression.operand.constant?
6060
+ return if indirection_expression.operand.constant?(@enum_tbl)
6049
6061
  if variable.value.scalar? &&
6050
6062
  variable.value.must_be_equal_to?(ScalarValue.of(0))
6051
6063
  W(:W0421, indirection_expression.location)
@@ -6055,7 +6067,7 @@ module C #:nodoc:
6055
6067
  def check_member_access(member_access_expression,
6056
6068
  outer_variable, member_variable)
6057
6069
  return unless outer_variable.type.pointer?
6058
- return if member_access_expression.expression.constant?
6070
+ return if member_access_expression.expression.constant?(@enum_tbl)
6059
6071
  if outer_variable.value.scalar? &&
6060
6072
  outer_variable.value.must_be_equal_to?(ScalarValue.of(0))
6061
6073
  W(:W0421, member_access_expression.location)
@@ -6066,7 +6078,7 @@ module C #:nodoc:
6066
6078
  pointer_variable, subscript_variable,
6067
6079
  array_variable, result_variable)
6068
6080
  return unless pointer_variable.type.pointer?
6069
- return if array_subscript_expression.expression.constant?
6081
+ return if array_subscript_expression.expression.constant?(@enum_tbl)
6070
6082
  if pointer_variable.value.scalar? &&
6071
6083
  pointer_variable.value.must_be_equal_to?(ScalarValue.of(0))
6072
6084
  W(:W0421, array_subscript_expression.location)
@@ -6081,11 +6093,12 @@ module C #:nodoc:
6081
6093
  interp.on_indirection_expr_evaled += method(:check_indirection)
6082
6094
  interp.on_member_access_expr_evaled += method(:check_member_access)
6083
6095
  interp.on_array_subscript_expr_evaled += method(:check_array_subscript)
6096
+ @enum_tbl = interp.environment.enumerator_table
6084
6097
  end
6085
6098
 
6086
6099
  private
6087
6100
  def check_indirection(indirection_expression, variable, dereferenced)
6088
- return if indirection_expression.operand.constant?
6101
+ return if indirection_expression.operand.constant?(@enum_tbl)
6089
6102
  return unless variable.value.scalar?
6090
6103
 
6091
6104
  if !variable.value.must_be_equal_to?(ScalarValue.of(0)) &&
@@ -6097,7 +6110,7 @@ module C #:nodoc:
6097
6110
  def check_member_access(member_access_expression,
6098
6111
  outer_variable, member_variable)
6099
6112
  return unless outer_variable.type.pointer?
6100
- return if member_access_expression.expression.constant?
6113
+ return if member_access_expression.expression.constant?(@enum_tbl)
6101
6114
  return unless outer_variable.value.scalar?
6102
6115
 
6103
6116
  if !outer_variable.value.must_be_equal_to?(ScalarValue.of(0)) &&
@@ -6110,7 +6123,7 @@ module C #:nodoc:
6110
6123
  pointer_variable, subscript_variable,
6111
6124
  array_variable, result_variable)
6112
6125
  return unless pointer_variable.type.pointer?
6113
- return if array_subscript_expression.expression.constant?
6126
+ return if array_subscript_expression.expression.constant?(@enum_tbl)
6114
6127
  return unless pointer_variable.value.scalar?
6115
6128
 
6116
6129
  if !pointer_variable.value.must_be_equal_to?(ScalarValue.of(0)) &&
@@ -7029,7 +7042,7 @@ module C #:nodoc:
7029
7042
  base_type = type.unqualify.base_type
7030
7043
  next unless !base_type.function? && base_type.const?
7031
7044
 
7032
- if pointee = @interp.pointee_of(arg)
7045
+ if pointee = @interp.pointee_of(arg) and pointee.variable?
7033
7046
  if pointee.value.must_be_undefined?
7034
7047
  W(:W0461,
7035
7048
  function_call_expression.argument_expressions[index].location)
@@ -7055,7 +7068,7 @@ module C #:nodoc:
7055
7068
  next unless type && type.pointer?
7056
7069
  next unless type.unqualify.base_type.const?
7057
7070
 
7058
- if pointee = @interp.pointee_of(arg)
7071
+ if pointee = @interp.pointee_of(arg) and pointee.variable?
7059
7072
  next if pointee.value.must_be_undefined?
7060
7073
  if pointee.value.may_be_undefined?
7061
7074
  W(:W0462,
@@ -10048,6 +10061,7 @@ module C #:nodoc:
10048
10061
  super
10049
10062
  interp = context[:c_interpreter]
10050
10063
  interp.on_shift_expr_evaled += method(:check)
10064
+ @enum_tbl = interp.environment.enumerator_table
10051
10065
  end
10052
10066
 
10053
10067
  private
@@ -10055,7 +10069,7 @@ module C #:nodoc:
10055
10069
  operator = shift_expression.operator.type
10056
10070
  return unless operator == "<<" || operator == "<<="
10057
10071
 
10058
- return unless shift_expression.lhs_operand.constant?
10072
+ return unless shift_expression.lhs_operand.constant?(@enum_tbl)
10059
10073
  return unless lhs_variable.type.signed?
10060
10074
 
10061
10075
  if lhs_variable.value.must_be_less_than?(ScalarValue.of(0)) or
@@ -10076,6 +10090,7 @@ module C #:nodoc:
10076
10090
  super
10077
10091
  interp = context[:c_interpreter]
10078
10092
  interp.on_shift_expr_evaled += method(:check)
10093
+ @enum_tbl = interp.environment.enumerator_table
10079
10094
  end
10080
10095
 
10081
10096
  private
@@ -10083,7 +10098,7 @@ module C #:nodoc:
10083
10098
  operator = shift_expression.operator.type
10084
10099
  return unless operator == "<<" || operator == "<<="
10085
10100
 
10086
- return if shift_expression.lhs_operand.constant?
10101
+ return if shift_expression.lhs_operand.constant?(@enum_tbl)
10087
10102
  return unless lhs_variable.type.signed?
10088
10103
 
10089
10104
  if lhs_variable.value.must_be_less_than?(ScalarValue.of(0)) or
@@ -10104,6 +10119,7 @@ module C #:nodoc:
10104
10119
  super
10105
10120
  interp = context[:c_interpreter]
10106
10121
  interp.on_shift_expr_evaled += method(:check)
10122
+ @enum_tbl = interp.environment.enumerator_table
10107
10123
  end
10108
10124
 
10109
10125
  private
@@ -10111,7 +10127,7 @@ module C #:nodoc:
10111
10127
  operator = shift_expression.operator.type
10112
10128
  return unless operator == "<<" || operator == "<<="
10113
10129
 
10114
- return if shift_expression.lhs_operand.constant?
10130
+ return if shift_expression.lhs_operand.constant?(@enum_tbl)
10115
10131
  return unless lhs_variable.type.signed?
10116
10132
 
10117
10133
  if !lhs_variable.value.must_be_less_than?(ScalarValue.of(0)) &&
@@ -10211,7 +10227,7 @@ module C #:nodoc:
10211
10227
  if src_type.integer_conversion_rank < dst_type.integer_conversion_rank
10212
10228
  case @rvalues[original_variable]
10213
10229
  when UnaryArithmeticExpression, ShiftExpression,
10214
- AdditiveExpression, MultiplicativeExpression
10230
+ AdditiveExpression, MultiplicativeExpression
10215
10231
  W(:W0578, initializer_or_expression.location)
10216
10232
  end
10217
10233
  end
@@ -10249,6 +10265,68 @@ module C #:nodoc:
10249
10265
  end
10250
10266
  end
10251
10267
 
10268
+ class W0579 < PassiveMessageDetection
10269
+ def initialize(context)
10270
+ super
10271
+ interp = context[:c_interpreter]
10272
+ interp.on_explicit_conv_performed += method(:check)
10273
+ interp.on_function_started += method(:clear_rvalues)
10274
+ interp.on_unary_arithmetic_expr_evaled += method(:handle_unary)
10275
+ interp.on_shift_expr_evaled += method(:handle_shift)
10276
+ interp.on_additive_expr_evaled += method(:handle_additive)
10277
+ interp.on_multiplicative_expr_evaled += method(:handle_multiplicative)
10278
+ @rvalues = nil
10279
+ end
10280
+
10281
+ private
10282
+ def check(cast_expression, original_variable, result_variable)
10283
+ return unless @rvalues
10284
+ return unless original_variable.type.integer?
10285
+
10286
+ src_type = original_variable.type
10287
+ dst_type = result_variable.type
10288
+
10289
+ if src_type.integer_conversion_rank < dst_type.integer_conversion_rank
10290
+ case @rvalues[original_variable]
10291
+ when UnaryArithmeticExpression, ShiftExpression,
10292
+ AdditiveExpression, MultiplicativeExpression
10293
+ W(:W0579, cast_expression.location)
10294
+ end
10295
+ end
10296
+ end
10297
+
10298
+ def clear_rvalues(function_definition)
10299
+ @rvalues = {}
10300
+ end
10301
+
10302
+ def handle_unary(unary_arithmetic_expression,
10303
+ operand_variable, result_variable)
10304
+ return unless unary_arithmetic_expression.operator == "~"
10305
+ memorize_rvalue_derivation(result_variable, unary_arithmetic_expression)
10306
+ end
10307
+
10308
+ def handle_shift(shift_expression,
10309
+ lhs_variable, rhs_variable, result_variable)
10310
+ return unless shift_expression.operator.type == "<<"
10311
+ memorize_rvalue_derivation(result_variable, shift_expression)
10312
+ end
10313
+
10314
+ def handle_additive(additive_expression,
10315
+ lhs_variable, rhs_variable, result_variable)
10316
+ memorize_rvalue_derivation(result_variable, additive_expression)
10317
+ end
10318
+
10319
+ def handle_multiplicative(multiplicative_expression,
10320
+ lhs_variable, rhs_variable, result_variable)
10321
+ return if multiplicative_expression.operator.type == "%"
10322
+ memorize_rvalue_derivation(result_variable, multiplicative_expression)
10323
+ end
10324
+
10325
+ def memorize_rvalue_derivation(rvalue_holder, expression)
10326
+ @rvalues[rvalue_holder] = expression if @rvalues
10327
+ end
10328
+ end
10329
+
10252
10330
  class W0580 < PassiveMessageDetection
10253
10331
  def initialize(context)
10254
10332
  super
@@ -10767,6 +10845,7 @@ module C #:nodoc:
10767
10845
  interp.on_do_stmt_ended += method(:check)
10768
10846
  interp.on_for_stmt_ended += method(:check)
10769
10847
  interp.on_c99_for_stmt_ended += method(:check)
10848
+ @enum_tbl = interp.environment.enumerator_table
10770
10849
  @iteration_stmts = []
10771
10850
  end
10772
10851
 
@@ -10820,12 +10899,14 @@ module C #:nodoc:
10820
10899
  end
10821
10900
 
10822
10901
  def check(iteration_statement)
10823
- if ctrlexpr = @iteration_stmts.last.ctrlexpr and !ctrlexpr.constant?
10824
- ctrlexpr_value = @iteration_stmts.last.ctrlexpr_value
10825
- ctrl_vars = @iteration_stmts.last.ctrl_vars
10826
- if ctrlexpr_value && ctrlexpr_value.must_be_true? and
10827
- ctrl_vars && ctrl_vars.values.none?
10828
- W(:W0611, ctrlexpr.location)
10902
+ if ctrlexpr = @iteration_stmts.last.ctrlexpr
10903
+ unless ctrlexpr.constant?(@enum_tbl)
10904
+ ctrlexpr_value = @iteration_stmts.last.ctrlexpr_value
10905
+ ctrl_vars = @iteration_stmts.last.ctrl_vars
10906
+ if ctrlexpr_value && ctrlexpr_value.must_be_true? and
10907
+ ctrl_vars && ctrl_vars.values.none?
10908
+ W(:W0611, ctrlexpr.location)
10909
+ end
10829
10910
  end
10830
10911
  end
10831
10912
  @iteration_stmts.pop
@@ -10838,13 +10919,14 @@ module C #:nodoc:
10838
10919
  interp = context[:c_interpreter]
10839
10920
  interp.on_if_ctrlexpr_evaled += method(:check)
10840
10921
  interp.on_if_else_ctrlexpr_evaled += method(:check)
10922
+ @enum_tbl = interp.environment.enumerator_table
10841
10923
  end
10842
10924
 
10843
10925
  private
10844
10926
  def check(selection_statement, ctrlexpr_value)
10845
- if ctrlexpr = selection_statement.expression and !ctrlexpr.constant?
10846
- if ctrlexpr_value.must_be_true?
10847
- W(:W0612, ctrlexpr.location)
10927
+ if ctrlexpr = selection_statement.expression
10928
+ unless ctrlexpr.constant?(@enum_tbl)
10929
+ W(:W0612, ctrlexpr.location) if ctrlexpr_value.must_be_true?
10848
10930
  end
10849
10931
  end
10850
10932
  end
@@ -10902,11 +10984,12 @@ module C #:nodoc:
10902
10984
  super
10903
10985
  interp = context[:c_interpreter]
10904
10986
  interp.on_do_ctrlexpr_evaled += method(:check)
10987
+ @enum_tbl = interp.environment.enumerator_table
10905
10988
  end
10906
10989
 
10907
10990
  private
10908
10991
  def check(do_statement, ctrlexpr_value)
10909
- unless do_statement.expression.constant?
10992
+ unless do_statement.expression.constant?(@enum_tbl)
10910
10993
  if ctrlexpr_value.must_be_false?
10911
10994
  W(:W0614, do_statement.expression.location)
10912
10995
  end
@@ -12406,7 +12489,8 @@ module C #:nodoc:
12406
12489
 
12407
12490
  value = original_variable.value.unique_sample
12408
12491
 
12409
- unless result_variable.type.enumerators.any? { |enum| value == enum.value }
12492
+ enumerators = result_variable.type.enumerators
12493
+ unless enumerators.any? { |enum| value == enum.value }
12410
12494
  W(:W0727, initializer_or_expression.location)
12411
12495
  end
12412
12496
  end
@@ -12417,6 +12501,7 @@ module C #:nodoc:
12417
12501
  super
12418
12502
  interp = context[:c_interpreter]
12419
12503
  interp.on_function_call_expr_evaled += method(:check)
12504
+ @enum_tbl = interp.environment.enumerator_table
12420
12505
  end
12421
12506
 
12422
12507
  private
@@ -12425,9 +12510,12 @@ module C #:nodoc:
12425
12510
  args.each_with_index do |(arg_variable, param_type), index|
12426
12511
  next unless param_type && param_type.enum?
12427
12512
 
12513
+ arg_expr = expression.argument_expressions[index]
12514
+ next unless arg_expr.constant?(@enum_tbl)
12515
+
12428
12516
  if arg_variable.type.enum?
12429
12517
  unless arg_variable.type.same_as?(param_type)
12430
- W(:W0728, expression.argument_expressions[index].location)
12518
+ W(:W0728, arg_expr.location)
12431
12519
  end
12432
12520
  end
12433
12521
  end
@@ -12439,11 +12527,13 @@ module C #:nodoc:
12439
12527
  super
12440
12528
  interp = context[:c_interpreter]
12441
12529
  interp.on_assignment_expr_evaled += method(:check)
12530
+ @enum_tbl = interp.environment.enumerator_table
12442
12531
  end
12443
12532
 
12444
12533
  private
12445
12534
  def check(expression, lhs_variable, rhs_variable)
12446
12535
  return unless lhs_variable.type.enum?
12536
+ return unless expression.rhs_operand.constant?(@enum_tbl)
12447
12537
 
12448
12538
  if rhs_variable.type.enum?
12449
12539
  unless lhs_variable.type.same_as?(rhs_variable.type)
@@ -12460,6 +12550,7 @@ module C #:nodoc:
12460
12550
  interp.on_function_started += method(:start_function)
12461
12551
  interp.on_function_ended += method(:end_function)
12462
12552
  interp.on_return_stmt_evaled += method(:check)
12553
+ @enum_tbl = interp.environment.enumerator_table
12463
12554
  @current_function = nil
12464
12555
  end
12465
12556
 
@@ -12477,6 +12568,7 @@ module C #:nodoc:
12477
12568
 
12478
12569
  return unless return_type = @current_function.type.return_type
12479
12570
  return unless return_type.enum?
12571
+ return unless return_statement.expression.constant?(@enum_tbl)
12480
12572
 
12481
12573
  if result_variable.type.enum?
12482
12574
  unless return_type.same_as?(result_variable.type)
@@ -12593,6 +12685,7 @@ module C #:nodoc:
12593
12685
  super
12594
12686
  interp = context[:c_interpreter]
12595
12687
  interp.on_implicit_conv_performed += method(:check)
12688
+ @enum_tbl = interp.environment.enumerator_table
12596
12689
  end
12597
12690
 
12598
12691
  private
@@ -12606,7 +12699,7 @@ module C #:nodoc:
12606
12699
  expression = initializer_or_expression
12607
12700
  end
12608
12701
 
12609
- return unless expression.constant?
12702
+ return unless expression.constant?(@enum_tbl)
12610
12703
 
12611
12704
  orig_type = original_variable.type
12612
12705
  conv_type = result_variable.type
@@ -12630,14 +12723,15 @@ module C #:nodoc:
12630
12723
  super
12631
12724
  interp = context[:c_interpreter]
12632
12725
  interp.on_additive_expr_evaled += method(:check)
12726
+ @enum_tbl = interp.environment.enumerator_table
12633
12727
  end
12634
12728
 
12635
12729
  private
12636
12730
  def check(additive_expression, lhs_variable, rhs_variable, result_variable)
12637
12731
  return unless additive_expression.operator.type == "-"
12638
12732
 
12639
- return unless additive_expression.lhs_operand.constant?
12640
- return unless additive_expression.rhs_operand.constant?
12733
+ return unless additive_expression.lhs_operand.constant?(@enum_tbl)
12734
+ return unless additive_expression.rhs_operand.constant?(@enum_tbl)
12641
12735
 
12642
12736
  return unless lhs_variable.type.scalar? && lhs_variable.type.unsigned?
12643
12737
  return unless rhs_variable.type.scalar? && rhs_variable.type.unsigned?
@@ -12658,14 +12752,15 @@ module C #:nodoc:
12658
12752
  super
12659
12753
  interp = context[:c_interpreter]
12660
12754
  interp.on_additive_expr_evaled += method(:check)
12755
+ @enum_tbl = interp.environment.enumerator_table
12661
12756
  end
12662
12757
 
12663
12758
  private
12664
12759
  def check(additive_expression, lhs_variable, rhs_variable, result_variable)
12665
12760
  return unless additive_expression.operator.type == "+"
12666
12761
 
12667
- return unless additive_expression.lhs_operand.constant?
12668
- return unless additive_expression.rhs_operand.constant?
12762
+ return unless additive_expression.lhs_operand.constant?(@enum_tbl)
12763
+ return unless additive_expression.rhs_operand.constant?(@enum_tbl)
12669
12764
 
12670
12765
  return unless lhs_variable.type.scalar? && lhs_variable.type.unsigned?
12671
12766
  return unless rhs_variable.type.scalar? && rhs_variable.type.unsigned?
@@ -12686,6 +12781,7 @@ module C #:nodoc:
12686
12781
  super
12687
12782
  interp = context[:c_interpreter]
12688
12783
  interp.on_multiplicative_expr_evaled += method(:check)
12784
+ @enum_tbl = interp.environment.enumerator_table
12689
12785
  end
12690
12786
 
12691
12787
  private
@@ -12693,8 +12789,8 @@ module C #:nodoc:
12693
12789
  result_variable)
12694
12790
  return unless multiplicative_expression.operator.type == "*"
12695
12791
 
12696
- return unless multiplicative_expression.lhs_operand.constant?
12697
- return unless multiplicative_expression.rhs_operand.constant?
12792
+ return unless multiplicative_expression.lhs_operand.constant?(@enum_tbl)
12793
+ return unless multiplicative_expression.rhs_operand.constant?(@enum_tbl)
12698
12794
 
12699
12795
  return unless lhs_variable.type.scalar? && lhs_variable.type.unsigned?
12700
12796
  return unless rhs_variable.type.scalar? && rhs_variable.type.unsigned?
@@ -12715,6 +12811,7 @@ module C #:nodoc:
12715
12811
  super
12716
12812
  interp = context[:c_interpreter]
12717
12813
  interp.on_implicit_conv_performed += method(:check)
12814
+ @enum_tbl = interp.environment.enumerator_table
12718
12815
  end
12719
12816
 
12720
12817
  private
@@ -12730,7 +12827,7 @@ module C #:nodoc:
12730
12827
  expression = initializer_or_expression
12731
12828
  end
12732
12829
 
12733
- if expression && expression.constant? &&
12830
+ if expression && expression.constant?(@enum_tbl) &&
12734
12831
  original_variable.value.must_be_less_than?(ScalarValue.of(0))
12735
12832
  W(:W0742, expression.location)
12736
12833
  end
@@ -12742,6 +12839,7 @@ module C #:nodoc:
12742
12839
  super
12743
12840
  interp = context[:c_interpreter]
12744
12841
  interp.on_implicit_conv_performed += method(:check)
12842
+ @enum_tbl = interp.environment.enumerator_table
12745
12843
  end
12746
12844
 
12747
12845
  private
@@ -12755,7 +12853,7 @@ module C #:nodoc:
12755
12853
  expression = initializer_or_expression
12756
12854
  end
12757
12855
 
12758
- return unless expression.constant?
12856
+ return unless expression.constant?(@enum_tbl)
12759
12857
 
12760
12858
  orig_type = original_variable.type
12761
12859
  conv_type = result_variable.type
@@ -12786,40 +12884,41 @@ module C #:nodoc:
12786
12884
  interp.on_while_ctrlexpr_evaled += method(:check_while_statement)
12787
12885
  interp.on_for_ctrlexpr_evaled += method(:check_for_statement)
12788
12886
  interp.on_c99_for_ctrlexpr_evaled += method(:check_c99_for_statement)
12887
+ @enum_tbl = interp.environment.enumerator_table
12789
12888
  end
12790
12889
 
12791
12890
  private
12792
12891
  def check_if_statement(if_statement, ctrlexpr_value)
12793
12892
  ctrlexpr = if_statement.expression
12794
- if ctrlexpr.constant? && ctrlexpr_value.must_be_false?
12893
+ if ctrlexpr.constant?(@enum_tbl) && ctrlexpr_value.must_be_false?
12795
12894
  W(:W0744, ctrlexpr.location)
12796
12895
  end
12797
12896
  end
12798
12897
 
12799
12898
  def check_if_else_statement(if_else_statement, ctrlexpr_value)
12800
12899
  ctrlexpr = if_else_statement.expression
12801
- if ctrlexpr.constant? && ctrlexpr_value.must_be_false?
12900
+ if ctrlexpr.constant?(@enum_tbl) && ctrlexpr_value.must_be_false?
12802
12901
  W(:W0744, ctrlexpr.location)
12803
12902
  end
12804
12903
  end
12805
12904
 
12806
12905
  def check_while_statement(while_statement, ctrlexpr_value)
12807
12906
  ctrlexpr = while_statement.expression
12808
- if ctrlexpr.constant? && ctrlexpr_value.must_be_false?
12907
+ if ctrlexpr.constant?(@enum_tbl) && ctrlexpr_value.must_be_false?
12809
12908
  W(:W0744, ctrlexpr.location)
12810
12909
  end
12811
12910
  end
12812
12911
 
12813
12912
  def check_for_statement(for_statement, ctrlexpr_value)
12814
12913
  ctrlexpr = for_statement.condition_statement.expression
12815
- if ctrlexpr.constant? && ctrlexpr_value.must_be_false?
12914
+ if ctrlexpr.constant?(@enum_tbl) && ctrlexpr_value.must_be_false?
12816
12915
  W(:W0744, ctrlexpr.location)
12817
12916
  end
12818
12917
  end
12819
12918
 
12820
12919
  def check_c99_for_statement(c99_for_statement, ctrlexpr_value)
12821
12920
  ctrlexpr = c99_for_statement.condition_statement.expression
12822
- if ctrlexpr.constant? && ctrlexpr_value.must_be_false?
12921
+ if ctrlexpr.constant?(@enum_tbl) && ctrlexpr_value.must_be_false?
12823
12922
  W(:W0744, ctrlexpr.location)
12824
12923
  end
12825
12924
  end
@@ -13338,6 +13437,413 @@ module C #:nodoc:
13338
13437
  end
13339
13438
  end
13340
13439
 
13440
+ class W0787 < PassiveMessageDetection
13441
+ def initialize(context)
13442
+ super
13443
+ interp = context[:c_interpreter]
13444
+ interp.on_variable_declared += method(:check_object_declaration)
13445
+ interp.on_variable_defined += method(:check_object_declaration)
13446
+ interp.on_function_declared += method(:check_object_declaration)
13447
+ interp.on_function_started += method(:check_object_declaration)
13448
+ interp.on_typedef_declared += method(:check_typedef_declaration)
13449
+ interp.on_enum_declared += method(:check_enum_declaration)
13450
+ interp.on_block_started += method(:start_block)
13451
+ interp.on_block_ended += method(:end_block)
13452
+
13453
+ @object_decls_stack = [Hash.new { |hash, key| hash[key] = [] }]
13454
+ @typedef_decls_stack = [Hash.new { |hash, key| hash[key] = [] }]
13455
+ @enumerators_stack = [Hash.new(0)]
13456
+
13457
+ @object_decls_in_other_scope = Hash.new { |hash, key| hash[key] = [] }
13458
+ @typedef_decls_in_other_scope = Hash.new { |hash, key| hash[key] = [] }
13459
+ @enumerators_in_other_scope = Hash.new(0)
13460
+ end
13461
+
13462
+ private
13463
+ def check_object_declaration(declaration_or_definition, *)
13464
+ name = declaration_or_definition.identifier.value
13465
+ type = declaration_or_definition.type
13466
+
13467
+ same_name_object_decls = @object_decls_in_other_scope[name]
13468
+ unless same_name_object_decls.all? { |decl| decl.type == type }
13469
+ W(:W0787, declaration_or_definition.location, name)
13470
+ return
13471
+ end
13472
+
13473
+ same_name_typedef_decls = @typedef_decls_in_other_scope[name]
13474
+ unless same_name_typedef_decls.empty?
13475
+ W(:W0787, declaration_or_definition.location, name)
13476
+ return
13477
+ end
13478
+
13479
+ same_name_enumerators = @enumerators_in_other_scope[name]
13480
+ unless same_name_enumerators == 0
13481
+ W(:W0787, declaration_or_definition.location, name)
13482
+ return
13483
+ end
13484
+ ensure
13485
+ unless @object_decls_stack.empty?
13486
+ @object_decls_stack.last[name].push(declaration_or_definition)
13487
+ end
13488
+ end
13489
+
13490
+ def check_typedef_declaration(typedef_declaration)
13491
+ name = typedef_declaration.identifier.value
13492
+ type = typedef_declaration.type
13493
+
13494
+ same_name_object_decls = @object_decls_in_other_scope[name]
13495
+ unless same_name_object_decls.empty?
13496
+ W(:W0787, typedef_declaration.location, name)
13497
+ return
13498
+ end
13499
+
13500
+ same_name_typedef_decls = @typedef_decls_in_other_scope[name]
13501
+ unless same_name_typedef_decls.all? { |decl| decl.type == type }
13502
+ W(:W0787, typedef_declaration.location, name)
13503
+ return
13504
+ end
13505
+
13506
+ same_name_enumerators = @enumerators_in_other_scope[name]
13507
+ unless same_name_enumerators == 0
13508
+ W(:W0787, typedef_declaration.location, name)
13509
+ return
13510
+ end
13511
+ ensure
13512
+ unless @typedef_decls_stack.empty?
13513
+ @typedef_decls_stack.last[name].push(typedef_declaration)
13514
+ end
13515
+ end
13516
+
13517
+ def check_enum_declaration(enum_type_declaration)
13518
+ enum_type_declaration.enumerators.each { |enum| check_enumerator(enum) }
13519
+ end
13520
+
13521
+ def check_enumerator(enumerator)
13522
+ name = enumerator.identifier.value
13523
+
13524
+ same_name_object_decls = @object_decls_in_other_scope[name]
13525
+ unless same_name_object_decls.empty?
13526
+ W(:W0787, enumerator.location, name)
13527
+ return
13528
+ end
13529
+
13530
+ same_name_typedef_decls = @typedef_decls_in_other_scope[name]
13531
+ unless same_name_typedef_decls.empty?
13532
+ W(:W0787, enumerator.location, name)
13533
+ return
13534
+ end
13535
+
13536
+ same_name_enumerators = @enumerators_in_other_scope[name]
13537
+ unless same_name_enumerators == 0
13538
+ W(:W0787, enumerator.location, name)
13539
+ return
13540
+ end
13541
+ ensure
13542
+ unless @enumerators_stack.empty?
13543
+ @enumerators_stack.last[name] += 1
13544
+ end
13545
+ end
13546
+
13547
+ def start_block(compound_statement)
13548
+ @object_decls_stack.push(Hash.new { |hash, key| hash[key] = [] })
13549
+ @typedef_decls_stack.push(Hash.new { |hash, key| hash[key] = [] })
13550
+ @enumerators_stack.push(Hash.new(0))
13551
+ end
13552
+
13553
+ def end_block(compound_statement)
13554
+ unless @object_decls_stack.empty?
13555
+ @object_decls_stack.last.each do |name, decls|
13556
+ @object_decls_in_other_scope[name].concat(decls)
13557
+ end
13558
+ @object_decls_stack.pop
13559
+ end
13560
+
13561
+ unless @typedef_decls_stack.empty?
13562
+ @typedef_decls_stack.last.each do |name, decls|
13563
+ @typedef_decls_in_other_scope[name].concat(decls)
13564
+ end
13565
+ @typedef_decls_stack.pop
13566
+ end
13567
+
13568
+ unless @enumerators_stack.empty?
13569
+ @enumerators_stack.last.each do |name, decl_num|
13570
+ @enumerators_in_other_scope[name] += decl_num
13571
+ end
13572
+ end
13573
+ end
13574
+ end
13575
+
13576
+ class W0788 < PassiveMessageDetection
13577
+ def initialize(context)
13578
+ super
13579
+ interp = context[:c_interpreter]
13580
+ interp.on_variable_declared += method(:check_object_declaration)
13581
+ interp.on_variable_defined += method(:check_object_declaration)
13582
+ interp.on_function_declared += method(:check_object_declaration)
13583
+ interp.on_function_started += method(:check_object_declaration)
13584
+ interp.on_typedef_declared += method(:check_typedef_declaration)
13585
+ interp.on_enum_declared += method(:check_enum_declaration)
13586
+ interp.on_block_started += method(:start_block)
13587
+ interp.on_block_ended += method(:end_block)
13588
+
13589
+ @object_decls_stack = [Hash.new { |hash, key| hash[key] = [] }]
13590
+ @typedef_decls_stack = [Hash.new { |hash, key| hash[key] = [] }]
13591
+ @enumerators_stack = [Hash.new(0)]
13592
+ end
13593
+
13594
+ private
13595
+ def check_object_declaration(declaration_or_definition, *)
13596
+ name = declaration_or_definition.identifier.value
13597
+ type = declaration_or_definition.type
13598
+
13599
+ unless @object_decls_stack.empty?
13600
+ same_name_object_decls = @object_decls_stack.last[name]
13601
+ unless same_name_object_decls.all? { |decl| decl.type == type }
13602
+ W(:W0788, declaration_or_definition.location, name)
13603
+ return
13604
+ end
13605
+ end
13606
+
13607
+ unless @typedef_decls_stack.empty?
13608
+ same_name_typedef_decls = @typedef_decls_stack.last[name]
13609
+ unless same_name_typedef_decls.empty?
13610
+ W(:W0788, declaration_or_definition.location, name)
13611
+ return
13612
+ end
13613
+ end
13614
+
13615
+ unless @enumerators_stack.empty?
13616
+ same_name_enumerators = @enumerators_stack.last[name]
13617
+ unless same_name_enumerators == 0
13618
+ W(:W0788, declaration_or_definition.location, name)
13619
+ return
13620
+ end
13621
+ end
13622
+ ensure
13623
+ unless @object_decls_stack.empty?
13624
+ @object_decls_stack.last[name].push(declaration_or_definition)
13625
+ end
13626
+ end
13627
+
13628
+ def check_typedef_declaration(typedef_declaration)
13629
+ name = typedef_declaration.identifier.value
13630
+ type = typedef_declaration.type
13631
+
13632
+ unless @object_decls_stack.empty?
13633
+ same_name_object_decls = @object_decls_stack.last[name]
13634
+ unless same_name_object_decls.empty?
13635
+ W(:W0788, typedef_declaration.location, name)
13636
+ return
13637
+ end
13638
+ end
13639
+
13640
+ unless @typedef_decls_stack.empty?
13641
+ same_name_typedef_decls = @typedef_decls_stack.last[name]
13642
+ unless same_name_typedef_decls.all? { |decl| decl.type == type }
13643
+ W(:W0788, typedef_declaration.location, name)
13644
+ return
13645
+ end
13646
+ end
13647
+
13648
+ unless @enumerators_stack.empty?
13649
+ same_name_enumerators = @enumerators_stack.last[name]
13650
+ unless same_name_enumerators == 0
13651
+ W(:W0788, typedef_declaration.location, name)
13652
+ return
13653
+ end
13654
+ end
13655
+ ensure
13656
+ unless @typedef_decls_stack.empty?
13657
+ @typedef_decls_stack.last[name].push(typedef_declaration)
13658
+ end
13659
+ end
13660
+
13661
+ def check_enum_declaration(enum_type_declaration)
13662
+ enum_type_declaration.enumerators.each { |enum| check_enumerator(enum) }
13663
+ end
13664
+
13665
+ def check_enumerator(enumerator)
13666
+ name = enumerator.identifier.value
13667
+
13668
+ unless @object_decls_stack.empty?
13669
+ same_name_object_decls = @object_decls_stack.last[name]
13670
+ unless same_name_object_decls.empty?
13671
+ W(:W0788, enumerator.location, name)
13672
+ return
13673
+ end
13674
+ end
13675
+
13676
+ unless @typedef_decls_stack.empty?
13677
+ same_name_typedef_decls = @typedef_decls_stack.last[name]
13678
+ unless same_name_typedef_decls.empty?
13679
+ W(:W0788, enumerator.location, name)
13680
+ return
13681
+ end
13682
+ end
13683
+
13684
+ unless @enumerators_stack.empty?
13685
+ same_name_enumerators = @enumerators_stack.last[name]
13686
+ unless same_name_enumerators == 0
13687
+ W(:W0788, enumerator.location, name)
13688
+ return
13689
+ end
13690
+ end
13691
+ ensure
13692
+ unless @enumerators_stack.empty?
13693
+ @enumerators_stack.last[name] += 1
13694
+ end
13695
+ end
13696
+
13697
+ def start_block(compound_statement)
13698
+ @object_decls_stack.push(Hash.new { |hash, key| hash[key] = [] })
13699
+ @typedef_decls_stack.push(Hash.new { |hash, key| hash[key] = [] })
13700
+ @enumerators_stack.push(Hash.new(0))
13701
+ end
13702
+
13703
+ def end_block(compound_statement)
13704
+ @object_decls_stack.pop
13705
+ @typedef_decls_stack.pop
13706
+ @enumerators_stack.pop
13707
+ end
13708
+ end
13709
+
13710
+ class W0789 < PassiveMessageDetection
13711
+ def initialize(context)
13712
+ super
13713
+ interp = context[:c_interpreter]
13714
+ interp.on_variable_declared += method(:check_object_declaration)
13715
+ interp.on_variable_defined += method(:check_object_declaration)
13716
+ interp.on_function_declared += method(:check_object_declaration)
13717
+ interp.on_function_started += method(:check_object_declaration)
13718
+ interp.on_typedef_declared += method(:check_typedef_declaration)
13719
+ interp.on_enum_declared += method(:check_enum_declaration)
13720
+ interp.on_block_started += method(:start_block)
13721
+ interp.on_block_ended += method(:end_block)
13722
+
13723
+ @object_decls_stack = [Hash.new { |hash, key| hash[key] = [] }]
13724
+ @typedef_decls_stack = [Hash.new { |hash, key| hash[key] = [] }]
13725
+ @enumerators_stack = [Hash.new(0)]
13726
+ end
13727
+
13728
+ private
13729
+ def check_object_declaration(declaration_or_definition, *)
13730
+ name = declaration_or_definition.identifier.value
13731
+ type = declaration_or_definition.type
13732
+
13733
+ same_name_object_decls =
13734
+ merge_same_name_object_decls(name, @object_decls_stack[0..-2])
13735
+ unless same_name_object_decls.all? { |decl| decl.type == type }
13736
+ W(:W0789, declaration_or_definition.location, name)
13737
+ return
13738
+ end
13739
+
13740
+ same_name_typedef_decls =
13741
+ merge_same_name_typedef_decls(name, @typedef_decls_stack[0..-2])
13742
+ unless same_name_typedef_decls.empty?
13743
+ W(:W0789, declaration_or_definition.location, name)
13744
+ return
13745
+ end
13746
+
13747
+ same_name_enumerators =
13748
+ merge_same_name_enumerators(name, @enumerators_stack[0..-2])
13749
+ unless same_name_enumerators == 0
13750
+ W(:W0789, declaration_or_definition.location, name)
13751
+ return
13752
+ end
13753
+ ensure
13754
+ unless @object_decls_stack.empty?
13755
+ @object_decls_stack.last[name].push(declaration_or_definition)
13756
+ end
13757
+ end
13758
+
13759
+ def check_typedef_declaration(typedef_declaration)
13760
+ name = typedef_declaration.identifier.value
13761
+ type = typedef_declaration.type
13762
+
13763
+ same_name_object_decls =
13764
+ merge_same_name_object_decls(name, @object_decls_stack[0..-2])
13765
+ unless same_name_object_decls.empty?
13766
+ W(:W0789, typedef_declaration.location, name)
13767
+ return
13768
+ end
13769
+
13770
+ same_name_typedef_decls =
13771
+ merge_same_name_typedef_decls(name, @typedef_decls_stack[0..-2])
13772
+ unless same_name_typedef_decls.all? { |decl| decl.type == type }
13773
+ W(:W0789, typedef_declaration.location, name)
13774
+ return
13775
+ end
13776
+
13777
+ same_name_enumerators =
13778
+ merge_same_name_enumerators(name, @enumerators_stack[0..-2])
13779
+ unless same_name_enumerators == 0
13780
+ W(:W0789, typedef_declaration.location, name)
13781
+ return
13782
+ end
13783
+ ensure
13784
+ unless @typedef_decls_stack.empty?
13785
+ @typedef_decls_stack.last[name].push(typedef_declaration)
13786
+ end
13787
+ end
13788
+
13789
+ def check_enum_declaration(enum_type_declaration)
13790
+ enum_type_declaration.enumerators.each { |enum| check_enumerator(enum) }
13791
+ end
13792
+
13793
+ def check_enumerator(enumerator)
13794
+ name = enumerator.identifier.value
13795
+
13796
+ same_name_object_decls =
13797
+ merge_same_name_object_decls(name, @object_decls_stack[0..-2])
13798
+ unless same_name_object_decls.empty?
13799
+ W(:W0789, enumerator.location, name)
13800
+ return
13801
+ end
13802
+
13803
+ same_name_typedef_decls =
13804
+ merge_same_name_typedef_decls(name, @typedef_decls_stack[0..-2])
13805
+ unless same_name_typedef_decls.empty?
13806
+ W(:W0789, enumerator.location, name)
13807
+ return
13808
+ end
13809
+
13810
+ same_name_enumerators =
13811
+ merge_same_name_enumerators(name, @enumerators_stack[0..-2])
13812
+ unless same_name_enumerators == 0
13813
+ W(:W0789, enumerator.location, name)
13814
+ return
13815
+ end
13816
+ ensure
13817
+ unless @enumerators_stack.empty?
13818
+ @enumerators_stack.last[name] += 1
13819
+ end
13820
+ end
13821
+
13822
+ def start_block(compound_statement)
13823
+ @object_decls_stack.push(Hash.new { |hash, key| hash[key] = [] })
13824
+ @typedef_decls_stack.push(Hash.new { |hash, key| hash[key] = [] })
13825
+ @enumerators_stack.push(Hash.new(0))
13826
+ end
13827
+
13828
+ def end_block(compound_statement)
13829
+ @object_decls_stack.pop
13830
+ @typedef_decls_stack.pop
13831
+ @enumerators_stack.pop
13832
+ end
13833
+
13834
+ def merge_same_name_object_decls(name, scopes)
13835
+ scopes.each_with_object([]) { |hash, result| result.concat(hash[name]) }
13836
+ end
13837
+
13838
+ def merge_same_name_typedef_decls(name, scopes)
13839
+ scopes.each_with_object([]) { |hash, result| result.concat(hash[name]) }
13840
+ end
13841
+
13842
+ def merge_same_name_enumerators(name, scopes)
13843
+ scopes.reduce(0) { |result, hash| result + hash[name] }
13844
+ end
13845
+ end
13846
+
13341
13847
  class W0790 < PassiveMessageDetection
13342
13848
  def initialize(context)
13343
13849
  super
@@ -14136,6 +14642,282 @@ module C #:nodoc:
14136
14642
  end
14137
14643
  end
14138
14644
 
14645
+ class W1053 < PassiveMessageDetection
14646
+ def initialize(context)
14647
+ super
14648
+ interp = context[:c_interpreter]
14649
+ interp.on_function_call_expr_evaled += method(:check)
14650
+ @enum_tbl = interp.environment.enumerator_table
14651
+ end
14652
+
14653
+ private
14654
+ def check(expression, function, arg_variables, result_variable)
14655
+ args = arg_variables.zip(function.type.parameter_types)
14656
+ args.each_with_index do |(arg_variable, param_type), index|
14657
+ next unless param_type && param_type.enum?
14658
+
14659
+ arg_expr = expression.argument_expressions[index]
14660
+ next unless arg_expr.constant?(@enum_tbl)
14661
+
14662
+ unless arg_variable.type.enum?
14663
+ W(:W1053, arg_expr.location)
14664
+ end
14665
+ end
14666
+ end
14667
+ end
14668
+
14669
+ class W1054 < PassiveMessageDetection
14670
+ def initialize(context)
14671
+ super
14672
+ interp = context[:c_interpreter]
14673
+ interp.on_assignment_expr_evaled += method(:check)
14674
+ end
14675
+
14676
+ private
14677
+ def check(expression, lhs_variable, rhs_variable)
14678
+ return unless lhs_variable.type.enum?
14679
+ W(:W1054, expression.location) unless rhs_variable.type.enum?
14680
+ end
14681
+ end
14682
+
14683
+ class W1055 < PassiveMessageDetection
14684
+ def initialize(context)
14685
+ super
14686
+ interp = context[:c_interpreter]
14687
+ interp.on_function_started += method(:start_function)
14688
+ interp.on_function_ended += method(:end_function)
14689
+ interp.on_return_stmt_evaled += method(:check)
14690
+ @current_function = nil
14691
+ end
14692
+
14693
+ private
14694
+ def start_function(function_definition)
14695
+ @current_function = function_definition
14696
+ end
14697
+
14698
+ def end_function(function_definition)
14699
+ @current_function = nil
14700
+ end
14701
+
14702
+ def check(return_statement, result_variable)
14703
+ return unless @current_function && result_variable
14704
+
14705
+ return unless return_type = @current_function.type.return_type
14706
+ return unless return_type.enum?
14707
+
14708
+ unless result_variable.type.enum?
14709
+ W(:W1055, return_statement.expression.location)
14710
+ end
14711
+ end
14712
+ end
14713
+
14714
+ class W1056 < PassiveMessageDetection
14715
+ def initialize(context)
14716
+ super
14717
+ interp = context[:c_interpreter]
14718
+ interp.on_function_call_expr_evaled += method(:check)
14719
+ @enum_tbl = interp.environment.enumerator_table
14720
+ end
14721
+
14722
+ private
14723
+ def check(expression, function, arg_variables, result_variable)
14724
+ args = arg_variables.zip(function.type.parameter_types)
14725
+ args.each_with_index do |(arg_variable, param_type), index|
14726
+ next unless param_type && param_type.enum?
14727
+
14728
+ arg_expr = expression.argument_expressions[index]
14729
+ next if arg_expr.constant?(@enum_tbl)
14730
+
14731
+ if arg_variable.type.enum?
14732
+ unless arg_variable.type.same_as?(param_type)
14733
+ W(:W1056, arg_expr.location)
14734
+ end
14735
+ end
14736
+ end
14737
+ end
14738
+ end
14739
+
14740
+ class W1057 < PassiveMessageDetection
14741
+ def initialize(context)
14742
+ super
14743
+ interp = context[:c_interpreter]
14744
+ interp.on_assignment_expr_evaled += method(:check)
14745
+ @enum_tbl = interp.environment.enumerator_table
14746
+ end
14747
+
14748
+ private
14749
+ def check(expression, lhs_variable, rhs_variable)
14750
+ return unless lhs_variable.type.enum?
14751
+ return if expression.rhs_operand.constant?(@enum_tbl)
14752
+
14753
+ if rhs_variable.type.enum?
14754
+ unless lhs_variable.type.same_as?(rhs_variable.type)
14755
+ W(:W1057, expression.location)
14756
+ end
14757
+ end
14758
+ end
14759
+ end
14760
+
14761
+ class W1058 < PassiveMessageDetection
14762
+ def initialize(context)
14763
+ super
14764
+ interp = context[:c_interpreter]
14765
+ interp.on_function_started += method(:start_function)
14766
+ interp.on_function_ended += method(:end_function)
14767
+ interp.on_return_stmt_evaled += method(:check)
14768
+ @enum_tbl = interp.environment.enumerator_table
14769
+ @current_function = nil
14770
+ end
14771
+
14772
+ private
14773
+ def start_function(function_definition)
14774
+ @current_function = function_definition
14775
+ end
14776
+
14777
+ def end_function(function_definition)
14778
+ @current_function = nil
14779
+ end
14780
+
14781
+ def check(return_statement, result_variable)
14782
+ return unless @current_function && result_variable
14783
+
14784
+ return unless return_type = @current_function.type.return_type
14785
+ return unless return_type.enum?
14786
+ return if return_statement.expression.constant?(@enum_tbl)
14787
+
14788
+ if result_variable.type.enum?
14789
+ unless return_type.same_as?(result_variable.type)
14790
+ W(:W1058, return_statement.expression.location)
14791
+ end
14792
+ end
14793
+ end
14794
+ end
14795
+
14796
+ class W1059 < PassiveMessageDetection
14797
+ def initialize(context)
14798
+ super
14799
+ interp = context[:c_interpreter]
14800
+ interp.on_function_call_expr_evaled += method(:check)
14801
+ @enum_tbl = interp.environment.enumerator_table
14802
+ end
14803
+
14804
+ private
14805
+ def check(expression, function, arg_variables, result_variable)
14806
+ args = arg_variables.zip(function.type.parameter_types)
14807
+ args.each_with_index do |(arg_variable, param_type), index|
14808
+ next if param_type.nil? || param_type.enum?
14809
+
14810
+ if arg_variable.type.enum?
14811
+ W(:W1059, expression.argument_expressions[index].location)
14812
+ end
14813
+ end
14814
+ end
14815
+ end
14816
+
14817
+ class W1060 < PassiveMessageDetection
14818
+ def initialize(context)
14819
+ super
14820
+ interp = context[:c_interpreter]
14821
+ interp.on_function_started += method(:start_function)
14822
+ interp.on_function_ended += method(:end_function)
14823
+ interp.on_return_stmt_evaled += method(:check)
14824
+ @enum_tbl = interp.environment.enumerator_table
14825
+ @current_function = nil
14826
+ end
14827
+
14828
+ private
14829
+ def start_function(function_definition)
14830
+ @current_function = function_definition
14831
+ end
14832
+
14833
+ def end_function(function_definition)
14834
+ @current_function = nil
14835
+ end
14836
+
14837
+ def check(return_statement, result_variable)
14838
+ return unless @current_function && result_variable
14839
+
14840
+ return unless return_type = @current_function.type.return_type
14841
+ return if return_type.enum?
14842
+
14843
+ if result_variable.type.enum?
14844
+ W(:W1060, return_statement.expression.location)
14845
+ end
14846
+ end
14847
+ end
14848
+
14849
+ class W1061 < PassiveMessageDetection
14850
+ def initialize(context)
14851
+ super
14852
+ interp = context[:c_interpreter]
14853
+ interp.on_function_call_expr_evaled += method(:check)
14854
+ @enum_tbl = interp.environment.enumerator_table
14855
+ end
14856
+
14857
+ private
14858
+ def check(expression, function, arg_variables, result_variable)
14859
+ args = arg_variables.zip(function.type.parameter_types)
14860
+ args.each_with_index do |(arg_variable, param_type), index|
14861
+ next unless param_type && param_type.enum?
14862
+
14863
+ arg_expr = expression.argument_expressions[index]
14864
+ next if arg_expr.constant?(@enum_tbl)
14865
+
14866
+ W(:W1061, arg_expr.location) unless arg_variable.type.enum?
14867
+ end
14868
+ end
14869
+ end
14870
+
14871
+ class W1062 < PassiveMessageDetection
14872
+ def initialize(context)
14873
+ super
14874
+ interp = context[:c_interpreter]
14875
+ interp.on_assignment_expr_evaled += method(:check)
14876
+ @enum_tbl = interp.environment.enumerator_table
14877
+ end
14878
+
14879
+ private
14880
+ def check(expression, lhs_variable, rhs_variable)
14881
+ return unless lhs_variable.type.enum?
14882
+ return if expression.rhs_operand.constant?(@enum_tbl)
14883
+
14884
+ W(:W1062, expression.location) unless rhs_variable.type.enum?
14885
+ end
14886
+ end
14887
+
14888
+ class W1063 < PassiveMessageDetection
14889
+ def initialize(context)
14890
+ super
14891
+ interp = context[:c_interpreter]
14892
+ interp.on_function_started += method(:start_function)
14893
+ interp.on_function_ended += method(:end_function)
14894
+ interp.on_return_stmt_evaled += method(:check)
14895
+ @enum_tbl = interp.environment.enumerator_table
14896
+ @current_function = nil
14897
+ end
14898
+
14899
+ private
14900
+ def start_function(function_definition)
14901
+ @current_function = function_definition
14902
+ end
14903
+
14904
+ def end_function(function_definition)
14905
+ @current_function = nil
14906
+ end
14907
+
14908
+ def check(return_statement, result_variable)
14909
+ return unless @current_function && result_variable
14910
+
14911
+ return unless return_type = @current_function.type.return_type
14912
+ return unless return_type.enum?
14913
+ return if return_statement.expression.constant?(@enum_tbl)
14914
+
14915
+ unless result_variable.type.enum?
14916
+ W(:W1063, return_statement.expression.location)
14917
+ end
14918
+ end
14919
+ end
14920
+
14139
14921
  class W1064 < W0731
14140
14922
  private
14141
14923
  def check(case_labeled_statement, ctrlexpr_result)