adlint 1.8.10 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data/ChangeLog +261 -3
  2. data/MANIFEST +25 -1
  3. data/NEWS +25 -5
  4. data/Rakefile +11 -0
  5. data/TODO +0 -1
  6. data/etc/mesg.d/en_US/messages.yml +1 -1
  7. data/etc/mesg.d/ja_JP/messages.yml +1 -1
  8. data/features/message_detection/W0001.feature +41 -0
  9. data/features/message_detection/W0002.feature +68 -0
  10. data/features/message_detection/W0003.feature +134 -0
  11. data/features/message_detection/W0007.feature +264 -0
  12. data/features/message_detection/W0010.feature +75 -0
  13. data/features/message_detection/W0013.feature +189 -0
  14. data/features/message_detection/W0109.feature +50 -0
  15. data/features/message_detection/W0583.feature +30 -0
  16. data/features/message_detection/W0606.feature +20 -0
  17. data/features/message_detection/W0698.feature +20 -0
  18. data/features/message_detection/W0699.feature +21 -0
  19. data/features/message_detection/W0703.feature +73 -0
  20. data/features/message_detection/W0716.feature +67 -0
  21. data/features/message_detection/W0717.feature +64 -0
  22. data/features/message_detection/W0718.feature +64 -0
  23. data/features/message_detection/W0723.feature +18 -0
  24. data/features/message_detection/W1031.feature +328 -0
  25. data/features/step_definitions/message_detection_steps.rb +45 -0
  26. data/features/support/env.rb +58 -0
  27. data/lib/adlint/c/branch.rb +16 -23
  28. data/lib/adlint/c/code.rb +1 -12
  29. data/lib/adlint/c/conv.rb +4 -4
  30. data/lib/adlint/c/ctrlexpr.rb +10 -6
  31. data/lib/adlint/c/domain.rb +2 -2
  32. data/lib/adlint/c/expr.rb +11 -33
  33. data/lib/adlint/c/format.rb +6 -6
  34. data/lib/adlint/c/interp.rb +137 -80
  35. data/lib/adlint/c/mediator.rb +5 -2
  36. data/lib/adlint/c/message.rb +123 -140
  37. data/lib/adlint/c/message_shima.rb +44 -0
  38. data/lib/adlint/c/object.rb +93 -26
  39. data/lib/adlint/c/option.rb +53 -0
  40. data/lib/adlint/c/phase.rb +4 -1
  41. data/lib/adlint/c/type.rb +112 -46
  42. data/lib/adlint/c.rb +1 -0
  43. data/lib/adlint/version.rb +3 -3
  44. data/share/doc/developers_guide_ja.html +3 -3
  45. data/share/doc/developers_guide_ja.texi +1 -1
  46. data/share/doc/users_guide_en.html +35 -28
  47. data/share/doc/users_guide_en.texi +30 -22
  48. data/share/doc/users_guide_ja.html +35 -31
  49. data/share/doc/users_guide_ja.texi +30 -24
  50. data/spec/adlint/c/type_spec.rb +110 -0
  51. data/spec/conf.d/default_traits.yml +216 -0
  52. data/spec/conf.d/empty_cinit.h +11 -0
  53. data/spec/conf.d/empty_pinit.h +11 -0
  54. data/spec/spec_helper.rb +49 -0
  55. metadata +27 -3
  56. data/spec/MUST_WRITE_SPECS_WITH_RSPEC +0 -0
@@ -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)