adlint 1.8.10 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/ChangeLog +261 -3
  2. data/MANIFEST +25 -1
  3. data/NEWS +25 -5
  4. data/Rakefile +11 -0
  5. data/TODO +0 -1
  6. data/etc/mesg.d/en_US/messages.yml +1 -1
  7. data/etc/mesg.d/ja_JP/messages.yml +1 -1
  8. data/features/message_detection/W0001.feature +41 -0
  9. data/features/message_detection/W0002.feature +68 -0
  10. data/features/message_detection/W0003.feature +134 -0
  11. data/features/message_detection/W0007.feature +264 -0
  12. data/features/message_detection/W0010.feature +75 -0
  13. data/features/message_detection/W0013.feature +189 -0
  14. data/features/message_detection/W0109.feature +50 -0
  15. data/features/message_detection/W0583.feature +30 -0
  16. data/features/message_detection/W0606.feature +20 -0
  17. data/features/message_detection/W0698.feature +20 -0
  18. data/features/message_detection/W0699.feature +21 -0
  19. data/features/message_detection/W0703.feature +73 -0
  20. data/features/message_detection/W0716.feature +67 -0
  21. data/features/message_detection/W0717.feature +64 -0
  22. data/features/message_detection/W0718.feature +64 -0
  23. data/features/message_detection/W0723.feature +18 -0
  24. data/features/message_detection/W1031.feature +328 -0
  25. data/features/step_definitions/message_detection_steps.rb +45 -0
  26. data/features/support/env.rb +58 -0
  27. data/lib/adlint/c/branch.rb +16 -23
  28. data/lib/adlint/c/code.rb +1 -12
  29. data/lib/adlint/c/conv.rb +4 -4
  30. data/lib/adlint/c/ctrlexpr.rb +10 -6
  31. data/lib/adlint/c/domain.rb +2 -2
  32. data/lib/adlint/c/expr.rb +11 -33
  33. data/lib/adlint/c/format.rb +6 -6
  34. data/lib/adlint/c/interp.rb +137 -80
  35. data/lib/adlint/c/mediator.rb +5 -2
  36. data/lib/adlint/c/message.rb +123 -140
  37. data/lib/adlint/c/message_shima.rb +44 -0
  38. data/lib/adlint/c/object.rb +93 -26
  39. data/lib/adlint/c/option.rb +53 -0
  40. data/lib/adlint/c/phase.rb +4 -1
  41. data/lib/adlint/c/type.rb +112 -46
  42. data/lib/adlint/c.rb +1 -0
  43. data/lib/adlint/version.rb +3 -3
  44. data/share/doc/developers_guide_ja.html +3 -3
  45. data/share/doc/developers_guide_ja.texi +1 -1
  46. data/share/doc/users_guide_en.html +35 -28
  47. data/share/doc/users_guide_en.texi +30 -22
  48. data/share/doc/users_guide_ja.html +35 -31
  49. data/share/doc/users_guide_ja.texi +30 -24
  50. data/spec/adlint/c/type_spec.rb +110 -0
  51. data/spec/conf.d/default_traits.yml +216 -0
  52. data/spec/conf.d/empty_cinit.h +11 -0
  53. data/spec/conf.d/empty_pinit.h +11 -0
  54. data/spec/spec_helper.rb +49 -0
  55. metadata +27 -3
  56. data/spec/MUST_WRITE_SPECS_WITH_RSPEC +0 -0
@@ -35,6 +35,7 @@ require "adlint/traits"
35
35
  require "adlint/monitor"
36
36
  require "adlint/c/syntax"
37
37
  require "adlint/c/format"
38
+ require "adlint/c/option"
38
39
  require "adlint/c/util"
39
40
  require "adlint/cpp/syntax"
40
41
 
@@ -659,8 +660,8 @@ module C #:nodoc:
659
660
  end
660
661
  end
661
662
 
662
- def check_conditional(conditional_expression, condition_variable, result)
663
- unless condition_variable.type.scalar?
663
+ def check_conditional(conditional_expression, controlling_variable, result)
664
+ unless controlling_variable.type.scalar?
664
665
  W(:W0035, conditional_expression.location)
665
666
  end
666
667
  end
@@ -1160,7 +1161,7 @@ module C #:nodoc:
1160
1161
  interp.on_variable_declared += method(:add_variable)
1161
1162
  interp.on_variable_defined += method(:add_variable)
1162
1163
  interp.on_function_declared += method(:add_function)
1163
- interp.on_function_started += method(:add_function)
1164
+ interp.on_function_defined += method(:add_function)
1164
1165
  interp.on_translation_unit_ended += method(:check)
1165
1166
  @identifiers = Hash.new { |hash, key| hash[key] = [] }
1166
1167
  end
@@ -2493,7 +2494,7 @@ module C #:nodoc:
2493
2494
  interp = context[:c_interpreter]
2494
2495
  interp.on_function_declared += method(:declare_function)
2495
2496
  interp.on_variable_declared += method(:declare_variable)
2496
- interp.on_function_started += method(:check_function)
2497
+ interp.on_function_defined += method(:check_function)
2497
2498
  interp.on_variable_defined += method(:check_variable)
2498
2499
  @target_fpath = context[:sources].first.fpath
2499
2500
  @external_symbols = Set.new
@@ -4108,10 +4109,10 @@ module C #:nodoc:
4108
4109
  def check_return_statement(return_statement, result_variable)
4109
4110
  return unless @current_function
4110
4111
  return if from_type == to_type
4111
-
4112
4112
  return unless result_variable
4113
- if from_type.same_as?(result_variable.type) &&
4114
- to_type.same_as?(@current_function.type.return_type)
4113
+
4114
+ if result_variable.type.same_as?(from_type) &&
4115
+ @current_function.type.return_type.same_as?(to_type)
4115
4116
  W(message_id, return_statement.location, @current_function.name)
4116
4117
  end
4117
4118
  end
@@ -6868,7 +6869,7 @@ module C #:nodoc:
6868
6869
  super
6869
6870
  interp = context[:c_interpreter]
6870
6871
  interp.on_variable_defined += method(:check_variable)
6871
- interp.on_function_started += method(:check_function)
6872
+ interp.on_function_defined += method(:check_function)
6872
6873
  @target_fpath = context[:sources].first.fpath
6873
6874
  end
6874
6875
 
@@ -8654,6 +8655,12 @@ module C #:nodoc:
8654
8655
  @group_depth -= 1
8655
8656
  end
8656
8657
 
8658
+ def visit_conditional_expression(node)
8659
+ @group_depth += 1
8660
+ super
8661
+ @group_depth -= 1
8662
+ end
8663
+
8657
8664
  def visit_array_subscript_expression(node)
8658
8665
  AmbiguousExpressionDetector.new(@context, node.array_subscript).execute
8659
8666
  end
@@ -8785,6 +8792,7 @@ module C #:nodoc:
8785
8792
  def initialize(context, expression)
8786
8793
  @context = context
8787
8794
  @expression = expression
8795
+ @already_warned = false
8788
8796
  @group_depth = 0
8789
8797
  @ungrouped_binary_expr = 0
8790
8798
  end
@@ -8800,61 +8808,73 @@ module C #:nodoc:
8800
8808
  end
8801
8809
 
8802
8810
  def visit_multiplicative_expression(node)
8803
- super unless check_binary_expression
8811
+ check_binary_expression
8812
+ super
8804
8813
  end
8805
8814
 
8806
8815
  def visit_additive_expression(node)
8807
- super unless check_binary_expression
8816
+ check_binary_expression
8817
+ super
8808
8818
  end
8809
8819
 
8810
8820
  def visit_shift_expression(node)
8811
- super unless check_binary_expression
8821
+ check_binary_expression
8822
+ super
8812
8823
  end
8813
8824
 
8814
8825
  def visit_relational_expression(node)
8815
- super unless check_binary_expression
8826
+ check_binary_expression
8827
+ super
8816
8828
  end
8817
8829
 
8818
8830
  def visit_equality_expression(node)
8819
- super unless check_binary_expression
8831
+ check_binary_expression
8832
+ super
8820
8833
  end
8821
8834
 
8822
8835
  def visit_and_expression(node)
8823
- super unless check_binary_expression
8836
+ check_binary_expression
8837
+ super
8824
8838
  end
8825
8839
 
8826
8840
  def visit_exclusive_or_expression(node)
8827
- super unless check_binary_expression
8841
+ check_binary_expression
8842
+ super
8828
8843
  end
8829
8844
 
8830
8845
  def visit_inclusive_or_expression(node)
8831
- super unless check_binary_expression
8846
+ check_binary_expression
8847
+ super
8832
8848
  end
8833
8849
 
8834
8850
  def visit_logical_and_expression(node)
8835
- super unless check_binary_expression
8851
+ check_binary_expression
8852
+ super
8836
8853
  end
8837
8854
 
8838
8855
  def visit_logical_or_expression(node)
8839
- super unless check_binary_expression
8856
+ check_binary_expression
8857
+ super
8840
8858
  end
8841
8859
 
8842
8860
  def visit_simple_assignment_expression(node)
8843
- super unless check_binary_expression
8861
+ check_binary_expression
8862
+ super
8844
8863
  end
8845
8864
 
8846
8865
  def visit_compound_assignment_expression(node)
8847
- super unless check_binary_expression
8866
+ check_binary_expression
8867
+ super
8848
8868
  end
8849
8869
 
8850
8870
  private
8851
8871
  def check_binary_expression
8852
8872
  @ungrouped_binary_expr += 1 if @group_depth == 0
8853
- if include_ambiguous_expr?
8854
- W(:W0501, @expression.head_location)
8855
- true
8856
- else
8857
- false
8873
+ unless @already_warned
8874
+ if include_ambiguous_expr?
8875
+ W(:W0501, @expression.head_location)
8876
+ @already_warned = true
8877
+ end
8858
8878
  end
8859
8879
  end
8860
8880
 
@@ -10372,21 +10392,12 @@ module C #:nodoc:
10372
10392
  return unless function.named?
10373
10393
  return if function.type.have_va_list?
10374
10394
 
10375
- param_types = function.type.parameter_types.map { |type|
10376
- type.void? ? nil : type.unqualify
10377
- }.compact
10395
+ param_types = function.type.parameter_types.reject { |type| type.void? }
10378
10396
 
10379
10397
  @function_calls[function.name].each do |expr, arg_types|
10380
10398
  if arg_types.size == param_types.size
10381
10399
  conformed = arg_types.zip(param_types).all? { |atype, ptype|
10382
- case
10383
- when atype.array? && ptype.array?,
10384
- atype.array? && ptype.pointer?,
10385
- atype.pointer? && ptype.array?
10386
- atype.base_type == ptype.base_type
10387
- else
10388
- atype == ptype
10389
- end
10400
+ atype.convertible?(ptype)
10390
10401
  }
10391
10402
  else
10392
10403
  conformed = false
@@ -10398,7 +10409,7 @@ module C #:nodoc:
10398
10409
 
10399
10410
  def call_function(expression, function, arg_variables, result_variable)
10400
10411
  if function.named?
10401
- arg_types = arg_variables.map { |var| var.type.unqualify }
10412
+ arg_types = arg_variables.map { |var| var.type }
10402
10413
  @function_calls[function.name].push([expression, arg_types])
10403
10414
  end
10404
10415
  end
@@ -10409,7 +10420,7 @@ module C #:nodoc:
10409
10420
  super
10410
10421
  interp = context[:c_interpreter]
10411
10422
  interp.on_function_call_expr_evaled += method(:call_function)
10412
- interp.on_function_started += method(:check)
10423
+ interp.on_function_defined += method(:check)
10413
10424
  @function_calls = Hash.new { |hash, key| hash[key] = [] }
10414
10425
  end
10415
10426
 
@@ -10418,21 +10429,12 @@ module C #:nodoc:
10418
10429
  return unless function.named?
10419
10430
  return if function.type.have_va_list?
10420
10431
 
10421
- param_types = function.type.parameter_types.map { |type|
10422
- type.void? ? nil : type.unqualify
10423
- }.compact
10432
+ param_types = function.type.parameter_types.reject { |type| type.void? }
10424
10433
 
10425
10434
  @function_calls[function.name].each do |expr, arg_types|
10426
10435
  if arg_types.size == param_types.size
10427
10436
  conformed = arg_types.zip(param_types).all? { |atype, ptype|
10428
- case
10429
- when atype.array? && ptype.array?,
10430
- atype.array? && ptype.pointer?,
10431
- atype.pointer? && ptype.array?
10432
- atype.base_type == ptype.base_type
10433
- else
10434
- atype == ptype
10435
- end
10437
+ atype.convertible?(ptype)
10436
10438
  }
10437
10439
  else
10438
10440
  conformed = false
@@ -10444,7 +10446,7 @@ module C #:nodoc:
10444
10446
 
10445
10447
  def call_function(expression, function, arg_variables, result_variable)
10446
10448
  if function.named?
10447
- arg_types = arg_variables.map { |var| var.type.unqualify }
10449
+ arg_types = arg_variables.map { |var| var.type }
10448
10450
  @function_calls[function.name].push([expression, arg_types])
10449
10451
  end
10450
10452
  end
@@ -10463,23 +10465,12 @@ module C #:nodoc:
10463
10465
  return unless kandr_style_definition_of(function)
10464
10466
  return if function.type.have_va_list?
10465
10467
 
10466
- arg_types = arg_variables.map { |var| var.type.unqualify }
10467
- param_types = function.type.parameter_types.map { |type|
10468
- type.void? ? nil : type.unqualify
10469
- }.compact
10468
+ arg_types = arg_variables.map { |var| var.type }
10469
+ param_types = function.type.parameter_types.reject { |type| type.void? }
10470
10470
 
10471
10471
  if arg_types.size == param_types.size
10472
10472
  arg_types.zip(param_types).each_with_index do |(atype, ptype), index|
10473
- conformed = case
10474
- when atype.array? && ptype.array?,
10475
- atype.array? && ptype.pointer?,
10476
- atype.pointer? && ptype.array?
10477
- atype.base_type == ptype.base_type
10478
- else
10479
- atype == ptype
10480
- end
10481
-
10482
- unless conformed
10473
+ unless atype.convertible?(ptype)
10483
10474
  W(:W0584,
10484
10475
  expression.argument_expressions[index].location, index + 1)
10485
10476
  end
@@ -11132,7 +11123,7 @@ module C #:nodoc:
11132
11123
  interp.on_variable_defined += method(:check)
11133
11124
  interp.on_variable_declared += method(:check)
11134
11125
  interp.on_function_declared += method(:check)
11135
- interp.on_function_started += method(:check)
11126
+ interp.on_function_defined += method(:check)
11136
11127
  @typedef_types = {}
11137
11128
  end
11138
11129
 
@@ -11245,7 +11236,7 @@ module C #:nodoc:
11245
11236
  def initialize(context)
11246
11237
  super
11247
11238
  interp = context[:c_interpreter]
11248
- interp.on_function_started += method(:define_function)
11239
+ interp.on_function_defined += method(:define_function)
11249
11240
  interp.on_function_referred += method(:refer_function)
11250
11241
  interp.on_translation_unit_ended += method(:check)
11251
11242
  @static_functions = {}
@@ -12166,7 +12157,7 @@ module C #:nodoc:
12166
12157
  interp.on_variable_declared += method(:declare_variable)
12167
12158
  interp.on_enum_declared += method(:declare_enum)
12168
12159
  interp.on_typedef_declared += method(:declare_typedef)
12169
- interp.on_function_started += method(:define_function)
12160
+ interp.on_function_defined += method(:define_function)
12170
12161
  interp.on_parameter_defined += method(:define_parameter)
12171
12162
  interp.on_block_started += method(:enter_scope)
12172
12163
  interp.on_block_ended += method(:leave_scope)
@@ -13543,7 +13534,7 @@ module C #:nodoc:
13543
13534
  interp.on_variable_declared += method(:check_object_declaration)
13544
13535
  interp.on_variable_defined += method(:check_object_declaration)
13545
13536
  interp.on_function_declared += method(:check_object_declaration)
13546
- interp.on_function_started += method(:check_object_declaration)
13537
+ interp.on_function_defined += method(:check_object_declaration)
13547
13538
  interp.on_typedef_declared += method(:check_typedef_declaration)
13548
13539
  interp.on_enum_declared += method(:check_enum_declaration)
13549
13540
  interp.on_block_started += method(:start_block)
@@ -13679,7 +13670,7 @@ module C #:nodoc:
13679
13670
  interp.on_variable_declared += method(:check_object_declaration)
13680
13671
  interp.on_variable_defined += method(:check_object_declaration)
13681
13672
  interp.on_function_declared += method(:check_object_declaration)
13682
- interp.on_function_started += method(:check_object_declaration)
13673
+ interp.on_function_defined += method(:check_object_declaration)
13683
13674
  interp.on_typedef_declared += method(:check_typedef_declaration)
13684
13675
  interp.on_enum_declared += method(:check_enum_declaration)
13685
13676
  interp.on_block_started += method(:start_block)
@@ -13813,7 +13804,7 @@ module C #:nodoc:
13813
13804
  interp.on_variable_declared += method(:check_object_declaration)
13814
13805
  interp.on_variable_defined += method(:check_object_declaration)
13815
13806
  interp.on_function_declared += method(:check_object_declaration)
13816
- interp.on_function_started += method(:check_object_declaration)
13807
+ interp.on_function_defined += method(:check_object_declaration)
13817
13808
  interp.on_typedef_declared += method(:check_typedef_declaration)
13818
13809
  interp.on_enum_declared += method(:check_enum_declaration)
13819
13810
  interp.on_block_started += method(:start_block)
@@ -13948,7 +13939,7 @@ module C #:nodoc:
13948
13939
  super
13949
13940
  interp = context[:c_interpreter]
13950
13941
  interp.on_variable_defined += method(:check_variable)
13951
- interp.on_function_started += method(:check_function)
13942
+ interp.on_function_defined += method(:check_function)
13952
13943
  interp.on_block_started += method(:enter_block)
13953
13944
  interp.on_block_ended += method(:leave_block)
13954
13945
  @global_var_names = Set.new
@@ -14344,7 +14335,7 @@ module C #:nodoc:
14344
14335
  end
14345
14336
 
14346
14337
  def compute_bitfield_width(expression)
14347
- object = @c_interp.execute(expression, :suppress_notification)
14338
+ object = @c_interp.execute(expression, InterpreterOptions::QUIET)
14348
14339
  if object.variable? && object.value.scalar?
14349
14340
  return object.value.unique_sample || 0
14350
14341
  end
@@ -14442,87 +14433,79 @@ module C #:nodoc:
14442
14433
  class W1031 < PassiveMessageDetection
14443
14434
  def initialize(context)
14444
14435
  super
14445
- visitor = context[:c_visitor]
14446
- visitor.enter_variable_declaration += method(:declare_variable)
14447
- visitor.enter_variable_definition += method(:define_variable)
14448
- visitor.enter_function_declaration += method(:declare_function)
14449
- visitor.enter_ansi_function_definition += method(:define_function)
14450
- visitor.enter_kandr_function_definition += method(:define_function)
14451
- visitor.enter_compound_statement += method(:enter_block)
14452
- visitor.leave_compound_statement += method(:leave_block)
14453
- @block_level = 0
14454
- @global_objects = {}
14436
+ interp = context[:c_interpreter]
14437
+ interp.on_variable_declared += method(:declare_variable)
14438
+ interp.on_variable_defined += method(:define_variable)
14439
+ interp.on_function_declared += method(:declare_function)
14440
+ interp.on_function_defined += method(:define_function)
14455
14441
  end
14456
14442
 
14457
14443
  private
14458
- def declare_variable(variable_declaration)
14459
- name = variable_declaration.identifier.value
14460
- linkage = linkage_of(variable_declaration)
14461
- prev_linkage = @global_objects[name]
14462
- case
14463
- when linkage && prev_linkage && linkage != prev_linkage
14464
- W(:W1031, variable_declaration.location, name)
14465
- when linkage
14466
- @global_objects[name] = linkage
14467
- end
14468
- end
14469
-
14470
- def define_variable(variable_definition)
14471
- name = variable_definition.identifier.value
14472
- linkage = linkage_of(variable_definition)
14473
- prev_linkage = @global_objects[name]
14474
- case
14475
- when linkage && prev_linkage && linkage != prev_linkage
14476
- W(:W1031, variable_definition.location, name)
14477
- when linkage
14478
- @global_objects[name] = linkage
14444
+ def declare_variable(variable_declaration, variable)
14445
+ if variable.named?
14446
+ case
14447
+ when variable.declared_as_extern?
14448
+ sc_specifier = variable_declaration.storage_class_specifier
14449
+ if sc_specifier && sc_specifier.type == :STATIC
14450
+ W(:W1031, variable_declaration.location, variable.name)
14451
+ end
14452
+ when variable.declared_as_static?
14453
+ sc_specifier = variable_declaration.storage_class_specifier
14454
+ if sc_specifier && sc_specifier.type == :EXTERN
14455
+ W(:W1031, variable_declaration.location, variable.name)
14456
+ end
14457
+ end
14479
14458
  end
14480
14459
  end
14481
14460
 
14482
- def declare_function(function_declaration)
14483
- name = function_declaration.identifier.value
14484
- linkage = linkage_of(function_declaration)
14485
- prev_linkage = @global_objects[name]
14486
- case
14487
- when linkage && prev_linkage && linkage != prev_linkage
14488
- W(:W1031, function_declaration.location, name)
14489
- when linkage
14490
- @global_objects[name] = linkage
14461
+ def define_variable(variable_definition, variable)
14462
+ if variable.named?
14463
+ case
14464
+ when variable.declared_as_extern?
14465
+ sc_specifier = variable_definition.storage_class_specifier
14466
+ if sc_specifier && sc_specifier.type == :STATIC
14467
+ W(:W1031, variable_definition.location, variable.name)
14468
+ end
14469
+ when variable.declared_as_static?
14470
+ sc_specifier = variable_definition.storage_class_specifier
14471
+ if sc_specifier && sc_specifier.type == :EXTERN
14472
+ W(:W1031, variable_definition.location, variable.name)
14473
+ end
14474
+ end
14491
14475
  end
14492
14476
  end
14493
14477
 
14494
- def define_function(function_definition)
14495
- name = function_definition.identifier.value
14496
- linkage = linkage_of(function_definition)
14497
- prev_linkage = @global_objects[name]
14498
- case
14499
- when linkage && prev_linkage && linkage != prev_linkage
14500
- W(:W1031, function_definition.location, name)
14501
- when linkage
14502
- @global_objects[name] = linkage
14478
+ def declare_function(function_declaration, function)
14479
+ if function.named?
14480
+ case
14481
+ when function.declared_as_extern?
14482
+ sc_specifier = function_declaration.storage_class_specifier
14483
+ if sc_specifier && sc_specifier.type == :STATIC
14484
+ W(:W1031, function_declaration.location, function.name)
14485
+ end
14486
+ when function.declared_as_static?
14487
+ sc_specifier = function_declaration.storage_class_specifier
14488
+ if sc_specifier && sc_specifier.type == :EXTERN
14489
+ W(:W1031, function_declaration.location, function.name)
14490
+ end
14491
+ end
14503
14492
  end
14504
14493
  end
14505
14494
 
14506
- def enter_block(*)
14507
- @block_level += 1
14508
- end
14509
-
14510
- def leave_block(*)
14511
- @block_level -= 1
14512
- end
14513
-
14514
- def linkage_of(decl_or_def)
14515
- if storage_class_specifier = decl_or_def.storage_class_specifier
14516
- case storage_class_specifier.type
14517
- when :STATIC
14518
- :internal
14519
- when :EXTERN
14520
- :external
14521
- else
14522
- nil
14495
+ def define_function(function_definition, function)
14496
+ if function.named?
14497
+ case
14498
+ when function.declared_as_extern?
14499
+ sc_specifier = function_definition.storage_class_specifier
14500
+ if sc_specifier && sc_specifier.type == :STATIC
14501
+ W(:W1031, function_definition.location, function.name)
14502
+ end
14503
+ when function.declared_as_static?
14504
+ sc_specifier = function_definition.storage_class_specifier
14505
+ if sc_specifier && sc_specifier.type == :EXTERN
14506
+ W(:W1031, function_definition.location, function.name)
14507
+ end
14523
14508
  end
14524
- else
14525
- @block_level == 0 ? :external : nil
14526
14509
  end
14527
14510
  end
14528
14511
  end
@@ -250,6 +250,50 @@ module C #:nodoc:
250
250
  end
251
251
  end
252
252
 
253
+ class W0716 < PassiveMessageDetection
254
+ def initialize(context)
255
+ super
256
+ visitor = context[:c_visitor]
257
+ visitor.enter_additive_expression += method(:check)
258
+ visitor.enter_multiplicative_expression += method(:check)
259
+ visitor.enter_shift_expression += method(:check)
260
+ visitor.enter_and_expression += method(:check)
261
+ visitor.enter_exclusive_or_expression += method(:check)
262
+ visitor.enter_inclusive_or_expression += method(:check)
263
+ visitor.enter_compound_assignment_expression += lambda { |expr|
264
+ case expr.operator.type
265
+ when "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", "^=", "|="
266
+ check(expr)
267
+ end
268
+ }
269
+ end
270
+
271
+ private
272
+ def check(expression)
273
+ if expression.lhs_operand.logical? && expression.rhs_operand.logical?
274
+ W(:W0716, expression.location)
275
+ end
276
+ end
277
+ end
278
+
279
+ class W0717 < W0716
280
+ private
281
+ def check(expression)
282
+ if expression.lhs_operand.logical? && !expression.rhs_operand.logical?
283
+ W(:W0717, expression.lhs_operand.location)
284
+ end
285
+ end
286
+ end
287
+
288
+ class W0718 < W0716
289
+ private
290
+ def check(expression)
291
+ if !expression.lhs_operand.logical? && expression.rhs_operand.logical?
292
+ W(:W0718, expression.rhs_operand.location)
293
+ end
294
+ end
295
+ end
296
+
253
297
  class W0726 < W0698
254
298
  private
255
299
  def check(return_statement)