adlint 1.12.0 → 1.14.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/ChangeLog +133 -34
- data/MANIFEST +10 -0
- data/NEWS +22 -4
- data/etc/mesg.d/en_US/messages.yml +1 -1
- data/etc/mesg.d/ja_JP/messages.yml +1 -1
- data/features/message_detection/W0093.feature +3 -3
- data/features/message_detection/W0104.feature +111 -0
- data/features/message_detection/W0606.feature +1 -1
- data/features/message_detection/W0645.feature +142 -0
- data/features/message_detection/W0697.feature +183 -0
- data/features/message_detection/W0699.feature +1 -0
- data/features/message_detection/W0700.feature +56 -0
- data/features/message_detection/W1031.feature +18 -18
- data/features/message_detection/W1066.feature +88 -0
- data/features/message_detection/W1067.feature +88 -0
- data/features/message_detection/W1068.feature +88 -0
- data/features/message_detection/W1069.feature +120 -0
- data/features/message_detection/W1070.feature +145 -0
- data/features/message_detection/W1072.feature +32 -0
- data/lib/adlint/c/interp.rb +17 -10
- data/lib/adlint/c/mediator.rb +1 -0
- data/lib/adlint/c/message_shima.rb +222 -0
- data/lib/adlint/c/phase.rb +9 -0
- data/lib/adlint/c/type.rb +13 -12
- data/lib/adlint/version.rb +2 -2
- 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 +59 -50
- data/share/doc/users_guide_en.texi +48 -40
- data/share/doc/users_guide_ja.html +60 -52
- data/share/doc/users_guide_ja.texi +49 -41
- metadata +12 -2
@@ -0,0 +1,120 @@
|
|
1
|
+
Feature: W1069
|
2
|
+
|
3
|
+
W1069 detects that no trailing `else' clause is found in this `if-else-if'
|
4
|
+
statements chain.
|
5
|
+
|
6
|
+
Scenario: no trailing `else' in `if-else-if' statements chain
|
7
|
+
Given a target source named "W1069.c" with:
|
8
|
+
"""
|
9
|
+
static int func(int i)
|
10
|
+
{
|
11
|
+
if (i == 2) { /* W1069 */
|
12
|
+
return 0;
|
13
|
+
}
|
14
|
+
else if (i == 4) {
|
15
|
+
return 1;
|
16
|
+
}
|
17
|
+
return 2;
|
18
|
+
}
|
19
|
+
"""
|
20
|
+
When I successfully run `adlint W1069.c` on noarch
|
21
|
+
Then the output should exactly match with:
|
22
|
+
| mesg | line | column |
|
23
|
+
| W0104 | 1 | 21 |
|
24
|
+
| W0629 | 1 | 12 |
|
25
|
+
| W1069 | 3 | 5 |
|
26
|
+
| W0628 | 1 | 12 |
|
27
|
+
|
28
|
+
Scenario: no trailing `else' in `if-else-if-else-if' statements chain
|
29
|
+
Given a target source named "W1069.c" with:
|
30
|
+
"""
|
31
|
+
static int func(int i)
|
32
|
+
{
|
33
|
+
if (i == 2) { /* W1069 */
|
34
|
+
return 0;
|
35
|
+
}
|
36
|
+
else if (i == 4) {
|
37
|
+
return 1;
|
38
|
+
}
|
39
|
+
else if (i == 6) {
|
40
|
+
return 2;
|
41
|
+
}
|
42
|
+
return 4;
|
43
|
+
}
|
44
|
+
"""
|
45
|
+
When I successfully run `adlint W1069.c` on noarch
|
46
|
+
Then the output should exactly match with:
|
47
|
+
| mesg | line | column |
|
48
|
+
| W0104 | 1 | 21 |
|
49
|
+
| W0629 | 1 | 12 |
|
50
|
+
| W1069 | 3 | 5 |
|
51
|
+
| W0628 | 1 | 12 |
|
52
|
+
|
53
|
+
Scenario: `else' clause at the last of `if-else-if-else-if' statements chain
|
54
|
+
Given a target source named "W1069.c" with:
|
55
|
+
"""
|
56
|
+
static int func(int i)
|
57
|
+
{
|
58
|
+
if (i == 2) { /* OK */
|
59
|
+
return 0;
|
60
|
+
}
|
61
|
+
else if (i == 4) {
|
62
|
+
return 1;
|
63
|
+
}
|
64
|
+
else if (i == 6) {
|
65
|
+
return 2;
|
66
|
+
}
|
67
|
+
else {
|
68
|
+
return 3;
|
69
|
+
}
|
70
|
+
}
|
71
|
+
"""
|
72
|
+
When I successfully run `adlint W1069.c` on noarch
|
73
|
+
Then the output should exactly match with:
|
74
|
+
| mesg | line | column |
|
75
|
+
| W0104 | 1 | 21 |
|
76
|
+
| W0629 | 1 | 12 |
|
77
|
+
| W0628 | 1 | 12 |
|
78
|
+
|
79
|
+
Scenario: standalone `if' statement
|
80
|
+
Given a target source named "W1069.c" with:
|
81
|
+
"""
|
82
|
+
static int func(int i)
|
83
|
+
{
|
84
|
+
if (i == 2) { /* OK */
|
85
|
+
return 0;
|
86
|
+
}
|
87
|
+
return 10;
|
88
|
+
}
|
89
|
+
"""
|
90
|
+
When I successfully run `adlint W1069.c` on noarch
|
91
|
+
Then the output should exactly match with:
|
92
|
+
| mesg | line | column |
|
93
|
+
| W0104 | 1 | 21 |
|
94
|
+
| W0629 | 1 | 12 |
|
95
|
+
| W0628 | 1 | 12 |
|
96
|
+
|
97
|
+
Scenario: `else' clause at the last of `if-else-if' statements chain
|
98
|
+
Given a target source named "W1069.c" with:
|
99
|
+
"""
|
100
|
+
static int func(int i)
|
101
|
+
{
|
102
|
+
if (i == 2) { /* OK */
|
103
|
+
return 0;
|
104
|
+
}
|
105
|
+
else if (i == 4) {
|
106
|
+
return 1;
|
107
|
+
}
|
108
|
+
else {
|
109
|
+
return 2;
|
110
|
+
}
|
111
|
+
}
|
112
|
+
"""
|
113
|
+
When I successfully run `adlint W1069.c` on noarch
|
114
|
+
Then the output should exactly match with:
|
115
|
+
| mesg | line | column |
|
116
|
+
| W0104 | 1 | 21 |
|
117
|
+
| W0629 | 1 | 12 |
|
118
|
+
| W0628 | 1 | 12 |
|
119
|
+
|
120
|
+
# vim:ts=2:sw=2:sts=2:et:
|
@@ -0,0 +1,145 @@
|
|
1
|
+
Feature: W1070
|
2
|
+
|
3
|
+
W1070 detects that a `switch' statement can be translated into if-else
|
4
|
+
statement because there are only two execution paths.
|
5
|
+
|
6
|
+
Scenario: `switch' statement which has only two execution paths
|
7
|
+
Given a target source named "W1070.c" with:
|
8
|
+
"""
|
9
|
+
static int func(const int i)
|
10
|
+
{
|
11
|
+
switch (i) { /* W1070 */
|
12
|
+
case 0:
|
13
|
+
return 4;
|
14
|
+
default:
|
15
|
+
return 8;
|
16
|
+
}
|
17
|
+
}
|
18
|
+
"""
|
19
|
+
When I successfully run `adlint W1070.c` on noarch
|
20
|
+
Then the output should exactly match with:
|
21
|
+
| mesg | line | column |
|
22
|
+
| W0629 | 1 | 12 |
|
23
|
+
| W1070 | 3 | 5 |
|
24
|
+
| W0628 | 1 | 12 |
|
25
|
+
|
26
|
+
Scenario: `switch' statement which has only two execution paths and doesn't
|
27
|
+
have `default' clause
|
28
|
+
Given a target source named "W1070.c" with:
|
29
|
+
"""
|
30
|
+
static int func(const int i)
|
31
|
+
{
|
32
|
+
switch (i) { /* W1070 */
|
33
|
+
case 0:
|
34
|
+
return 4;
|
35
|
+
case 1:
|
36
|
+
return 6;
|
37
|
+
}
|
38
|
+
return 10;
|
39
|
+
}
|
40
|
+
"""
|
41
|
+
When I successfully run `adlint W1070.c` on noarch
|
42
|
+
Then the output should exactly match with:
|
43
|
+
| mesg | line | column |
|
44
|
+
| W0629 | 1 | 12 |
|
45
|
+
| W0003 | 3 | 5 |
|
46
|
+
| W1070 | 3 | 5 |
|
47
|
+
| W0628 | 1 | 12 |
|
48
|
+
|
49
|
+
Scenario: `switch' statement which has only two execution paths and the
|
50
|
+
control never reaches to one of that paths
|
51
|
+
Given a target source named "W1070.c" with:
|
52
|
+
"""
|
53
|
+
static int func(const int i)
|
54
|
+
{
|
55
|
+
if (i > 5) {
|
56
|
+
switch (i) { /* W1070, W0781 */
|
57
|
+
case 5:
|
58
|
+
return 2;
|
59
|
+
default:
|
60
|
+
return 3;
|
61
|
+
}
|
62
|
+
}
|
63
|
+
return 10;
|
64
|
+
}
|
65
|
+
"""
|
66
|
+
When I successfully run `adlint W1070.c` on noarch
|
67
|
+
Then the output should exactly match with:
|
68
|
+
| mesg | line | column |
|
69
|
+
| W0629 | 1 | 12 |
|
70
|
+
| W9001 | 5 | 9 |
|
71
|
+
| W9001 | 6 | 13 |
|
72
|
+
| W0781 | 4 | 9 |
|
73
|
+
| W1070 | 4 | 9 |
|
74
|
+
| W0628 | 1 | 12 |
|
75
|
+
|
76
|
+
Scenario: `switch' statement which has only one execution path
|
77
|
+
Given a target source named "W1070.c" with:
|
78
|
+
"""
|
79
|
+
static int func(const int i)
|
80
|
+
{
|
81
|
+
switch (i) { /* W0781 */
|
82
|
+
default:
|
83
|
+
return 8;
|
84
|
+
}
|
85
|
+
}
|
86
|
+
"""
|
87
|
+
When I successfully run `adlint W1070.c` on noarch
|
88
|
+
Then the output should exactly match with:
|
89
|
+
| mesg | line | column |
|
90
|
+
| W0629 | 1 | 12 |
|
91
|
+
| W0781 | 3 | 5 |
|
92
|
+
| W0628 | 1 | 12 |
|
93
|
+
|
94
|
+
Scenario: `switch' statement which has three execution paths, but the control
|
95
|
+
never reaches to only one of that paths
|
96
|
+
Given a target source named "W1070.c" with:
|
97
|
+
"""
|
98
|
+
static int func(const int i)
|
99
|
+
{
|
100
|
+
if (i > 5) {
|
101
|
+
switch (i) { /* W0781 */
|
102
|
+
case 0:
|
103
|
+
return 1;
|
104
|
+
case 5:
|
105
|
+
return 2;
|
106
|
+
default:
|
107
|
+
return 3;
|
108
|
+
}
|
109
|
+
}
|
110
|
+
return 10;
|
111
|
+
}
|
112
|
+
"""
|
113
|
+
When I successfully run `adlint W1070.c` on noarch
|
114
|
+
Then the output should exactly match with:
|
115
|
+
| mesg | line | column |
|
116
|
+
| W0629 | 1 | 12 |
|
117
|
+
| W9001 | 5 | 9 |
|
118
|
+
| W9001 | 6 | 13 |
|
119
|
+
| W9001 | 7 | 9 |
|
120
|
+
| W9001 | 8 | 13 |
|
121
|
+
| W0781 | 4 | 9 |
|
122
|
+
| W0628 | 1 | 12 |
|
123
|
+
|
124
|
+
Scenario: `switch' statement which has three execution paths
|
125
|
+
Given a target source named "W1070.c" with:
|
126
|
+
"""
|
127
|
+
static int func(const int i)
|
128
|
+
{
|
129
|
+
switch (i) { /* OK */
|
130
|
+
case 0:
|
131
|
+
return 4;
|
132
|
+
case 1:
|
133
|
+
return 6;
|
134
|
+
default:
|
135
|
+
return 8;
|
136
|
+
}
|
137
|
+
}
|
138
|
+
"""
|
139
|
+
When I successfully run `adlint W1070.c` on noarch
|
140
|
+
Then the output should exactly match with:
|
141
|
+
| mesg | line | column |
|
142
|
+
| W0629 | 1 | 12 |
|
143
|
+
| W0628 | 1 | 12 |
|
144
|
+
|
145
|
+
# vim:ts=2:sw=2:sts=2:et:
|
@@ -0,0 +1,32 @@
|
|
1
|
+
Feature: W1072
|
2
|
+
|
3
|
+
W1072 detects that a `goto' statement is found.
|
4
|
+
|
5
|
+
Scenario: `goto' statement is found
|
6
|
+
Given a target source named "W1072.c" with:
|
7
|
+
"""
|
8
|
+
static int func(int i)
|
9
|
+
{
|
10
|
+
if (i == 1) {
|
11
|
+
goto Label1; /* W1072 */
|
12
|
+
}
|
13
|
+
|
14
|
+
goto Label2; /* W1072 */
|
15
|
+
|
16
|
+
Label1:
|
17
|
+
i = 10;
|
18
|
+
Label2:
|
19
|
+
i = 20;
|
20
|
+
|
21
|
+
return i;
|
22
|
+
}
|
23
|
+
"""
|
24
|
+
When I successfully run `adlint W1072.c` on noarch
|
25
|
+
Then the output should exactly match with:
|
26
|
+
| mesg | line | column |
|
27
|
+
| W0629 | 1 | 12 |
|
28
|
+
| W1072 | 4 | 9 |
|
29
|
+
| W1072 | 7 | 5 |
|
30
|
+
| W0628 | 1 | 12 |
|
31
|
+
|
32
|
+
# vim:ts=2:sw=2:sts=2:et:
|
data/lib/adlint/c/interp.rb
CHANGED
@@ -354,6 +354,9 @@ module C #:nodoc:
|
|
354
354
|
def_plugin_and_notifier :return_stmt_evaled,
|
355
355
|
:return_statement, :result_variable
|
356
356
|
|
357
|
+
# NOTE: Notified when the interpreter evaluates an implicit return.
|
358
|
+
def_plugin_and_notifier :implicit_return_evaled
|
359
|
+
|
357
360
|
# NOTE: Notified when the interpreter evaluates a controlling expression of
|
358
361
|
# the if-statement.
|
359
362
|
def_plugin_and_notifier :if_ctrlexpr_evaled, :if_statement, :ctrlexpr_value
|
@@ -816,16 +819,7 @@ module C #:nodoc:
|
|
816
819
|
|
817
820
|
reset_environment
|
818
821
|
resolve_unresolved_type(node)
|
819
|
-
|
820
|
-
if function = function_named(node.identifier.value)
|
821
|
-
function.declarations_and_definitions.each do |decl_or_def|
|
822
|
-
decl_or_def.mark_as_referred_by(node.identifier)
|
823
|
-
end
|
824
|
-
function.declarations_and_definitions.push(node)
|
825
|
-
else
|
826
|
-
function = define_explicit_function(node)
|
827
|
-
end
|
828
|
-
|
822
|
+
function = lookup_or_define_function(node)
|
829
823
|
notify_function_defined(node, function)
|
830
824
|
|
831
825
|
begin
|
@@ -838,6 +832,7 @@ module C #:nodoc:
|
|
838
832
|
|
839
833
|
BreakEvent.catch do
|
840
834
|
node.function_body.block_items.each { |item| interpret(item) }
|
835
|
+
notify_implicit_return_evaled
|
841
836
|
end
|
842
837
|
|
843
838
|
notify_block_ended(node.function_body)
|
@@ -847,6 +842,18 @@ module C #:nodoc:
|
|
847
842
|
interpreter._leave_function(node)
|
848
843
|
end
|
849
844
|
end
|
845
|
+
|
846
|
+
def lookup_or_define_function(function_definition)
|
847
|
+
if function = function_named(function_definition.identifier.value)
|
848
|
+
function.declarations_and_definitions.each do |decl_or_def|
|
849
|
+
decl_or_def.mark_as_referred_by(function_definition.identifier)
|
850
|
+
end
|
851
|
+
function.declarations_and_definitions.push(function_definition)
|
852
|
+
else
|
853
|
+
function = define_explicit_function(function_definition)
|
854
|
+
end
|
855
|
+
function
|
856
|
+
end
|
850
857
|
end
|
851
858
|
|
852
859
|
class StatementInterpreter < SubInterpreter
|
data/lib/adlint/c/mediator.rb
CHANGED
@@ -234,6 +234,7 @@ module C #:nodoc:
|
|
234
234
|
def_delegator :interpreter, :notify_c99_for_stmt_ended
|
235
235
|
def_delegator :interpreter, :notify_goto_stmt_evaled
|
236
236
|
def_delegator :interpreter, :notify_return_stmt_evaled
|
237
|
+
def_delegator :interpreter, :notify_implicit_return_evaled
|
237
238
|
def_delegator :interpreter, :notify_if_ctrlexpr_evaled
|
238
239
|
def_delegator :interpreter, :notify_if_else_ctrlexpr_evaled
|
239
240
|
def_delegator :interpreter, :notify_switch_ctrlexpr_evaled
|
@@ -102,6 +102,20 @@ module C #:nodoc:
|
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
|
+
class W0645 < PassiveMessageDetection
|
106
|
+
def initialize(context)
|
107
|
+
super
|
108
|
+
visitor = context[:c_visitor]
|
109
|
+
visitor.enter_kandr_function_definition += method(:check)
|
110
|
+
end
|
111
|
+
|
112
|
+
def check(node)
|
113
|
+
if node.type.parameter_types.any? { |type| type.void? }
|
114
|
+
W(:W0645, node.location)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
105
119
|
class W0685 < W0573
|
106
120
|
def check(function_call_expression, function, arg_variables,
|
107
121
|
result_variable)
|
@@ -142,6 +156,35 @@ module C #:nodoc:
|
|
142
156
|
end
|
143
157
|
end
|
144
158
|
|
159
|
+
class W0697 < PassiveMessageDetection
|
160
|
+
def initialize(context)
|
161
|
+
super
|
162
|
+
interp = context[:c_interpreter]
|
163
|
+
interp.on_function_started += method(:start_function)
|
164
|
+
interp.on_function_ended += method(:end_function)
|
165
|
+
interp.on_implicit_return_evaled += method(:check_implicit_return)
|
166
|
+
@current_function = nil
|
167
|
+
end
|
168
|
+
|
169
|
+
private
|
170
|
+
def start_function(function_definition, function)
|
171
|
+
@current_function = function_definition
|
172
|
+
end
|
173
|
+
|
174
|
+
def end_function(function_definition, function)
|
175
|
+
@current_function = nil
|
176
|
+
end
|
177
|
+
|
178
|
+
def check_implicit_return
|
179
|
+
return unless @current_function
|
180
|
+
|
181
|
+
unless @current_function.type.return_type.void?
|
182
|
+
W(:W0697,
|
183
|
+
@current_function.location, @current_function.identifier.value)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
145
188
|
class W0698 < PassiveMessageDetection
|
146
189
|
def initialize(context)
|
147
190
|
super
|
@@ -187,6 +230,45 @@ module C #:nodoc:
|
|
187
230
|
end
|
188
231
|
end
|
189
232
|
|
233
|
+
class W0700 < PassiveMessageDetection
|
234
|
+
def initialize(context)
|
235
|
+
super
|
236
|
+
interp = context[:c_interpreter]
|
237
|
+
interp.on_function_started += method(:start_function)
|
238
|
+
interp.on_function_ended += method(:end_function)
|
239
|
+
interp.on_return_stmt_evaled += method(:check_explicit_return)
|
240
|
+
interp.on_implicit_return_evaled += method(:check_implicit_return)
|
241
|
+
@current_function = nil
|
242
|
+
end
|
243
|
+
|
244
|
+
private
|
245
|
+
def start_function(function_definition, function)
|
246
|
+
@current_function = function_definition
|
247
|
+
end
|
248
|
+
|
249
|
+
def end_function(function_definition, function)
|
250
|
+
@current_function = nil
|
251
|
+
end
|
252
|
+
|
253
|
+
def check_explicit_return(return_stmt, result_variable)
|
254
|
+
return unless @current_function
|
255
|
+
|
256
|
+
if @current_function.implicitly_typed? && return_stmt.expression.nil?
|
257
|
+
W(:W0700,
|
258
|
+
@current_function.location, @current_function.identifier.value)
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def check_implicit_return
|
263
|
+
return unless @current_function
|
264
|
+
|
265
|
+
if @current_function.implicitly_typed?
|
266
|
+
W(:W0700,
|
267
|
+
@current_function.location, @current_function.identifier.value)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
190
272
|
class W0711 < PassiveMessageDetection
|
191
273
|
def initialize(context)
|
192
274
|
super
|
@@ -552,5 +634,145 @@ module C #:nodoc:
|
|
552
634
|
end
|
553
635
|
end
|
554
636
|
|
637
|
+
class W1066 < PassiveMessageDetection
|
638
|
+
def initialize(context)
|
639
|
+
super
|
640
|
+
@interp = context[:c_interpreter]
|
641
|
+
@interp.on_explicit_conv_performed += method(:check)
|
642
|
+
@interp.on_function_started += method(:clear_rvalues)
|
643
|
+
@interp.on_additive_expr_evaled += method(:handle_additive)
|
644
|
+
@interp.on_multiplicative_expr_evaled += method(:handle_multiplicative)
|
645
|
+
@rvalues = nil
|
646
|
+
end
|
647
|
+
|
648
|
+
private
|
649
|
+
def check(cast_expression, original_variable, result_variable)
|
650
|
+
return unless @rvalues
|
651
|
+
return unless original_variable.type.floating?
|
652
|
+
|
653
|
+
case expression = @rvalues[original_variable]
|
654
|
+
when AdditiveExpression, MultiplicativeExpression
|
655
|
+
if original_variable.type.same_as?(from_type) &&
|
656
|
+
result_variable.type.same_as?(to_type)
|
657
|
+
W(message_id, expression.location)
|
658
|
+
end
|
659
|
+
end
|
660
|
+
end
|
661
|
+
|
662
|
+
def clear_rvalues(function_definition, function)
|
663
|
+
@rvalues = {}
|
664
|
+
end
|
665
|
+
|
666
|
+
def handle_additive(additive_expression,
|
667
|
+
lhs_variable, rhs_variable, result_variable)
|
668
|
+
memorize_rvalue_derivation(result_variable, additive_expression)
|
669
|
+
end
|
670
|
+
|
671
|
+
def handle_multiplicative(multiplicative_expression,
|
672
|
+
lhs_variable, rhs_variable, result_variable)
|
673
|
+
return if multiplicative_expression.operator.type == "%"
|
674
|
+
memorize_rvalue_derivation(result_variable, multiplicative_expression)
|
675
|
+
end
|
676
|
+
|
677
|
+
def memorize_rvalue_derivation(rvalue_holder, expression)
|
678
|
+
@rvalues[rvalue_holder] = expression if @rvalues
|
679
|
+
end
|
680
|
+
|
681
|
+
def from_type
|
682
|
+
@interp.float_type
|
683
|
+
end
|
684
|
+
|
685
|
+
def to_type
|
686
|
+
@interp.double_type
|
687
|
+
end
|
688
|
+
|
689
|
+
def message_id
|
690
|
+
self.class.name.sub(/\A.*::/, "").intern
|
691
|
+
end
|
692
|
+
end
|
693
|
+
|
694
|
+
class W1067 < W1066
|
695
|
+
private
|
696
|
+
def from_type
|
697
|
+
@interp.float_type
|
698
|
+
end
|
699
|
+
|
700
|
+
def to_type
|
701
|
+
@interp.long_double_type
|
702
|
+
end
|
703
|
+
end
|
704
|
+
|
705
|
+
class W1068 < W1066
|
706
|
+
private
|
707
|
+
def from_type
|
708
|
+
@interp.double_type
|
709
|
+
end
|
710
|
+
|
711
|
+
def to_type
|
712
|
+
@interp.long_double_type
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
class W1069 < PassiveMessageDetection
|
717
|
+
def initialize(context)
|
718
|
+
super
|
719
|
+
visitor = context[:c_visitor]
|
720
|
+
visitor.enter_ansi_function_definition += method(:enter_function)
|
721
|
+
visitor.leave_ansi_function_definition += method(:leave_function)
|
722
|
+
visitor.enter_kandr_function_definition += method(:enter_function)
|
723
|
+
visitor.leave_kandr_function_definition += method(:leave_function)
|
724
|
+
visitor.enter_if_else_statement += method(:enter_if_else_statement)
|
725
|
+
visitor.leave_if_else_statement += method(:leave_if_else_statement)
|
726
|
+
@if_else_statement_chain = []
|
727
|
+
end
|
728
|
+
|
729
|
+
private
|
730
|
+
def enter_function(function_definition)
|
731
|
+
@if_else_statement_chain = []
|
732
|
+
end
|
733
|
+
|
734
|
+
def leave_function(function_definition)
|
735
|
+
@if_else_statement_chain = []
|
736
|
+
end
|
737
|
+
|
738
|
+
def enter_if_else_statement(node)
|
739
|
+
@if_else_statement_chain.push(node)
|
740
|
+
if node.else_statement.kind_of?(IfStatement)
|
741
|
+
W(:W1069, @if_else_statement_chain.first.location)
|
742
|
+
end
|
743
|
+
end
|
744
|
+
|
745
|
+
def leave_if_else_statement(node)
|
746
|
+
@if_else_statement_chain.pop
|
747
|
+
end
|
748
|
+
end
|
749
|
+
|
750
|
+
class W1070 < W0781
|
751
|
+
private
|
752
|
+
def check(node)
|
753
|
+
if exec_path_num = @exec_path_nums.last and exec_path_num == 2
|
754
|
+
W(:W1070, node.location)
|
755
|
+
end
|
756
|
+
@exec_path_nums.pop
|
757
|
+
end
|
758
|
+
|
759
|
+
def add_exec_path(node)
|
760
|
+
@exec_path_nums[-1] += 1
|
761
|
+
end
|
762
|
+
end
|
763
|
+
|
764
|
+
class W1072 < PassiveMessageDetection
|
765
|
+
def initialize(context)
|
766
|
+
super
|
767
|
+
visitor = context[:c_visitor]
|
768
|
+
visitor.enter_goto_statement += method(:warn_goto)
|
769
|
+
end
|
770
|
+
|
771
|
+
private
|
772
|
+
def warn_goto(node)
|
773
|
+
W(:W1072, node.location)
|
774
|
+
end
|
775
|
+
end
|
776
|
+
|
555
777
|
end
|
556
778
|
end
|
data/lib/adlint/c/phase.rb
CHANGED
@@ -596,6 +596,7 @@ module C #:nodoc:
|
|
596
596
|
W0639.new(context),
|
597
597
|
W0640.new(context),
|
598
598
|
W0642.new(context),
|
599
|
+
W0645.new(context),
|
599
600
|
W0653.new(context),
|
600
601
|
W0654.new(context),
|
601
602
|
W0655.new(context),
|
@@ -630,8 +631,10 @@ module C #:nodoc:
|
|
630
631
|
W0684.new(context),
|
631
632
|
W0685.new(context),
|
632
633
|
W0686.new(context),
|
634
|
+
W0697.new(context),
|
633
635
|
W0698.new(context),
|
634
636
|
W0699.new(context),
|
637
|
+
W0700.new(context),
|
635
638
|
W0703.new(context),
|
636
639
|
W0704.new(context),
|
637
640
|
W0705.new(context),
|
@@ -745,6 +748,12 @@ module C #:nodoc:
|
|
745
748
|
W1063.new(context),
|
746
749
|
W1064.new(context),
|
747
750
|
W1065.new(context),
|
751
|
+
W1066.new(context),
|
752
|
+
W1067.new(context),
|
753
|
+
W1068.new(context),
|
754
|
+
W1069.new(context),
|
755
|
+
W1070.new(context),
|
756
|
+
W1072.new(context),
|
748
757
|
W9001.new(context),
|
749
758
|
W9003.new(context)
|
750
759
|
]
|
data/lib/adlint/c/type.rb
CHANGED
@@ -7562,21 +7562,22 @@ module C #:nodoc:
|
|
7562
7562
|
end
|
7563
7563
|
|
7564
7564
|
def qualify_type(type, type_qualifiers, declarator, interpreter = nil)
|
7565
|
-
type_qualifiers.
|
7565
|
+
cvr_qualifiers = type_qualifiers.map { |token|
|
7566
7566
|
case token.type
|
7567
|
-
when :CONST
|
7568
|
-
|
7569
|
-
|
7570
|
-
|
7571
|
-
when :RESTRICT
|
7572
|
-
# TODO: Should support C99 features.
|
7567
|
+
when :CONST then :const
|
7568
|
+
when :VOLATILE then :volatile
|
7569
|
+
else
|
7570
|
+
# TODO: Should support C99 `restrict' qualifier.
|
7573
7571
|
end
|
7574
|
-
|
7575
|
-
|
7576
|
-
return type unless declarator
|
7572
|
+
}.compact
|
7573
|
+
type = qualified_type(type, *cvr_qualifiers) unless cvr_qualifiers.empty?
|
7577
7574
|
|
7578
|
-
|
7579
|
-
|
7575
|
+
if declarator
|
7576
|
+
decl_interp = DeclaratorInterpreter.new(self, interpreter, type)
|
7577
|
+
declarator.accept(decl_interp)
|
7578
|
+
else
|
7579
|
+
type
|
7580
|
+
end
|
7580
7581
|
end
|
7581
7582
|
|
7582
7583
|
def create_members(struct_declarations)
|