adlint 1.2.0 → 1.4.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.
- data/AUTHORS +1 -1
- data/ChangeLog +272 -0
- data/MANIFEST +4 -0
- data/NEWS +39 -4
- data/etc/mesg.d/en_US/messages.yml +2 -2
- data/etc/mesg.d/ja_JP/messages.yml +2 -2
- data/lib/adlint/c.rb +1 -0
- data/lib/adlint/c/expr.rb +20 -26
- data/lib/adlint/c/interp.rb +137 -45
- data/lib/adlint/c/mediator.rb +4 -0
- data/lib/adlint/c/message.rb +479 -16
- data/lib/adlint/c/message_shima.rb +151 -0
- data/lib/adlint/c/phase.rb +23 -0
- data/lib/adlint/c/resolver.rb +1 -0
- data/lib/adlint/c/syntax.rb +93 -89
- data/lib/adlint/c/type.rb +70 -0
- data/lib/adlint/cpp/eval.rb +12 -1
- data/lib/adlint/cpp/message_shima.rb +51 -0
- data/lib/adlint/cpp/phase.rb +3 -0
- data/lib/adlint/version.rb +2 -2
- data/share/demo/Makefile +3 -0
- data/share/demo/bad_enum/bad_enum.c +27 -0
- data/share/demo/bad_macro/bad_macro.c +4 -0
- data/share/demo/bad_return/bad_return.c +83 -0
- data/share/demo/incomplete_type/incomplete_type.c +3 -0
- data/share/demo/overflow/overflow.c +59 -5
- data/share/demo/union_type/union_type.c +13 -0
- data/share/demo/unnamed_member/unnamed_member.c +13 -0
- data/share/demo/various_fundef/various_fundef.c +43 -0
- data/share/demo/wrap_around/wrap_around.c +95 -21
- data/share/doc/developers_guide_ja.html +3 -3
- data/share/doc/developers_guide_ja.texi +1 -1
- data/share/doc/users_guide_en.html +222 -149
- data/share/doc/users_guide_en.texi +194 -120
- data/share/doc/users_guide_ja.html +224 -167
- data/share/doc/users_guide_ja.texi +194 -137
- metadata +6 -2
data/lib/adlint/c/interp.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
631
|
+
variable, converted = init_interp.execute(initializer, variable_type)
|
604
632
|
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
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,
|
619
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
1088
|
-
|
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
|
-
|
1229
|
-
|
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
|
data/lib/adlint/c/mediator.rb
CHANGED
@@ -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
|
data/lib/adlint/c/message.rb
CHANGED
@@ -6957,13 +6957,7 @@ module C #:nodoc:
|
|
6957
6957
|
|
6958
6958
|
private
|
6959
6959
|
def check_function(node)
|
6960
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|