adlint 1.2.0 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -61,6 +61,10 @@ module C #:nodoc:
61
61
  ]
62
62
 
63
63
  @suppress_notification = false
64
+
65
+ # NOTE: Active (executing) function may be nested if the nested
66
+ # function-definition of the GCC extension is used.
67
+ @active_function_stack = []
64
68
  end
65
69
 
66
70
  attr_reader :environment
@@ -276,6 +280,13 @@ module C #:nodoc:
276
280
  :assignment_expression, :lhs_variable,
277
281
  :rhs_variable
278
282
 
283
+ # NOTE: Notified when the interpreter starts execution of a
284
+ # switch-statement.
285
+ def_plugin_and_notifier :switch_stmt_started, :switch_statement
286
+
287
+ # NOTE: Notified when the interpreter ends execution of a switch-statement.
288
+ def_plugin_and_notifier :switch_stmt_ended, :switch_statement
289
+
279
290
  # NOTE: Notified when the interpreter starts execution of a
280
291
  # while-statement.
281
292
  def_plugin_and_notifier :while_stmt_started, :while_statement
@@ -319,6 +330,16 @@ module C #:nodoc:
319
330
  def_plugin_and_notifier :if_else_ctrlexpr_evaled,
320
331
  :if_else_statement, :ctrlexpr_value
321
332
 
333
+ # NOTE: Notified when the interpreter evaluates a controlling expression of
334
+ # the switch-statement.
335
+ def_plugin_and_notifier :switch_ctrlexpr_evaled,
336
+ :switch_statement, :ctrlexpr_result
337
+
338
+ # NOTE: Notified when the interpreter evaluates a controlling expression of
339
+ # the case-labeled-statement.
340
+ def_plugin_and_notifier :case_ctrlexpr_evaled,
341
+ :case_labeled_statement, :ctrlexpr_result
342
+
322
343
  # NOTE: Notified when the interpreter evaluates a controlling expression of
323
344
  # the while-statement.
324
345
  def_plugin_and_notifier :while_ctrlexpr_evaled,
@@ -409,6 +430,24 @@ module C #:nodoc:
409
430
  @suppress_notification = suppress_notification
410
431
  end
411
432
 
433
+ def _active_function
434
+ # NOTE: This method is called only from
435
+ # StatementInterpreter#visit_return_statement.
436
+ # NOTE: To convert returning object, StatementInterpreter must have
437
+ # knowledge about conversion destination type.
438
+ @active_function_stack.last
439
+ end
440
+
441
+ def _enter_function(function_definition)
442
+ # NOTE: This method is called only from FunctionInterpreter.
443
+ @active_function_stack.push(function_definition)
444
+ end
445
+
446
+ def _leave_function(function_definition)
447
+ # NOTE: This method is called only from FunctionInterpreter.
448
+ @active_function_stack.pop
449
+ end
450
+
412
451
  private
413
452
  def interpreter_for(node)
414
453
  @sub_interpreters.find do |interp|
@@ -519,25 +558,14 @@ module C #:nodoc:
519
558
  end
520
559
 
521
560
  if initializer = node.initializer
522
- init_variable = evaluate_initializer(initializer, node.type)
523
-
524
- if node.type.same_as?(init_variable.type)
525
- converted = init_variable
526
- else
527
- converted =
528
- do_conversion(init_variable, node.type) ||
529
- temporary_variable(node.type)
530
- notify_implicit_conv_performed(initializer, init_variable, converted)
531
- end
561
+ init_variable, converted = evaluate_initializer(initializer, node.type)
562
+ variable = define_variable(node, converted.value.to_defined_value)
532
563
 
533
564
  notify_variable_value_referred(node, init_variable)
534
-
535
- variable = define_variable(node, converted.value.to_defined_value)
536
565
  notify_variable_defined(node, variable)
537
566
  notify_variable_initialized(node, variable, init_variable)
538
567
  else
539
- variable = define_variable(node)
540
- notify_variable_defined(node, variable)
568
+ notify_variable_defined(node, define_variable(node))
541
569
  end
542
570
 
543
571
  evaluate_sequence_point(node.init_declarator.declarator)
@@ -600,29 +628,21 @@ module C #:nodoc:
600
628
  private
601
629
  def evaluate_initializer(initializer, variable_type)
602
630
  init_interp = InitializerInterpreter.new(interpreter)
603
- object = init_interp.execute(initializer, variable_type)
631
+ variable, converted = init_interp.execute(initializer, variable_type)
604
632
 
605
- case
606
- when variable_type.pointer? && object.type.array?
607
- init_variable = temporary_variable(variable_type,
608
- pointer_value_of(object))
609
- notify_implicit_conv_performed(initializer, object, init_variable)
610
- when variable_type.pointer? && object.type.function?
611
- init_variable = temporary_variable(variable_type,
612
- pointer_value_of(object))
613
- notify_implicit_conv_performed(initializer, object, init_variable)
614
- when variable_type.array? && object.type.pointer?
615
- unless init_variable = pointee_of(object) and init_variable.type.array?
616
- init_variable = temporary_variable(variable_type)
633
+ # NOTE: An implicit conversion has been done by InitializerInterpreter.
634
+
635
+ # NOTE: For the case of array variable definition with a
636
+ # string-literal-specifier as the initializer.
637
+ if variable_type.array? && variable.type.pointer?
638
+ unless array = pointee_of(variable) and array.type.array?
639
+ array = temporary_variable(variable_type)
617
640
  end
618
- deduct_array_length_from_array_variable(variable_type, init_variable)
619
- when object.function?
620
- init_variable = temporary_variable(variable_type)
621
- else
622
- init_variable = object
641
+ deduct_array_length_from_array_variable(variable_type, array)
642
+ variable = converted = array
623
643
  end
624
644
 
625
- init_variable
645
+ return variable, converted
626
646
  end
627
647
 
628
648
  def deduct_array_length_from_array_variable(variable_type, array_variable)
@@ -638,6 +658,8 @@ module C #:nodoc:
638
658
 
639
659
  class InitializerInterpreter
640
660
  include InterpreterMediator
661
+ include NotifierMediator
662
+ include Conversion
641
663
  include MonitorUtil
642
664
 
643
665
  def initialize(interpreter)
@@ -649,19 +671,46 @@ module C #:nodoc:
649
671
 
650
672
  case
651
673
  when expression = initializer.expression
652
- evaluate_expression(expression)
674
+ # NOTE: An implicit conversion is already notified in
675
+ # #evaluate_expression.
676
+ return evaluate_expression(expression, variable_type)
653
677
  when initializers = initializer.initializers
654
- evaluate_initializers(initializers, variable_type)
678
+ variable = evaluate_initializers(initializers, variable_type)
679
+
680
+ if variable.type.same_as?(variable_type)
681
+ converted = variable
682
+ else
683
+ converted =
684
+ do_conversion(variable, variable_type) ||
685
+ temporary_variable(variable_type)
686
+ notify_implicit_conv_performed(initializer, variable, converted)
687
+ end
655
688
  else
656
- temporary_variable(variable_type)
689
+ variable = converted = temporary_variable(variable_type)
657
690
  end
691
+
692
+ return variable, converted
658
693
  end
659
694
 
660
695
  private
661
- def evaluate_expression(expression)
696
+ def evaluate_expression(expression, type)
662
697
  checkpoint(expression.location)
663
698
 
664
- object_to_variable(interpret(expression))
699
+ object = interpret(expression)
700
+
701
+ variable = object_to_variable(object)
702
+ unless variable == object
703
+ notify_implicit_conv_performed(expression, object, variable)
704
+ end
705
+
706
+ if variable.type.same_as?(type)
707
+ converted = variable
708
+ else
709
+ converted = do_conversion(variable, type) || temporary_variable(type)
710
+ notify_implicit_conv_performed(expression, variable, converted)
711
+ end
712
+
713
+ return variable, converted
665
714
  end
666
715
 
667
716
  def evaluate_initializers(initializers, variable_type)
@@ -680,7 +729,7 @@ module C #:nodoc:
680
729
  checkpoint(initializer.location)
681
730
  case
682
731
  when expression = initializer.expression
683
- value_of(evaluate_expression(expression))
732
+ value_of(evaluate_expression(expression, type).last)
684
733
  when initializers = initializer.initializers
685
734
  value_of(evaluate_initializers(initializers, type))
686
735
  else
@@ -756,6 +805,8 @@ module C #:nodoc:
756
805
  def interpret_function(node)
757
806
  checkpoint(node.location)
758
807
 
808
+ interpreter._enter_function(node)
809
+
759
810
  reset_environment
760
811
  resolve_unresolved_type(node)
761
812
 
@@ -781,6 +832,8 @@ module C #:nodoc:
781
832
  notify_block_ended(node.function_body)
782
833
  notify_function_ended(node)
783
834
  end
835
+ ensure
836
+ interpreter._leave_function(node)
784
837
  end
785
838
  end
786
839
 
@@ -807,6 +860,11 @@ module C #:nodoc:
807
860
  checkpoint(node.location)
808
861
 
809
862
  node.executed = true
863
+ ctrlexpr = node.expression
864
+ ctrlexpr_result = object_to_variable(interpret(ctrlexpr,
865
+ :suppress_notification))
866
+ notify_case_ctrlexpr_evaled(node, ctrlexpr_result)
867
+
810
868
  interpret(node.statement)
811
869
  end
812
870
 
@@ -1025,7 +1083,7 @@ module C #:nodoc:
1025
1083
  interpret(node.body_statement)
1026
1084
  interpret(node.expression) if node.expression
1027
1085
  # NOTE: To avoid that value of the controlling variable is marked
1028
- # as updated at end of the for-statement. Value of the
1086
+ # as updated at end of the c99-for-statement. Value of the
1029
1087
  # controlling variable is referred by the controlling
1030
1088
  # expression at the last iteration.
1031
1089
  # FIXME: This re-interpretation of the controlling expression may
@@ -1038,7 +1096,7 @@ module C #:nodoc:
1038
1096
  interpret(node.body_statement)
1039
1097
  interpret(node.expression) if node.expression
1040
1098
  # NOTE: To avoid that value of the controlling variable is marked
1041
- # as updated at end of the for-statement. Value of the
1099
+ # as updated at end of the c99-for-statement. Value of the
1042
1100
  # controlling variable is referred by the controlling
1043
1101
  # expression at the last iteration.
1044
1102
  # FIXME: This re-interpretation of the controlling expression may
@@ -1084,8 +1142,35 @@ module C #:nodoc:
1084
1142
  checkpoint(node.location)
1085
1143
 
1086
1144
  node.executed = true
1087
- return_object = node.expression ? interpret(node.expression) : nil
1088
- notify_return_stmt_evaled(node, return_object)
1145
+
1146
+ unless node.expression
1147
+ notify_return_stmt_evaled(node, nil)
1148
+ BreakEvent.of_return.throw
1149
+ end
1150
+
1151
+ object = interpret(node.expression)
1152
+ variable = object_to_variable(object)
1153
+ unless variable == object
1154
+ notify_implicit_conv_performed(node.expression, object, variable)
1155
+ end
1156
+
1157
+ notify_variable_value_referred(node.expression, variable)
1158
+
1159
+ if active_function = interpreter._active_function and
1160
+ return_type = active_function.type.return_type
1161
+ if variable.type.same_as?(return_type)
1162
+ converted = variable
1163
+ else
1164
+ converted =
1165
+ do_conversion(variable, return_type) ||
1166
+ temporary_variable(return_type)
1167
+ notify_implicit_conv_performed(node.expression, variable, converted)
1168
+ end
1169
+ else
1170
+ converted = variable
1171
+ end
1172
+
1173
+ notify_return_stmt_evaled(node, variable)
1089
1174
  BreakEvent.of_return.throw
1090
1175
  end
1091
1176
 
@@ -1225,8 +1310,15 @@ module C #:nodoc:
1225
1310
  checkpoint(node.location)
1226
1311
 
1227
1312
  node.executed = true
1228
- object = interpret(node.expression)
1229
- execute_switch_body(object, node.statement) if object.variable?
1313
+ notify_switch_stmt_started(node)
1314
+
1315
+ ctrlexpr = node.expression
1316
+ ctrlexpr_result = object_to_variable(interpret(ctrlexpr))
1317
+ notify_switch_ctrlexpr_evaled(node, ctrlexpr_result)
1318
+
1319
+ execute_switch_body(ctrlexpr_result, node.statement)
1320
+
1321
+ notify_switch_stmt_ended(node)
1230
1322
  end
1231
1323
 
1232
1324
  private
@@ -217,6 +217,8 @@ module C #:nodoc:
217
217
  def_delegator :interpreter, :notify_prefix_decrement_expr_evaled
218
218
  def_delegator :interpreter, :notify_postfix_decrement_expr_evaled
219
219
  def_delegator :interpreter, :notify_assignment_expr_evaled
220
+ def_delegator :interpreter, :notify_switch_stmt_started
221
+ def_delegator :interpreter, :notify_switch_stmt_ended
220
222
  def_delegator :interpreter, :notify_while_stmt_started
221
223
  def_delegator :interpreter, :notify_while_stmt_ended
222
224
  def_delegator :interpreter, :notify_do_stmt_started
@@ -229,6 +231,8 @@ module C #:nodoc:
229
231
  def_delegator :interpreter, :notify_return_stmt_evaled
230
232
  def_delegator :interpreter, :notify_if_ctrlexpr_evaled
231
233
  def_delegator :interpreter, :notify_if_else_ctrlexpr_evaled
234
+ def_delegator :interpreter, :notify_switch_ctrlexpr_evaled
235
+ def_delegator :interpreter, :notify_case_ctrlexpr_evaled
232
236
  def_delegator :interpreter, :notify_while_ctrlexpr_evaled
233
237
  def_delegator :interpreter, :notify_do_ctrlexpr_evaled
234
238
  def_delegator :interpreter, :notify_for_ctrlexpr_evaled
@@ -6957,13 +6957,7 @@ module C #:nodoc:
6957
6957
 
6958
6958
  private
6959
6959
  def check_function(node)
6960
- if declaration_specifiers = node.declaration_specifiers
6961
- if declaration_specifiers.type_specifiers.empty?
6962
- W(:W0457, node.location)
6963
- end
6964
- else
6965
- W(:W0457, node.location)
6966
- end
6960
+ W(:W0457, node.location) if node.implicitly_typed?
6967
6961
  end
6968
6962
  end
6969
6963
 
@@ -6978,13 +6972,7 @@ module C #:nodoc:
6978
6972
 
6979
6973
  private
6980
6974
  def check_variable(node)
6981
- if declaration_specifiers = node.declaration_specifiers
6982
- if declaration_specifiers.type_specifiers.empty?
6983
- W(:W0458, node.location)
6984
- end
6985
- else
6986
- W(:W0458, node.location)
6987
- end
6975
+ W(:W0458, node.location) if node.implicitly_typed?
6988
6976
  end
6989
6977
  end
6990
6978
 
@@ -12279,6 +12267,260 @@ module C #:nodoc:
12279
12267
  private_constant :Visitor
12280
12268
  end
12281
12269
 
12270
+ class W0720 < PassiveMessageDetection
12271
+ def initialize(context)
12272
+ super
12273
+ interp = context[:c_interpreter]
12274
+ interp.on_explicit_conv_performed += method(:check)
12275
+ end
12276
+
12277
+ private
12278
+ def check(expression, original_variable, result_variable)
12279
+ orig_type = original_variable.type
12280
+ conv_type = result_variable.type
12281
+
12282
+ unless orig_type.scalar? && orig_type.floating? &&
12283
+ conv_type.scalar? && conv_type.integer?
12284
+ return
12285
+ end
12286
+
12287
+ orig_value = original_variable.value
12288
+ return unless orig_value.scalar?
12289
+
12290
+ lower_test = orig_value < ScalarValue.of(conv_type.min_value - 1)
12291
+ upper_test = orig_value > ScalarValue.of(conv_type.max_value + 1)
12292
+
12293
+ if lower_test.must_be_true? || upper_test.must_be_true?
12294
+ W(:W0720, expression.location)
12295
+ end
12296
+ end
12297
+ end
12298
+
12299
+ class W0721 < PassiveMessageDetection
12300
+ def initialize(context)
12301
+ super
12302
+ interp = context[:c_interpreter]
12303
+ interp.on_explicit_conv_performed += method(:check)
12304
+ end
12305
+
12306
+ private
12307
+ def check(expression, original_variable, result_variable)
12308
+ orig_type = original_variable.type
12309
+ conv_type = result_variable.type
12310
+
12311
+ unless orig_type.pointer? && conv_type.scalar? && conv_type.integer?
12312
+ return
12313
+ end
12314
+
12315
+ if orig_type.min_value < conv_type.min_value ||
12316
+ orig_type.max_value > conv_type.max_value
12317
+ W(:W0721, expression.location)
12318
+ end
12319
+ end
12320
+ end
12321
+
12322
+ class W0722 < PassiveMessageDetection
12323
+ def initialize(context)
12324
+ super
12325
+ interp = context[:c_interpreter]
12326
+ interp.on_multiplicative_expr_evaled += method(:check)
12327
+ interp.on_additive_expr_evaled += method(:check)
12328
+ end
12329
+
12330
+ private
12331
+ def check(binary_expression, lhs_variable, rhs_variable, result_variable)
12332
+ return unless lhs_variable.type.scalar? && lhs_variable.type.signed?
12333
+ return unless rhs_variable.type.scalar? && rhs_variable.type.signed?
12334
+
12335
+ return unless lhs_variable.value.scalar? && rhs_variable.value.scalar?
12336
+
12337
+ case binary_expression.operator.type
12338
+ when "+"
12339
+ unbound_value = lhs_variable.value + rhs_variable.value
12340
+ when "-"
12341
+ unbound_value = lhs_variable.value - rhs_variable.value
12342
+ when "*"
12343
+ unbound_value = lhs_variable.value * rhs_variable.value
12344
+ else
12345
+ return
12346
+ end
12347
+
12348
+ result_type = result_variable.type
12349
+ lower_test = unbound_value < ScalarValue.of(result_type.min_value)
12350
+ upper_test = unbound_value > ScalarValue.of(result_type.max_value)
12351
+
12352
+ if lower_test.must_be_true? || upper_test.must_be_true?
12353
+ W(:W0722, binary_expression.location)
12354
+ end
12355
+ end
12356
+ end
12357
+
12358
+ class W0723 < PassiveMessageDetection
12359
+ def initialize(context)
12360
+ super
12361
+ interp = context[:c_interpreter]
12362
+ interp.on_multiplicative_expr_evaled += method(:check)
12363
+ interp.on_additive_expr_evaled += method(:check)
12364
+ end
12365
+
12366
+ private
12367
+ def check(binary_expression, lhs_variable, rhs_variable, result_variable)
12368
+ return unless lhs_variable.type.scalar? && lhs_variable.type.signed?
12369
+ return unless rhs_variable.type.scalar? && rhs_variable.type.signed?
12370
+
12371
+ return unless lhs_variable.value.scalar? && rhs_variable.value.scalar?
12372
+
12373
+ case binary_expression.operator.type
12374
+ when "+"
12375
+ unbound_value = lhs_variable.value + rhs_variable.value
12376
+ when "-"
12377
+ unbound_value = lhs_variable.value + rhs_variable.value
12378
+ when "*"
12379
+ unbound_value = lhs_variable.value * rhs_variable.value
12380
+ else
12381
+ return
12382
+ end
12383
+
12384
+ result_type = result_variable.type
12385
+ lower_test = unbound_value < ScalarValue.of(result_type.min_value)
12386
+ upper_test = unbound_value > ScalarValue.of(result_type.max_value)
12387
+
12388
+ if !lower_test.must_be_true? && lower_test.may_be_true? or
12389
+ !upper_test.must_be_true? && upper_test.may_be_true?
12390
+ W(:W0723, binary_expression.location)
12391
+ end
12392
+ end
12393
+ end
12394
+
12395
+ class W0727 < PassiveMessageDetection
12396
+ def initialize(context)
12397
+ super
12398
+ interp = context[:c_interpreter]
12399
+ interp.on_explicit_conv_performed += method(:check)
12400
+ interp.on_implicit_conv_performed += method(:check)
12401
+ end
12402
+
12403
+ private
12404
+ def check(initializer_or_expression, original_variable, result_variable)
12405
+ return unless result_variable.type.enum?
12406
+
12407
+ value = original_variable.value.unique_sample
12408
+
12409
+ unless result_variable.type.enumerators.any? { |enum| value == enum.value }
12410
+ W(:W0727, initializer_or_expression.location)
12411
+ end
12412
+ end
12413
+ end
12414
+
12415
+ class W0728 < PassiveMessageDetection
12416
+ def initialize(context)
12417
+ super
12418
+ interp = context[:c_interpreter]
12419
+ interp.on_function_call_expr_evaled += method(:check)
12420
+ end
12421
+
12422
+ private
12423
+ def check(expression, function, arg_variables, result_variable)
12424
+ args = arg_variables.zip(function.type.parameter_types)
12425
+ args.each_with_index do |(arg_variable, param_type), index|
12426
+ next unless param_type && param_type.enum?
12427
+
12428
+ if arg_variable.type.enum?
12429
+ unless arg_variable.type.same_as?(param_type)
12430
+ W(:W0728, expression.argument_expressions[index].location)
12431
+ end
12432
+ end
12433
+ end
12434
+ end
12435
+ end
12436
+
12437
+ class W0729 < PassiveMessageDetection
12438
+ def initialize(context)
12439
+ super
12440
+ interp = context[:c_interpreter]
12441
+ interp.on_assignment_expr_evaled += method(:check)
12442
+ end
12443
+
12444
+ private
12445
+ def check(expression, lhs_variable, rhs_variable)
12446
+ return unless lhs_variable.type.enum?
12447
+
12448
+ if rhs_variable.type.enum?
12449
+ unless lhs_variable.type.same_as?(rhs_variable.type)
12450
+ W(:W0729, expression.location)
12451
+ end
12452
+ end
12453
+ end
12454
+ end
12455
+
12456
+ class W0730 < PassiveMessageDetection
12457
+ def initialize(context)
12458
+ super
12459
+ interp = context[:c_interpreter]
12460
+ interp.on_function_started += method(:start_function)
12461
+ interp.on_function_ended += method(:end_function)
12462
+ interp.on_return_stmt_evaled += method(:check)
12463
+ @current_function = nil
12464
+ end
12465
+
12466
+ private
12467
+ def start_function(function_definition)
12468
+ @current_function = function_definition
12469
+ end
12470
+
12471
+ def end_function(function_definition)
12472
+ @current_function = nil
12473
+ end
12474
+
12475
+ def check(return_statement, result_variable)
12476
+ return unless @current_function && result_variable
12477
+
12478
+ return unless return_type = @current_function.type.return_type
12479
+ return unless return_type.enum?
12480
+
12481
+ if result_variable.type.enum?
12482
+ unless return_type.same_as?(result_variable.type)
12483
+ W(:W0730, return_statement.expression.location)
12484
+ end
12485
+ end
12486
+ end
12487
+ end
12488
+
12489
+ class W0731 < PassiveMessageDetection
12490
+ def initialize(context)
12491
+ super
12492
+ interp = context[:c_interpreter]
12493
+ interp.on_switch_stmt_ended += method(:end_switch_statement)
12494
+ interp.on_switch_ctrlexpr_evaled += method(:memorize_switch_ctrlexpr)
12495
+ interp.on_case_ctrlexpr_evaled += method(:check)
12496
+ @switch_ctrlexpr_stack = []
12497
+ end
12498
+
12499
+ private
12500
+ def end_switch_statement(node)
12501
+ @switch_ctrlexpr_stack.pop
12502
+ end
12503
+
12504
+ def memorize_switch_ctrlexpr(node, ctrlexpr_result)
12505
+ @switch_ctrlexpr_stack.push(ctrlexpr_result)
12506
+ end
12507
+
12508
+ def check(case_labeled_statement, ctrlexpr_result)
12509
+ unless switch_ctrlexpr_result = @switch_ctrlexpr_stack.last
12510
+ return
12511
+ end
12512
+
12513
+ return unless switch_ctrlexpr_result.type.enum?
12514
+ expected_type = switch_ctrlexpr_result.type
12515
+
12516
+ value = ctrlexpr_result.value.unique_sample
12517
+ unless expected_type.enumerators.any? { |enum| value == enum.value }
12518
+ W(:W0731, case_labeled_statement.expression.location,
12519
+ case_labeled_statement.expression.to_s)
12520
+ end
12521
+ end
12522
+ end
12523
+
12282
12524
  class W0736 < PassiveMessageDetection
12283
12525
  def initialize(context)
12284
12526
  super
@@ -12328,6 +12570,146 @@ module C #:nodoc:
12328
12570
  end
12329
12571
  end
12330
12572
 
12573
+ class W0737 < PassiveMessageDetection
12574
+ def initialize(context)
12575
+ super
12576
+ interp = context[:c_interpreter]
12577
+ interp.on_variable_declared += method(:check)
12578
+ interp.on_variable_defined += method(:check)
12579
+ end
12580
+
12581
+ private
12582
+ def check(decl_or_def, variable)
12583
+ return unless decl_or_def.type.enum?
12584
+
12585
+ if decl_or_def.type.incomplete?
12586
+ W(:W0737, decl_or_def.location, decl_or_def.type.name)
12587
+ end
12588
+ end
12589
+ end
12590
+
12591
+ class W0738 < PassiveMessageDetection
12592
+ def initialize(context)
12593
+ super
12594
+ interp = context[:c_interpreter]
12595
+ interp.on_implicit_conv_performed += method(:check)
12596
+ end
12597
+
12598
+ private
12599
+ def check(initializer_or_expression, original_variable, result_variable)
12600
+ case initializer_or_expression
12601
+ when Initializer
12602
+ unless expression = initializer_or_expression.expression
12603
+ return
12604
+ end
12605
+ when Expression
12606
+ expression = initializer_or_expression
12607
+ end
12608
+
12609
+ return unless expression.constant?
12610
+
12611
+ orig_type = original_variable.type
12612
+ conv_type = result_variable.type
12613
+
12614
+ unless orig_type.scalar? && orig_type.integer? &&
12615
+ conv_type.scalar? && conv_type.integer? && conv_type.unsigned?
12616
+ return
12617
+ end
12618
+
12619
+ orig_value = original_variable.value
12620
+ return unless orig_value.scalar?
12621
+
12622
+ upper_test = orig_value > ScalarValue.of(conv_type.max_value)
12623
+
12624
+ W(:W0738, expression.location) if upper_test.must_be_true?
12625
+ end
12626
+ end
12627
+
12628
+ class W0739 < PassiveMessageDetection
12629
+ def initialize(context)
12630
+ super
12631
+ interp = context[:c_interpreter]
12632
+ interp.on_additive_expr_evaled += method(:check)
12633
+ end
12634
+
12635
+ private
12636
+ def check(additive_expression, lhs_variable, rhs_variable, result_variable)
12637
+ return unless additive_expression.operator.type == "-"
12638
+
12639
+ return unless additive_expression.lhs_operand.constant?
12640
+ return unless additive_expression.rhs_operand.constant?
12641
+
12642
+ return unless lhs_variable.type.scalar? && lhs_variable.type.unsigned?
12643
+ return unless rhs_variable.type.scalar? && rhs_variable.type.unsigned?
12644
+
12645
+ return unless lhs_variable.value.scalar? && rhs_variable.value.scalar?
12646
+
12647
+ unbound_value = lhs_variable.value - rhs_variable.value
12648
+
12649
+ result_type = result_variable.type
12650
+ lower_test = unbound_value < ScalarValue.of(result_type.min_value)
12651
+
12652
+ W(:W0739, additive_expression.location) if lower_test.must_be_true?
12653
+ end
12654
+ end
12655
+
12656
+ class W0740 < PassiveMessageDetection
12657
+ def initialize(context)
12658
+ super
12659
+ interp = context[:c_interpreter]
12660
+ interp.on_additive_expr_evaled += method(:check)
12661
+ end
12662
+
12663
+ private
12664
+ def check(additive_expression, lhs_variable, rhs_variable, result_variable)
12665
+ return unless additive_expression.operator.type == "+"
12666
+
12667
+ return unless additive_expression.lhs_operand.constant?
12668
+ return unless additive_expression.rhs_operand.constant?
12669
+
12670
+ return unless lhs_variable.type.scalar? && lhs_variable.type.unsigned?
12671
+ return unless rhs_variable.type.scalar? && rhs_variable.type.unsigned?
12672
+
12673
+ return unless lhs_variable.value.scalar? && rhs_variable.value.scalar?
12674
+
12675
+ unbound_value = lhs_variable.value + rhs_variable.value
12676
+
12677
+ result_type = result_variable.type
12678
+ upper_test = unbound_value > ScalarValue.of(result_type.max_value)
12679
+
12680
+ W(:W0740, additive_expression.location) if upper_test.must_be_true?
12681
+ end
12682
+ end
12683
+
12684
+ class W0741 < PassiveMessageDetection
12685
+ def initialize(context)
12686
+ super
12687
+ interp = context[:c_interpreter]
12688
+ interp.on_multiplicative_expr_evaled += method(:check)
12689
+ end
12690
+
12691
+ private
12692
+ def check(multiplicative_expression, lhs_variable, rhs_variable,
12693
+ result_variable)
12694
+ return unless multiplicative_expression.operator.type == "*"
12695
+
12696
+ return unless multiplicative_expression.lhs_operand.constant?
12697
+ return unless multiplicative_expression.rhs_operand.constant?
12698
+
12699
+ return unless lhs_variable.type.scalar? && lhs_variable.type.unsigned?
12700
+ return unless rhs_variable.type.scalar? && rhs_variable.type.unsigned?
12701
+
12702
+ return unless lhs_variable.value.scalar? && rhs_variable.value.scalar?
12703
+
12704
+ unbound_value = lhs_variable.value * rhs_variable.value
12705
+
12706
+ result_type = result_variable.type
12707
+ upper_test = unbound_value > ScalarValue.of(result_type.max_value)
12708
+
12709
+ W(:W0741, multiplicative_expression.location) if upper_test.must_be_true?
12710
+ end
12711
+ end
12712
+
12331
12713
  class W0742 < PassiveMessageDetection
12332
12714
  def initialize(context)
12333
12715
  super
@@ -12355,6 +12737,46 @@ module C #:nodoc:
12355
12737
  end
12356
12738
  end
12357
12739
 
12740
+ class W0743 < PassiveMessageDetection
12741
+ def initialize(context)
12742
+ super
12743
+ interp = context[:c_interpreter]
12744
+ interp.on_implicit_conv_performed += method(:check)
12745
+ end
12746
+
12747
+ private
12748
+ def check(initializer_or_expression, original_variable, result_variable)
12749
+ case initializer_or_expression
12750
+ when Initializer
12751
+ unless expression = initializer_or_expression.expression
12752
+ return
12753
+ end
12754
+ when Expression
12755
+ expression = initializer_or_expression
12756
+ end
12757
+
12758
+ return unless expression.constant?
12759
+
12760
+ orig_type = original_variable.type
12761
+ conv_type = result_variable.type
12762
+
12763
+ unless orig_type.scalar? && orig_type.integer? &&
12764
+ conv_type.scalar? && conv_type.integer? && conv_type.signed?
12765
+ return
12766
+ end
12767
+
12768
+ orig_value = original_variable.value
12769
+ return unless orig_value.scalar?
12770
+
12771
+ lower_test = orig_value < ScalarValue.of(conv_type.min_value)
12772
+ upper_test = orig_value > ScalarValue.of(conv_type.max_value)
12773
+
12774
+ if lower_test.must_be_true? || upper_test.must_be_true?
12775
+ W(:W0743, expression.location)
12776
+ end
12777
+ end
12778
+ end
12779
+
12358
12780
  class W0744 < PassiveMessageDetection
12359
12781
  def initialize(context)
12360
12782
  super
@@ -13593,7 +14015,11 @@ module C #:nodoc:
13593
14015
  def check(expression, original_variable, result_variable)
13594
14016
  orig_type = original_variable.type
13595
14017
  conv_type = result_variable.type
13596
- return unless orig_type.scalar? && conv_type.scalar? && conv_type.signed?
14018
+
14019
+ unless orig_type.scalar? && orig_type.integer? &&
14020
+ conv_type.scalar? && conv_type.integer? && conv_type.signed?
14021
+ return
14022
+ end
13597
14023
 
13598
14024
  orig_value = original_variable.value
13599
14025
  return unless orig_value.scalar?
@@ -13619,7 +14045,11 @@ module C #:nodoc:
13619
14045
  def check(expression, original_variable, result_variable)
13620
14046
  orig_type = original_variable.type
13621
14047
  conv_type = result_variable.type
13622
- return unless orig_type.scalar? && conv_type.scalar? && conv_type.signed?
14048
+
14049
+ unless orig_type.scalar? && orig_type.integer? &&
14050
+ conv_type.scalar? && conv_type.integer? && conv_type.signed?
14051
+ return
14052
+ end
13623
14053
 
13624
14054
  orig_value = original_variable.value
13625
14055
  return unless orig_value.scalar?
@@ -13706,6 +14136,39 @@ module C #:nodoc:
13706
14136
  end
13707
14137
  end
13708
14138
 
14139
+ class W1064 < W0731
14140
+ private
14141
+ def check(case_labeled_statement, ctrlexpr_result)
14142
+ unless switch_ctrlexpr_result = @switch_ctrlexpr_stack.last
14143
+ return
14144
+ end
14145
+
14146
+ return unless switch_ctrlexpr_result.type.enum?
14147
+
14148
+ unless ctrlexpr_result.type.enum?
14149
+ W(:W1064, case_labeled_statement.expression.location)
14150
+ end
14151
+ end
14152
+ end
14153
+
14154
+ class W1065 < W0731
14155
+ private
14156
+ def check(case_labeled_statement, ctrlexpr_result)
14157
+ unless switch_ctrlexpr_result = @switch_ctrlexpr_stack.last
14158
+ return
14159
+ end
14160
+
14161
+ return unless switch_ctrlexpr_result.type.enum?
14162
+ expected_type = switch_ctrlexpr_result.type
14163
+
14164
+ if ctrlexpr_result.type.enum?
14165
+ unless ctrlexpr_result.type.same_as?(expected_type)
14166
+ W(:W1065, case_labeled_statement.expression.location)
14167
+ end
14168
+ end
14169
+ end
14170
+ end
14171
+
13709
14172
  class W9001 < PassiveMessageDetection
13710
14173
  def initialize(context)
13711
14174
  super