adlint 1.4.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
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)