adlint 3.0.4 → 3.0.8
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/ChangeLog +374 -13
- data/INSTALL +1 -3
- data/MANIFEST +12 -0
- data/NEWS +30 -4
- data/README +0 -4
- data/TODO +2 -1
- data/etc/mesg.d/c_builtin/en_US/messages.yml +2 -2
- data/etc/mesg.d/c_builtin/ja_JP/messages.yml +2 -2
- data/etc/mesg.d/core/en_US/messages.yml +5 -1
- data/etc/mesg.d/core/ja_JP/messages.yml +5 -1
- data/features/code_check/W0422.feature +128 -0
- data/features/code_check/W0491.feature +57 -0
- data/features/code_check/W0492.feature +80 -0
- data/features/code_check/W0542.feature +20 -0
- data/features/code_check/W0580.feature +25 -0
- data/features/code_check/W0610.feature +36 -0
- data/features/code_check/W0642.feature +67 -0
- data/features/code_check/W0786.feature +39 -0
- data/features/code_check/W0830.feature +27 -0
- data/features/code_check/W1047.feature +72 -0
- data/features/code_check/W9003.feature +22 -0
- data/features/code_extraction/TODO +1 -0
- data/features/metric_measurement/TODO +1 -0
- data/lib/adlint/analyzer.rb +2 -2
- data/lib/adlint/cc1/ctrlexpr.rb +27 -6
- data/lib/adlint/cc1/domain.rb +72 -12
- data/lib/adlint/cc1/enum.rb +4 -0
- data/lib/adlint/cc1/expr.rb +31 -29
- data/lib/adlint/cc1/interp.rb +45 -56
- data/lib/adlint/cc1/lexer.rb +26 -5
- data/lib/adlint/cc1/mediator.rb +35 -6
- data/lib/adlint/cc1/object.rb +62 -19
- data/lib/adlint/cc1/parser.rb +948 -904
- data/lib/adlint/cc1/parser.y +59 -29
- data/lib/adlint/cc1/phase.rb +6 -8
- data/lib/adlint/cc1/syntax.rb +70 -17
- data/lib/adlint/cc1/util.rb +4 -4
- data/lib/adlint/code.rb +16 -6
- data/lib/adlint/cpp/eval.rb +31 -25
- data/lib/adlint/cpp/lexer.rb +11 -5
- data/lib/adlint/cpp/macro.rb +34 -7
- data/lib/adlint/cpp/phase.rb +8 -8
- data/lib/adlint/error.rb +6 -0
- data/lib/adlint/exam/c_builtin/cc1_check.rb +557 -594
- data/lib/adlint/exam/c_builtin/cc1_check_shima.rb +72 -72
- data/lib/adlint/exam/c_builtin/cc1_code.rb +72 -52
- data/lib/adlint/exam/c_builtin/cc1_metric.rb +131 -131
- data/lib/adlint/exam/c_builtin/cpp_check.rb +48 -48
- data/lib/adlint/exam/c_builtin/cpp_check_shima.rb +2 -2
- data/lib/adlint/exam/c_builtin/cpp_code.rb +21 -21
- data/lib/adlint/exam/c_builtin/ld_check.rb +88 -87
- data/lib/adlint/exam/c_builtin/ld_metric.rb +4 -5
- data/lib/adlint/exam/c_builtin.rb +6 -6
- data/lib/adlint/ld/object.rb +269 -186
- data/lib/adlint/ld/phase.rb +19 -19
- data/lib/adlint/ld/typedef.rb +7 -7
- data/lib/adlint/ld/util.rb +25 -17
- data/lib/adlint/location.rb +6 -1
- data/lib/adlint/memo.rb +66 -13
- data/lib/adlint/prelude.rb +2 -2
- data/lib/adlint/report.rb +13 -14
- data/lib/adlint/util.rb +1 -1
- data/lib/adlint/version.rb +2 -2
- data/share/doc/Makefile +6 -2
- data/share/doc/c99gram.dot +502 -0
- data/share/doc/c99gram.pdf +0 -0
- data/share/doc/developers_guide_ja.html +4 -3
- data/share/doc/developers_guide_ja.texi +2 -1
- data/share/doc/users_guide_en.html +9 -9
- data/share/doc/users_guide_en.texi +7 -7
- data/share/doc/users_guide_ja.html +9 -9
- data/share/doc/users_guide_ja.texi +7 -7
- metadata +14 -2
data/lib/adlint/cc1/domain.rb
CHANGED
@@ -42,57 +42,112 @@ module Cc1 #:nodoc:
|
|
42
42
|
def equal_to(numeric, logical_shr)
|
43
43
|
EqualToValueDomain.new(numeric, logical_shr)
|
44
44
|
end
|
45
|
-
|
45
|
+
# NOTE: Value of #equal_to depends on the `logical_shr' parameter derived
|
46
|
+
# from the traits object.
|
47
|
+
# But the traits object is unique in an AdLint instance.
|
48
|
+
# So, it is safe to treat this method as unary method for improving
|
49
|
+
# the performance.
|
50
|
+
memoize :equal_to, key_indices: [0]
|
46
51
|
|
47
52
|
def not_equal_to(numeric, logical_shr)
|
48
53
|
equal_to(numeric, logical_shr).inversion
|
49
54
|
end
|
50
|
-
|
55
|
+
# NOTE: Value of #not_equal_to depends on the `logical_shr' parameter
|
56
|
+
# derived from the traits object.
|
57
|
+
# But the traits object is unique in an AdLint instance.
|
58
|
+
# So, it is safe to treat this method as unary method for improving
|
59
|
+
# the performance.
|
60
|
+
memoize :not_equal_to, key_indices: [0]
|
51
61
|
|
52
62
|
def less_than(numeric, logical_shr)
|
53
63
|
LessThanValueDomain.new(numeric, logical_shr)
|
54
64
|
end
|
55
|
-
|
65
|
+
# NOTE: Value of #less_than depends on the `logical_shr' parameter derived
|
66
|
+
# from the traits object.
|
67
|
+
# But the traits object is unique in an AdLint instance.
|
68
|
+
# So, it is safe to treat this method as unary method for improving
|
69
|
+
# the performance.
|
70
|
+
memoize :less_than, key_indices: [0]
|
56
71
|
|
57
72
|
def greater_than(numeric, logical_shr)
|
58
73
|
GreaterThanValueDomain.new(numeric, logical_shr)
|
59
74
|
end
|
60
|
-
|
75
|
+
# NOTE: Value of #greater_than depends on the `logical_shr' parameter
|
76
|
+
# derived from the traits object.
|
77
|
+
# But the traits object is unique in an AdLint instance.
|
78
|
+
# So, it is safe to treat this method as unary method for improving
|
79
|
+
# the performance.
|
80
|
+
memoize :greater_than, key_indices: [0]
|
61
81
|
|
62
82
|
def less_than_or_equal_to(numeric, logical_shr)
|
63
83
|
less_than(numeric, logical_shr).union(equal_to(numeric, logical_shr))
|
64
84
|
end
|
65
|
-
|
85
|
+
# NOTE: Value of #less_than_or_equal_to depends on the `logical_shr'
|
86
|
+
# parameter derived from the traits object.
|
87
|
+
# But the traits object is unique in an AdLint instance.
|
88
|
+
# So, it is safe to treat this method as unary method for improving
|
89
|
+
# the performance.
|
90
|
+
memoize :less_than_or_equal_to, key_indices: [0]
|
66
91
|
|
67
92
|
def greater_than_or_equal_to(numeric, logical_shr)
|
68
93
|
greater_than(numeric, logical_shr).union(equal_to(numeric, logical_shr))
|
69
94
|
end
|
70
|
-
|
95
|
+
# NOTE: Value of #greater_than_or_equal_to depends on the `logical_shr'
|
96
|
+
# parameter derived from the traits object.
|
97
|
+
# But the traits object is unique in an AdLint instance.
|
98
|
+
# So, it is safe to treat this method as unary method for improving
|
99
|
+
# the performance.
|
100
|
+
memoize :greater_than_or_equal_to, key_indices: [0]
|
71
101
|
|
72
102
|
def of_true(logical_shr)
|
73
103
|
not_equal_to(0, logical_shr)
|
74
104
|
end
|
75
|
-
|
105
|
+
# NOTE: Value of #of_true depends on the `logical_shr' parameter derived
|
106
|
+
# from the traits object.
|
107
|
+
# But the traits object is unique in an AdLint instance.
|
108
|
+
# So, it is safe to treat this method as nullary method for improving
|
109
|
+
# the performance.
|
110
|
+
memoize :of_true, force_nullary: true
|
76
111
|
|
77
112
|
def of_false(logical_shr)
|
78
113
|
equal_to(0, logical_shr)
|
79
114
|
end
|
80
|
-
|
115
|
+
# NOTE: Value of #of_false depends on the `logical_shr' parameter derived
|
116
|
+
# from the traits object.
|
117
|
+
# But the traits object is unique in an AdLint instance.
|
118
|
+
# So, it is safe to treat this method as nullary method for improving
|
119
|
+
# the performance.
|
120
|
+
memoize :of_false, force_nullary: true
|
81
121
|
|
82
122
|
def of_unlimited(logical_shr)
|
83
123
|
UnlimitedValueDomain.new(logical_shr)
|
84
124
|
end
|
85
|
-
|
125
|
+
# NOTE: Value of #of_unlimited depends on the `logical_shr' parameter
|
126
|
+
# derived from the traits object.
|
127
|
+
# But the traits object is unique in an AdLint instance.
|
128
|
+
# So, it is safe to treat this method as nullary method for improving
|
129
|
+
# the performance.
|
130
|
+
memoize :of_unlimited, force_nullary: true
|
86
131
|
|
87
132
|
def of_nil(logical_shr)
|
88
133
|
NilValueDomain.new(logical_shr)
|
89
134
|
end
|
90
|
-
|
135
|
+
# NOTE: Value of #of_nil depends on the `logical_shr' parameter derived
|
136
|
+
# from the traits object.
|
137
|
+
# But the traits object is unique in an AdLint instance.
|
138
|
+
# So, it is safe to treat this method as nullary method for improving
|
139
|
+
# the performance.
|
140
|
+
memoize :of_nil, force_nullary: true
|
91
141
|
|
92
142
|
def of_nan(logical_shr)
|
93
143
|
NaN.new(logical_shr)
|
94
144
|
end
|
95
|
-
|
145
|
+
# NOTE: Value of #of_nan depends on the `logical_shr' parameter derived
|
146
|
+
# from the traits object.
|
147
|
+
# But the traits object is unique in an AdLint instance.
|
148
|
+
# So, it is safe to treat this method as nullary method for improving
|
149
|
+
# the performance.
|
150
|
+
memoize :of_nan, force_nullary: true
|
96
151
|
|
97
152
|
def of_intersection(lhs_dom, rhs_dom)
|
98
153
|
case lhs_dom
|
@@ -168,7 +223,12 @@ module Cc1 #:nodoc:
|
|
168
223
|
def of_ambiguous(undefined, logical_shr)
|
169
224
|
AmbiguousValueDomain.new(undefined, logical_shr)
|
170
225
|
end
|
171
|
-
|
226
|
+
# NOTE: Value of #of_ambiguous depends on the `logical_shr' parameter
|
227
|
+
# derived from the traits object.
|
228
|
+
# But the traits object is unique in an AdLint instance.
|
229
|
+
# So, it is safe to treat this method as unary method for improving
|
230
|
+
# the performance.
|
231
|
+
memoize :of_ambiguous, key_indices: [0]
|
172
232
|
|
173
233
|
def _create_intersection(lhs_dom, rhs_dom)
|
174
234
|
expected = lhs_dom.complexity + rhs_dom.complexity
|
data/lib/adlint/cc1/enum.rb
CHANGED
data/lib/adlint/cc1/expr.rb
CHANGED
@@ -550,7 +550,9 @@ module Cc1 #:nodoc:
|
|
550
550
|
}
|
551
551
|
|
552
552
|
unless fun.builtin?
|
553
|
-
arg_vars = args.map { |arg_obj,
|
553
|
+
arg_vars = args.map { |arg_obj, arg_expr|
|
554
|
+
object_to_variable(arg_obj, arg_expr)
|
555
|
+
}
|
554
556
|
notify_function_call_expr_evaled(node, fun, arg_vars, res_var)
|
555
557
|
end
|
556
558
|
|
@@ -627,7 +629,7 @@ module Cc1 #:nodoc:
|
|
627
629
|
end
|
628
630
|
|
629
631
|
def eval_postfix_increment_expr(node, obj)
|
630
|
-
var = object_to_variable(obj)
|
632
|
+
var = object_to_variable(obj, node)
|
631
633
|
if !var.type.scalar? && !var.type.void?
|
632
634
|
# NOTE: To detect bad value reference of `void' expressions.
|
633
635
|
return create_tmpvar
|
@@ -650,7 +652,7 @@ module Cc1 #:nodoc:
|
|
650
652
|
end
|
651
653
|
|
652
654
|
def eval_postfix_decrement_expr(node, obj)
|
653
|
-
var = object_to_variable(obj)
|
655
|
+
var = object_to_variable(obj, node)
|
654
656
|
if !var.type.scalar? && !var.type.void?
|
655
657
|
# NOTE: To detect bad value reference of `void' expressions.
|
656
658
|
return create_tmpvar
|
@@ -673,7 +675,7 @@ module Cc1 #:nodoc:
|
|
673
675
|
end
|
674
676
|
|
675
677
|
def eval_prefix_increment_expr(node, obj)
|
676
|
-
var = object_to_variable(obj)
|
678
|
+
var = object_to_variable(obj, node)
|
677
679
|
if !var.type.scalar? && !var.type.void?
|
678
680
|
# NOTE: To detect bad value reference of `void' expressions.
|
679
681
|
return create_tmpvar
|
@@ -696,7 +698,7 @@ module Cc1 #:nodoc:
|
|
696
698
|
end
|
697
699
|
|
698
700
|
def eval_prefix_decrement_expr(node, obj)
|
699
|
-
var = object_to_variable(obj)
|
701
|
+
var = object_to_variable(obj, node)
|
700
702
|
if !var.type.scalar? && !var.type.void?
|
701
703
|
# NOTE: To detect bad value reference of `void' expressions.
|
702
704
|
return create_tmpvar
|
@@ -724,13 +726,13 @@ module Cc1 #:nodoc:
|
|
724
726
|
# variable cross-references.
|
725
727
|
_notify_variable_value_referred(node, obj)
|
726
728
|
|
727
|
-
ptr =
|
729
|
+
ptr = object_to_pointer(obj, node)
|
728
730
|
notify_address_expr_evaled(node, obj, ptr)
|
729
731
|
ptr
|
730
732
|
end
|
731
733
|
|
732
734
|
def eval_indirection_expr(node, obj)
|
733
|
-
var = object_to_variable(obj)
|
735
|
+
var = object_to_variable(obj, node)
|
734
736
|
if var.type.pointer?
|
735
737
|
ptr = var
|
736
738
|
else
|
@@ -768,7 +770,7 @@ module Cc1 #:nodoc:
|
|
768
770
|
end
|
769
771
|
|
770
772
|
def eval_unary_arithmetic_expr(node, obj)
|
771
|
-
var = object_to_variable(obj)
|
773
|
+
var = object_to_variable(obj, node)
|
772
774
|
if !var.type.scalar? && !var.type.void?
|
773
775
|
# NOTE: To detect bad value reference of `void' expressions.
|
774
776
|
return create_tmpvar
|
@@ -795,7 +797,7 @@ module Cc1 #:nodoc:
|
|
795
797
|
def eval_cast_expr(node, obj)
|
796
798
|
resolve_unresolved_type(node.type_name)
|
797
799
|
|
798
|
-
var = object_to_variable(obj)
|
800
|
+
var = object_to_variable(obj, node)
|
799
801
|
res_var = do_conversion(var, node.type_name.type) ||
|
800
802
|
create_tmpvar(node.type_name.type)
|
801
803
|
|
@@ -810,13 +812,13 @@ module Cc1 #:nodoc:
|
|
810
812
|
end
|
811
813
|
|
812
814
|
def eval_multiplicative_expr(node, lhs_obj, rhs_obj)
|
813
|
-
lhs_var = object_to_variable(lhs_obj)
|
815
|
+
lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
|
814
816
|
if !lhs_var.type.scalar? && !lhs_var.type.void?
|
815
817
|
# NOTE: To detect bad value reference of `void' expressions.
|
816
818
|
return create_tmpvar
|
817
819
|
end
|
818
820
|
|
819
|
-
rhs_var = object_to_variable(rhs_obj)
|
821
|
+
rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
|
820
822
|
if !rhs_var.type.scalar? && !rhs_var.type.void?
|
821
823
|
# NOTE: To detect bad value reference of `void' expressions.
|
822
824
|
return create_tmpvar
|
@@ -863,13 +865,13 @@ module Cc1 #:nodoc:
|
|
863
865
|
end
|
864
866
|
|
865
867
|
def eval_additive_expr(node, lhs_obj, rhs_obj)
|
866
|
-
lhs_var = object_to_variable(lhs_obj)
|
868
|
+
lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
|
867
869
|
if !lhs_var.type.scalar? && !lhs_var.type.void?
|
868
870
|
# NOTE: To detect bad value reference of `void' expressions.
|
869
871
|
return create_tmpvar
|
870
872
|
end
|
871
873
|
|
872
|
-
rhs_var = object_to_variable(rhs_obj)
|
874
|
+
rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
|
873
875
|
if !rhs_var.type.scalar? && !rhs_var.type.void?
|
874
876
|
# NOTE: To detect bad value reference of `void' expressions.
|
875
877
|
return create_tmpvar
|
@@ -908,13 +910,13 @@ module Cc1 #:nodoc:
|
|
908
910
|
end
|
909
911
|
|
910
912
|
def eval_shift_expr(node, lhs_obj, rhs_obj)
|
911
|
-
lhs_var = object_to_variable(lhs_obj)
|
913
|
+
lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
|
912
914
|
if !lhs_var.type.scalar? && !lhs_var.type.void?
|
913
915
|
# NOTE: To detect bad value reference of `void' expressions.
|
914
916
|
return create_tmpvar
|
915
917
|
end
|
916
918
|
|
917
|
-
rhs_var = object_to_variable(rhs_obj)
|
919
|
+
rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
|
918
920
|
if !rhs_var.type.scalar? && !rhs_var.type.void?
|
919
921
|
# NOTE: To detect bad value reference of `void' expressions.
|
920
922
|
return create_tmpvar
|
@@ -963,13 +965,13 @@ module Cc1 #:nodoc:
|
|
963
965
|
end
|
964
966
|
|
965
967
|
def eval_relational_expr(node, lhs_obj, rhs_obj)
|
966
|
-
lhs_var = object_to_variable(lhs_obj)
|
968
|
+
lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
|
967
969
|
if !lhs_var.type.scalar? && !lhs_var.type.void?
|
968
970
|
# NOTE: To detect bad value reference of `void' expressions.
|
969
971
|
return create_tmpvar(int_t, scalar_value_of_arbitrary)
|
970
972
|
end
|
971
973
|
|
972
|
-
rhs_var = object_to_variable(rhs_obj)
|
974
|
+
rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
|
973
975
|
if !rhs_var.type.scalar? && !rhs_var.type.void?
|
974
976
|
# NOTE: To detect bad value reference of `void' expressions.
|
975
977
|
return create_tmpvar(int_t, scalar_value_of_arbitrary)
|
@@ -1008,13 +1010,13 @@ module Cc1 #:nodoc:
|
|
1008
1010
|
end
|
1009
1011
|
|
1010
1012
|
def eval_equality_expr(node, lhs_obj, rhs_obj)
|
1011
|
-
lhs_var = object_to_variable(lhs_obj)
|
1013
|
+
lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
|
1012
1014
|
if !lhs_var.type.scalar? && !lhs_var.type.void?
|
1013
1015
|
# NOTE: To detect bad value reference of `void' expressions.
|
1014
1016
|
return create_tmpvar(int_t, scalar_value_of_arbitrary)
|
1015
1017
|
end
|
1016
1018
|
|
1017
|
-
rhs_var = object_to_variable(rhs_obj)
|
1019
|
+
rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
|
1018
1020
|
if !rhs_var.type.scalar? && !rhs_var.type.void?
|
1019
1021
|
# NOTE: To detect bad value reference of `void' expressions.
|
1020
1022
|
return create_tmpvar(int_t, scalar_value_of_arbitrary)
|
@@ -1049,13 +1051,13 @@ module Cc1 #:nodoc:
|
|
1049
1051
|
end
|
1050
1052
|
|
1051
1053
|
def eval_and_expr(node, lhs_obj, rhs_obj)
|
1052
|
-
lhs_var = object_to_variable(lhs_obj)
|
1054
|
+
lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
|
1053
1055
|
if !lhs_var.type.scalar? && !lhs_var.type.void?
|
1054
1056
|
# NOTE: To detect bad value reference of `void' expressions.
|
1055
1057
|
return create_tmpvar
|
1056
1058
|
end
|
1057
1059
|
|
1058
|
-
rhs_var = object_to_variable(rhs_obj)
|
1060
|
+
rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
|
1059
1061
|
if !rhs_var.type.scalar? && !rhs_var.type.void?
|
1060
1062
|
# NOTE: To detect bad value reference of `void' expressions.
|
1061
1063
|
return create_tmpvar
|
@@ -1085,13 +1087,13 @@ module Cc1 #:nodoc:
|
|
1085
1087
|
end
|
1086
1088
|
|
1087
1089
|
def eval_exclusive_or_expr(node, lhs_obj, rhs_obj)
|
1088
|
-
lhs_var = object_to_variable(lhs_obj)
|
1090
|
+
lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
|
1089
1091
|
if !lhs_var.type.scalar? && !lhs_var.type.void?
|
1090
1092
|
# NOTE: To detect bad value reference of `void' expressions.
|
1091
1093
|
return create_tmpvar
|
1092
1094
|
end
|
1093
1095
|
|
1094
|
-
rhs_var = object_to_variable(rhs_obj)
|
1096
|
+
rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
|
1095
1097
|
if !rhs_var.type.scalar? && !rhs_var.type.void?
|
1096
1098
|
# NOTE: To detect bad value reference of `void' expressions.
|
1097
1099
|
return create_tmpvar
|
@@ -1121,13 +1123,13 @@ module Cc1 #:nodoc:
|
|
1121
1123
|
end
|
1122
1124
|
|
1123
1125
|
def eval_inclusive_or_expr(node, lhs_obj, rhs_obj)
|
1124
|
-
lhs_var = object_to_variable(lhs_obj)
|
1126
|
+
lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
|
1125
1127
|
if !lhs_var.type.scalar? && !lhs_var.type.void?
|
1126
1128
|
# NOTE: To detect bad value reference of `void' expressions.
|
1127
1129
|
return create_tmpvar
|
1128
1130
|
end
|
1129
1131
|
|
1130
|
-
rhs_var = object_to_variable(rhs_obj)
|
1132
|
+
rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
|
1131
1133
|
if !rhs_var.type.scalar? && !rhs_var.type.void?
|
1132
1134
|
# NOTE: To detect bad value reference of `void' expressions.
|
1133
1135
|
return create_tmpvar
|
@@ -1157,8 +1159,8 @@ module Cc1 #:nodoc:
|
|
1157
1159
|
end
|
1158
1160
|
|
1159
1161
|
def eval_simple_assignment_expr(node, lhs_obj, rhs_obj)
|
1160
|
-
lhs_var = object_to_variable(lhs_obj)
|
1161
|
-
rhs_var = object_to_variable(rhs_obj)
|
1162
|
+
lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
|
1163
|
+
rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
|
1162
1164
|
|
1163
1165
|
if rhs_var.type.same_as?(lhs_var.type)
|
1164
1166
|
rhs_conved = rhs_var
|
@@ -1182,13 +1184,13 @@ module Cc1 #:nodoc:
|
|
1182
1184
|
end
|
1183
1185
|
|
1184
1186
|
def eval_compound_assignment_expr(node, lhs_obj, rhs_obj)
|
1185
|
-
lhs_var = object_to_variable(lhs_obj)
|
1187
|
+
lhs_var = object_to_variable(lhs_obj, node.lhs_operand)
|
1186
1188
|
if !lhs_var.type.scalar? && !lhs_var.type.void?
|
1187
1189
|
# NOTE: To detect bad value reference of `void' expressions.
|
1188
1190
|
return lhs_obj
|
1189
1191
|
end
|
1190
1192
|
|
1191
|
-
rhs_var = object_to_variable(rhs_obj)
|
1193
|
+
rhs_var = object_to_variable(rhs_obj, node.rhs_operand)
|
1192
1194
|
if !rhs_var.type.scalar? && !rhs_var.type.void?
|
1193
1195
|
# NOTE: To detect bad value reference of `void' expressions.
|
1194
1196
|
return lhs_var
|
data/lib/adlint/cc1/interp.rb
CHANGED
@@ -191,11 +191,17 @@ module Cc1 #:nodoc:
|
|
191
191
|
# NOTE: Notified when the interpreter evaluates a cast-expression.
|
192
192
|
def_plugin_and_notifier :explicit_conv_performed, :expr, :org_var, :res_var
|
193
193
|
|
194
|
-
# NOTE: Notified when the interpreter performs an implicit
|
195
|
-
#
|
194
|
+
# NOTE: Notified when the interpreter performs an implicit conversion while
|
195
|
+
# evaluating an expression.
|
196
196
|
def_plugin_and_notifier :implicit_conv_performed,
|
197
197
|
:init_or_expr, :org_var, :res_var
|
198
198
|
|
199
|
+
# NOTE: Notified when the interpreter performs an address derivation while
|
200
|
+
# address-expression evaluation and array or function address
|
201
|
+
# derivation.
|
202
|
+
def_plugin_and_notifier :address_derivation_performed,
|
203
|
+
:init_or_expr, :obj, :ptr
|
204
|
+
|
199
205
|
# NOTE: Notified when the interpreter evaluates an
|
200
206
|
# array-subscript-expression.
|
201
207
|
def_plugin_and_notifier :array_subscript_expr_evaled,
|
@@ -427,37 +433,6 @@ module Cc1 #:nodoc:
|
|
427
433
|
@options_stack.pop
|
428
434
|
end
|
429
435
|
|
430
|
-
def object_to_variable(obj)
|
431
|
-
case
|
432
|
-
when obj.function?
|
433
|
-
function_to_pointer(obj)
|
434
|
-
when obj.variable? && obj.type.array?
|
435
|
-
array_to_pointer(obj)
|
436
|
-
else
|
437
|
-
obj
|
438
|
-
end
|
439
|
-
end
|
440
|
-
|
441
|
-
def function_to_pointer(fun)
|
442
|
-
create_tmpvar(pointer_type(fun.type), pointer_value_of(fun))
|
443
|
-
end
|
444
|
-
|
445
|
-
def array_to_pointer(ary)
|
446
|
-
create_tmpvar(pointer_type(ary.type.base_type), pointer_value_of(ary))
|
447
|
-
end
|
448
|
-
|
449
|
-
def value_of(obj)
|
450
|
-
if obj.type.array? || obj.type.function?
|
451
|
-
pointer_value_of(obj)
|
452
|
-
else
|
453
|
-
obj.value.to_single_value
|
454
|
-
end
|
455
|
-
end
|
456
|
-
|
457
|
-
def pointer_value_of(obj)
|
458
|
-
scalar_value_of(obj.binding.memory.address)
|
459
|
-
end
|
460
|
-
|
461
436
|
def quiet?
|
462
437
|
cur_opts.include?(QUIET) || cur_opts.include?(QUIET_WITHOUT_SIDE_EFFECT)
|
463
438
|
end
|
@@ -592,8 +567,20 @@ module Cc1 #:nodoc:
|
|
592
567
|
end
|
593
568
|
|
594
569
|
if node.initializer
|
595
|
-
|
596
|
-
|
570
|
+
if node.type.incomplete?
|
571
|
+
# NOTE: Unable to define variable of incomplete type such as an array
|
572
|
+
# without length.
|
573
|
+
init_var, init_conved = evaluate_initializer(node)
|
574
|
+
var = define_variable(node, init_conved.value.to_defined_value)
|
575
|
+
else
|
576
|
+
# NOTE: Define variable first in order to correctly evaluate
|
577
|
+
# sizeof-expression that refers to the defining variable in the
|
578
|
+
# initializer.
|
579
|
+
define_variable(node) unless variable_named(node.identifier.value)
|
580
|
+
init_var, init_conved = evaluate_initializer(node)
|
581
|
+
var = define_variable(node, init_conved.value.to_defined_value)
|
582
|
+
end
|
583
|
+
|
597
584
|
notify_variable_value_referred(node, init_var)
|
598
585
|
notify_variable_defined(node, var)
|
599
586
|
notify_variable_initialized(node, var, init_var)
|
@@ -736,9 +723,7 @@ module Cc1 #:nodoc:
|
|
736
723
|
def evaluate_expression(expr, type)
|
737
724
|
checkpoint(expr.location)
|
738
725
|
|
739
|
-
|
740
|
-
var = object_to_variable(obj)
|
741
|
-
notify_implicit_conv_performed(expr, obj, var) unless var == obj
|
726
|
+
var = object_to_variable(interpret(expr), expr)
|
742
727
|
|
743
728
|
if var.type.same_as?(type)
|
744
729
|
conved = var
|
@@ -969,7 +954,7 @@ module Cc1 #:nodoc:
|
|
969
954
|
|
970
955
|
node.executed = true
|
971
956
|
ctrlexpr = node.expression
|
972
|
-
ctrlexpr_var = object_to_variable(interpret(ctrlexpr, QUIET))
|
957
|
+
ctrlexpr_var = object_to_variable(interpret(ctrlexpr, QUIET), ctrlexpr)
|
973
958
|
notify_case_ctrlexpr_evaled(node, ctrlexpr_var)
|
974
959
|
|
975
960
|
interpret(node.statement)
|
@@ -1017,7 +1002,8 @@ module Cc1 #:nodoc:
|
|
1017
1002
|
ctrlexpr_val = scalar_value_of_arbitrary
|
1018
1003
|
ctrlexpr = nil
|
1019
1004
|
else
|
1020
|
-
ctrlexpr_var = object_to_variable(interpret(org_ctrlexpr)
|
1005
|
+
ctrlexpr_var = object_to_variable(interpret(org_ctrlexpr),
|
1006
|
+
org_ctrlexpr)
|
1021
1007
|
ctrlexpr_val = value_of(ctrlexpr_var)
|
1022
1008
|
notify_variable_value_referred(org_ctrlexpr, ctrlexpr_var)
|
1023
1009
|
notify_sequence_point_reached(SequencePoint.new(org_ctrlexpr))
|
@@ -1050,7 +1036,8 @@ module Cc1 #:nodoc:
|
|
1050
1036
|
ctrlexpr_val = scalar_value_of_arbitrary
|
1051
1037
|
ctrlexpr = nil
|
1052
1038
|
else
|
1053
|
-
ctrlexpr_var = object_to_variable(interpret(org_ctrlexpr)
|
1039
|
+
ctrlexpr_var = object_to_variable(interpret(org_ctrlexpr),
|
1040
|
+
org_ctrlexpr)
|
1054
1041
|
ctrlexpr_val = value_of(ctrlexpr_var)
|
1055
1042
|
notify_variable_value_referred(org_ctrlexpr, ctrlexpr_var)
|
1056
1043
|
notify_sequence_point_reached(SequencePoint.new(org_ctrlexpr))
|
@@ -1088,7 +1075,8 @@ module Cc1 #:nodoc:
|
|
1088
1075
|
|
1089
1076
|
widen_varying_variable_value_domain(node)
|
1090
1077
|
|
1091
|
-
ctrlexpr_var = object_to_variable(interpret(node.expression)
|
1078
|
+
ctrlexpr_var = object_to_variable(interpret(node.expression),
|
1079
|
+
node.expression)
|
1092
1080
|
ctrlexpr_val = value_of(ctrlexpr_var)
|
1093
1081
|
notify_variable_value_referred(node.expression, ctrlexpr_var)
|
1094
1082
|
notify_sequence_point_reached(SequencePoint.new(node.expression))
|
@@ -1139,7 +1127,8 @@ module Cc1 #:nodoc:
|
|
1139
1127
|
leave_iteration_statement(org_ctrlexpr)
|
1140
1128
|
end
|
1141
1129
|
|
1142
|
-
ctrlexpr_var = object_to_variable(interpret(node.expression)
|
1130
|
+
ctrlexpr_var = object_to_variable(interpret(node.expression),
|
1131
|
+
node.expression)
|
1143
1132
|
ctrlexpr_val = value_of(ctrlexpr_var)
|
1144
1133
|
notify_variable_value_referred(node.expression, ctrlexpr_var)
|
1145
1134
|
notify_sequence_point_reached(SequencePoint.new(node.expression))
|
@@ -1161,7 +1150,8 @@ module Cc1 #:nodoc:
|
|
1161
1150
|
|
1162
1151
|
node.condition_statement.executed = true
|
1163
1152
|
if explicit_ctrlexpr = node.condition_statement.expression
|
1164
|
-
ctrlexpr_var = object_to_variable(interpret(explicit_ctrlexpr)
|
1153
|
+
ctrlexpr_var = object_to_variable(interpret(explicit_ctrlexpr),
|
1154
|
+
explicit_ctrlexpr)
|
1165
1155
|
ctrlexpr_val = value_of(ctrlexpr_var)
|
1166
1156
|
notify_variable_value_referred(explicit_ctrlexpr, ctrlexpr_var)
|
1167
1157
|
notify_sequence_point_reached(SequencePoint.new(explicit_ctrlexpr))
|
@@ -1194,7 +1184,8 @@ module Cc1 #:nodoc:
|
|
1194
1184
|
|
1195
1185
|
node.condition_statement.executed = true
|
1196
1186
|
if explicit_ctrlexpr = node.condition_statement.expression
|
1197
|
-
ctrlexpr_var = object_to_variable(interpret(explicit_ctrlexpr)
|
1187
|
+
ctrlexpr_var = object_to_variable(interpret(explicit_ctrlexpr),
|
1188
|
+
explicit_ctrlexpr)
|
1198
1189
|
ctrlexpr_val = value_of(ctrlexpr_var)
|
1199
1190
|
notify_variable_value_referred(explicit_ctrlexpr, ctrlexpr_var)
|
1200
1191
|
notify_sequence_point_reached(SequencePoint.new(explicit_ctrlexpr))
|
@@ -1246,12 +1237,7 @@ module Cc1 #:nodoc:
|
|
1246
1237
|
BreakEvent.of_return.throw
|
1247
1238
|
end
|
1248
1239
|
|
1249
|
-
|
1250
|
-
var = object_to_variable(obj)
|
1251
|
-
unless var == obj
|
1252
|
-
notify_implicit_conv_performed(node.expression, obj, var)
|
1253
|
-
end
|
1254
|
-
|
1240
|
+
var = object_to_variable(interpret(node.expression), node.expression)
|
1255
1241
|
notify_variable_value_referred(node.expression, var)
|
1256
1242
|
|
1257
1243
|
if active_fun = interpreter._active_function and
|
@@ -1296,7 +1282,8 @@ module Cc1 #:nodoc:
|
|
1296
1282
|
# causes "logical-expression must be false" warnings about a
|
1297
1283
|
# one-time-for-loop. To avoid this, now, workarounds are in
|
1298
1284
|
# builtin code checks W0609 and W0610.
|
1299
|
-
var = object_to_variable(interpret(explicit_ctrlexpr)
|
1285
|
+
var = object_to_variable(interpret(explicit_ctrlexpr),
|
1286
|
+
explicit_ctrlexpr)
|
1300
1287
|
notify_variable_value_referred(explicit_ctrlexpr, var)
|
1301
1288
|
notify_sequence_point_reached(SequencePoint.new(explicit_ctrlexpr))
|
1302
1289
|
end
|
@@ -1440,7 +1427,7 @@ module Cc1 #:nodoc:
|
|
1440
1427
|
notify_switch_stmt_started(node)
|
1441
1428
|
|
1442
1429
|
ctrlexpr = node.expression
|
1443
|
-
ctrlexpr_var = object_to_variable(interpret(ctrlexpr))
|
1430
|
+
ctrlexpr_var = object_to_variable(interpret(ctrlexpr), ctrlexpr)
|
1444
1431
|
notify_switch_ctrlexpr_evaled(node, ctrlexpr_var)
|
1445
1432
|
notify_variable_value_referred(ctrlexpr, ctrlexpr_var)
|
1446
1433
|
|
@@ -1693,7 +1680,7 @@ module Cc1 #:nodoc:
|
|
1693
1680
|
checkpoint(node.location)
|
1694
1681
|
|
1695
1682
|
ctrlexpr = node.condition
|
1696
|
-
ctrlexpr_var = object_to_variable(interpret(ctrlexpr))
|
1683
|
+
ctrlexpr_var = object_to_variable(interpret(ctrlexpr), ctrlexpr)
|
1697
1684
|
ctrlexpr_val = value_of(ctrlexpr_var)
|
1698
1685
|
notify_variable_value_referred(ctrlexpr, ctrlexpr_var)
|
1699
1686
|
notify_sequence_point_reached(ctrlexpr.subsequent_sequence_point)
|
@@ -1702,14 +1689,16 @@ module Cc1 #:nodoc:
|
|
1702
1689
|
then_var = nil
|
1703
1690
|
if ctrlexpr_val.may_be_true?
|
1704
1691
|
branched_eval(ctrlexpr, NARROWING, IMPLICIT_COND) do
|
1705
|
-
then_var = object_to_variable(interpret(node.then_expression)
|
1692
|
+
then_var = object_to_variable(interpret(node.then_expression),
|
1693
|
+
node.then_expression)
|
1706
1694
|
end
|
1707
1695
|
end
|
1708
1696
|
|
1709
1697
|
else_var = nil
|
1710
1698
|
if ctrlexpr_val.may_be_false?
|
1711
1699
|
branched_eval(nil, NARROWING, FINAL, COMPLETE) do
|
1712
|
-
else_var = object_to_variable(interpret(node.else_expression)
|
1700
|
+
else_var = object_to_variable(interpret(node.else_expression),
|
1701
|
+
node.else_expression)
|
1713
1702
|
end
|
1714
1703
|
else
|
1715
1704
|
branched_eval(nil, NARROWING, FINAL, COMPLETE) {}
|
data/lib/adlint/cc1/lexer.rb
CHANGED
@@ -69,11 +69,11 @@ module Cc1 #:nodoc:
|
|
69
69
|
@object_names.leave_scope
|
70
70
|
end
|
71
71
|
|
72
|
-
def
|
72
|
+
def enable_identifier_translation
|
73
73
|
@identifier_translation = true
|
74
74
|
end
|
75
75
|
|
76
|
-
def
|
76
|
+
def disable_identifier_translation
|
77
77
|
@identifier_translation = false
|
78
78
|
end
|
79
79
|
|
@@ -119,14 +119,35 @@ module Cc1 #:nodoc:
|
|
119
119
|
end
|
120
120
|
|
121
121
|
def translate_identifier(tok, lexer_ctxt)
|
122
|
+
# NOTE: To translate given IDENTIFIER into TYPEDEF_NAME if needed.
|
123
|
+
|
124
|
+
# NOTE: The ISO C99 standard says;
|
125
|
+
#
|
126
|
+
# 6.2.3 Name spaces of identifiers
|
127
|
+
#
|
128
|
+
# 1 If more than one declaration of a particular identifier is visible at
|
129
|
+
# any point in a translation unit, the syntactic context disambiguates
|
130
|
+
# uses that refer to different entities. Thus, there are separate name
|
131
|
+
# spaces for various categories of identifiers, as follows:
|
132
|
+
# -- label names (disambiguated by the syntax of the label declaration
|
133
|
+
# and use);
|
134
|
+
# -- the tags of structures, unions, and enumerations (disambiguated by
|
135
|
+
# following any of the keywords struct, union, or enum);
|
136
|
+
# -- the members of structures or unions; each structure or union has a
|
137
|
+
# separate name space for its members (disambiguated by the type of
|
138
|
+
# the expression used to access the member via the . or ->
|
139
|
+
# operator);
|
140
|
+
# -- all other identifiers, called ordinary identifiers (declared in
|
141
|
+
# ordinary declarators or as enumeration constants).
|
142
|
+
|
122
143
|
if @identifier_translation
|
123
144
|
if tok.type == :IDENTIFIER
|
124
145
|
return tok if @object_names.include?(tok.value)
|
125
146
|
if @typedef_names.include?(tok.value)
|
126
147
|
unless @lst_tok and
|
127
|
-
|
128
|
-
|
129
|
-
|
148
|
+
@lst_tok.type == :STRUCT || @lst_tok.type == :UNION ||
|
149
|
+
@lst_tok.type == :ENUM ||
|
150
|
+
@lst_tok.type == "->" || @lst_tok.type == "."
|
130
151
|
tok = tok.class.new(:TYPEDEF_NAME, tok.value, tok.location)
|
131
152
|
end
|
132
153
|
end
|