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