adlint 1.14.0 → 1.16.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 +265 -0
- data/MANIFEST +15 -0
- data/NEWS +30 -4
- data/etc/conf.d/noarch/adlint_all_bat.erb +1 -1
- data/etc/mesg.d/en_US/messages.yml +3 -3
- data/etc/mesg.d/ja_JP/messages.yml +3 -3
- data/features/message_detection/W0001.feature +2 -0
- data/features/message_detection/W0007.feature +8 -0
- data/features/message_detection/W0010.feature +4 -1
- data/features/message_detection/W0013.feature +8 -0
- data/features/message_detection/W0093.feature +3 -0
- data/features/message_detection/W0104.feature +7 -0
- data/features/message_detection/W0643.feature +80 -0
- data/features/message_detection/W0646.feature +115 -0
- data/features/message_detection/W0691.feature +100 -0
- data/features/message_detection/W0692.feature +32 -0
- data/features/message_detection/W0694.feature +128 -0
- data/features/message_detection/W0716.feature +3 -0
- data/features/message_detection/W0717.feature +3 -0
- data/features/message_detection/W0718.feature +3 -0
- data/features/message_detection/W0723.feature +2 -0
- data/features/message_detection/W0732.feature +3 -0
- data/features/message_detection/W0733.feature +3 -0
- data/features/message_detection/W0734.feature +8 -0
- data/features/message_detection/W0735.feature +8 -0
- data/features/message_detection/W0805.feature +92 -0
- data/features/message_detection/W0811.feature +79 -0
- data/features/message_detection/W1031.feature +7 -0
- data/features/message_detection/W1040.feature +89 -0
- data/features/message_detection/W1041.feature +15 -0
- data/features/message_detection/W1046.feature +60 -0
- data/features/message_detection/W1052.feature +3 -0
- data/features/message_detection/W1066.feature +3 -0
- data/features/message_detection/W1067.feature +3 -0
- data/features/message_detection/W1068.feature +3 -0
- data/features/message_detection/W1069.feature +5 -0
- data/features/message_detection/W1070.feature +6 -0
- data/features/message_detection/W1072.feature +1 -0
- data/features/message_detection/W1073.feature +145 -0
- data/features/message_detection/W1074.feature +139 -0
- data/features/message_detection/W1075.feature +86 -0
- data/features/message_detection/W1076.feature +66 -0
- data/features/message_detection/W1077.feature +105 -0
- data/features/message_detection/W9003.feature +4 -0
- data/lib/adlint/c/ctrlexpr.rb +3 -0
- data/lib/adlint/c/interp.rb +11 -5
- data/lib/adlint/c/lexer.rb +14 -3
- data/lib/adlint/c/message.rb +192 -0
- data/lib/adlint/c/parser.rb +19 -3
- data/lib/adlint/c/parser.y +18 -2
- data/lib/adlint/c/phase.rb +19 -6
- data/lib/adlint/c/syntax.rb +6 -0
- data/lib/adlint/c/type.rb +5 -1
- data/lib/adlint/cpp/constexpr.rb +3 -3
- data/lib/adlint/cpp/constexpr.y +3 -3
- data/lib/adlint/cpp/eval.rb +60 -86
- data/lib/adlint/cpp/lexer.rb +82 -28
- data/lib/adlint/cpp/macro.rb +64 -35
- data/lib/adlint/cpp/message.rb +137 -4
- data/lib/adlint/cpp/phase.rb +8 -0
- data/lib/adlint/cpp/syntax.rb +25 -0
- data/lib/adlint/lang.rb +2 -1
- 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 +102 -85
- data/share/doc/users_guide_en.texi +85 -69
- data/share/doc/users_guide_ja.html +102 -94
- data/share/doc/users_guide_ja.texi +85 -77
- metadata +17 -2
@@ -0,0 +1,105 @@
|
|
1
|
+
Feature: W1077
|
2
|
+
|
3
|
+
W1077 detects that an array variable declared without number of its elements.
|
4
|
+
|
5
|
+
Scenario: 1-dimensional array variable declaration without size
|
6
|
+
Given a target source named "W1077.c" with:
|
7
|
+
"""
|
8
|
+
extern int a[]; /* W1077 */
|
9
|
+
"""
|
10
|
+
When I successfully run `adlint W1077.c` on noarch
|
11
|
+
Then the output should exactly match with:
|
12
|
+
| mesg | line | column |
|
13
|
+
| W0118 | 1 | 12 |
|
14
|
+
| W1077 | 1 | 12 |
|
15
|
+
|
16
|
+
Scenario: 1-dimensional array variable declaration with size
|
17
|
+
Given a target source named "W1077.c" with:
|
18
|
+
"""
|
19
|
+
extern int a[3]; /* OK */
|
20
|
+
"""
|
21
|
+
When I successfully run `adlint W1077.c` on noarch
|
22
|
+
Then the output should exactly match with:
|
23
|
+
| mesg | line | column |
|
24
|
+
| W0118 | 1 | 12 |
|
25
|
+
|
26
|
+
Scenario: 2-dimensional array variable declaration without all sizes
|
27
|
+
Given a target source named "W1077.c" with:
|
28
|
+
"""
|
29
|
+
extern int a[][]; /* W1077 */
|
30
|
+
"""
|
31
|
+
When I successfully run `adlint W1077.c` on noarch
|
32
|
+
Then the output should exactly match with:
|
33
|
+
| mesg | line | column |
|
34
|
+
| W0118 | 1 | 12 |
|
35
|
+
| W1028 | 1 | 12 |
|
36
|
+
| W1077 | 1 | 12 |
|
37
|
+
|
38
|
+
Scenario: 2-dimensional array variable declaration without outer size
|
39
|
+
Given a target source named "W1077.c" with:
|
40
|
+
"""
|
41
|
+
extern int a[][3]; /* W1077 */
|
42
|
+
"""
|
43
|
+
When I successfully run `adlint W1077.c` on noarch
|
44
|
+
Then the output should exactly match with:
|
45
|
+
| mesg | line | column |
|
46
|
+
| W0118 | 1 | 12 |
|
47
|
+
| W1077 | 1 | 12 |
|
48
|
+
|
49
|
+
Scenario: 2-dimensional array variable declaration with all sizes
|
50
|
+
Given a target source named "W1077.c" with:
|
51
|
+
"""
|
52
|
+
extern int a[2][3]; /* OK */
|
53
|
+
"""
|
54
|
+
When I successfully run `adlint W1077.c` on noarch
|
55
|
+
Then the output should exactly match with:
|
56
|
+
| mesg | line | column |
|
57
|
+
| W0118 | 1 | 12 |
|
58
|
+
|
59
|
+
Scenario: 3-dimensional array variable declaration without all sizes
|
60
|
+
Given a target source named "W1077.c" with:
|
61
|
+
"""
|
62
|
+
extern int a[][][]; /* W1077 */
|
63
|
+
"""
|
64
|
+
When I successfully run `adlint W1077.c` on noarch
|
65
|
+
Then the output should exactly match with:
|
66
|
+
| mesg | line | column |
|
67
|
+
| W0118 | 1 | 12 |
|
68
|
+
| W1028 | 1 | 12 |
|
69
|
+
| W1077 | 1 | 12 |
|
70
|
+
|
71
|
+
Scenario: 3-dimensional array variable declaration with all sizes
|
72
|
+
Given a target source named "W1077.c" with:
|
73
|
+
"""
|
74
|
+
extern int a[1][2][3]; /* OK */
|
75
|
+
"""
|
76
|
+
When I successfully run `adlint W1077.c` on noarch
|
77
|
+
Then the output should exactly match with:
|
78
|
+
| mesg | line | column |
|
79
|
+
| W0118 | 1 | 12 |
|
80
|
+
|
81
|
+
Scenario: cv-qualified 3-dimensional array variable declaration without all
|
82
|
+
sizes
|
83
|
+
Given a target source named "W1077.c" with:
|
84
|
+
"""
|
85
|
+
extern const int a[][][]; /* W1077 */
|
86
|
+
"""
|
87
|
+
When I successfully run `adlint W1077.c` on noarch
|
88
|
+
Then the output should exactly match with:
|
89
|
+
| mesg | line | column |
|
90
|
+
| W0118 | 1 | 18 |
|
91
|
+
| W1028 | 1 | 18 |
|
92
|
+
| W1077 | 1 | 18 |
|
93
|
+
|
94
|
+
Scenario: cv-qualified 3-dimensional array variable declaration with all
|
95
|
+
sizes
|
96
|
+
Given a target source named "W1077.c" with:
|
97
|
+
"""
|
98
|
+
extern const int a[1][2][3]; /* OK */
|
99
|
+
"""
|
100
|
+
When I successfully run `adlint W1077.c` on noarch
|
101
|
+
Then the output should exactly match with:
|
102
|
+
| mesg | line | column |
|
103
|
+
| W0118 | 1 | 18 |
|
104
|
+
|
105
|
+
# vim:ts=2:sw=2:sts=2:et:
|
@@ -22,6 +22,7 @@ Feature: W9003
|
|
22
22
|
And the output should exactly match with:
|
23
23
|
| mesg | line | column |
|
24
24
|
| W0118 | 4 | 13 |
|
25
|
+
| W1076 | 6 | 13 |
|
25
26
|
| W9003 | 8 | 9 |
|
26
27
|
| W0728 | 8 | 9 |
|
27
28
|
| W0629 | 6 | 13 |
|
@@ -44,6 +45,7 @@ Feature: W9003
|
|
44
45
|
And the output should exactly match with:
|
45
46
|
| mesg | line | column |
|
46
47
|
| W0118 | 3 | 13 |
|
48
|
+
| W1076 | 5 | 13 |
|
47
49
|
| W9003 | 7 | 9 |
|
48
50
|
| W1059 | 7 | 9 |
|
49
51
|
| W0629 | 5 | 13 |
|
@@ -66,6 +68,7 @@ Feature: W9003
|
|
66
68
|
And the output should exactly match with:
|
67
69
|
| mesg | line | column |
|
68
70
|
| W0118 | 3 | 13 |
|
71
|
+
| W1076 | 5 | 13 |
|
69
72
|
| W9003 | 7 | 9 |
|
70
73
|
| W1053 | 7 | 9 |
|
71
74
|
| W0629 | 5 | 13 |
|
@@ -116,6 +119,7 @@ Feature: W9003
|
|
116
119
|
Then the output should match with /6:.*:W9003/
|
117
120
|
And the output should exactly match with:
|
118
121
|
| mesg | line | column |
|
122
|
+
| W1076 | 3 | 12 |
|
119
123
|
| W0727 | 6 | 20 |
|
120
124
|
| W9003 | 6 | 20 |
|
121
125
|
| W9003 | 6 | 18 |
|
data/lib/adlint/c/ctrlexpr.rb
CHANGED
@@ -787,6 +787,9 @@ module C #:nodoc:
|
|
787
787
|
__NOTREACHED__
|
788
788
|
end
|
789
789
|
|
790
|
+
notify_variable_value_referred(@node, lhs_var)
|
791
|
+
notify_variable_value_referred(@node, rhs_var)
|
792
|
+
|
790
793
|
case @operator
|
791
794
|
when Operator::EQ, Operator::NE
|
792
795
|
notify_equality_expr_evaled(@node, lhs_conv, rhs_conv, result)
|
data/lib/adlint/c/interp.rb
CHANGED
@@ -162,15 +162,15 @@ module C #:nodoc:
|
|
162
162
|
# a constant temporary variable.
|
163
163
|
def_plugin_and_notifier :constant_referred, :constant_specifier, :variable
|
164
164
|
|
165
|
-
# NOTE: Notified when the interpreter
|
165
|
+
# NOTE: Notified when the interpreter refers to a value of a variable while
|
166
166
|
# evaluating an expression.
|
167
167
|
def_plugin_and_notifier :variable_value_referred, :expression, :variable
|
168
168
|
|
169
|
-
# NOTE: Notified when the interpreter
|
170
|
-
# evaluating an expression.
|
169
|
+
# NOTE: Notified when the interpreter overwrites a value of a variable
|
170
|
+
# while evaluating an expression.
|
171
171
|
def_plugin_and_notifier :variable_value_updated, :expression, :variable
|
172
172
|
|
173
|
-
# NOTE: Notified when the interpreter
|
173
|
+
# NOTE: Notified when the interpreter refers to a function object while
|
174
174
|
# evaluating an expression.
|
175
175
|
def_plugin_and_notifier :function_referred, :expression, :function
|
176
176
|
|
@@ -421,7 +421,7 @@ module C #:nodoc:
|
|
421
421
|
# NOTE: Notified when the interpreter ends execution of a translation-unit.
|
422
422
|
def_plugin_and_notifier :translation_unit_ended, :translation_unit
|
423
423
|
|
424
|
-
# NOTE: Notified when control reaches to a sequence-point.
|
424
|
+
# NOTE: Notified when the control reaches to a sequence-point.
|
425
425
|
def_plugin_and_notifier :sequence_point_reached, :sequence_point
|
426
426
|
|
427
427
|
def execute(node, *options)
|
@@ -1582,6 +1582,12 @@ module C #:nodoc:
|
|
1582
1582
|
when then_var && else_var
|
1583
1583
|
result_val = then_var.value.single_value_unified_with(else_var.value)
|
1584
1584
|
result = temporary_variable(then_var.type, result_val)
|
1585
|
+
# FIXME: Not to over-warn about discarding a function return value.
|
1586
|
+
# Because the unified result is a new temporary variable, it is
|
1587
|
+
# impossible to relate a reference of the unified result and a
|
1588
|
+
# reference of the 2nd or 3rd expression's value.
|
1589
|
+
notify_variable_value_referred(node, then_var)
|
1590
|
+
notify_variable_value_referred(node, else_var)
|
1585
1591
|
when then_var
|
1586
1592
|
result = then_var
|
1587
1593
|
when else_var
|
data/lib/adlint/c/lexer.rb
CHANGED
@@ -30,6 +30,7 @@
|
|
30
30
|
#++
|
31
31
|
|
32
32
|
require "adlint/lexer"
|
33
|
+
require "adlint/util"
|
33
34
|
require "adlint/c/scanner"
|
34
35
|
require "adlint/c/scope"
|
35
36
|
|
@@ -50,6 +51,10 @@ module C #:nodoc:
|
|
50
51
|
|
51
52
|
attr_reader :translation_unit_fpath
|
52
53
|
|
54
|
+
extend Pluggable
|
55
|
+
|
56
|
+
def_plugin :on_string_literals_concatenated
|
57
|
+
|
53
58
|
def add_typedef_name(token)
|
54
59
|
@typedef_names.add(token.value)
|
55
60
|
end
|
@@ -140,9 +145,11 @@ module C #:nodoc:
|
|
140
145
|
until context.content.empty?
|
141
146
|
next_token = tokenize(context)
|
142
147
|
if next_token.type == :STRING_LITERAL
|
143
|
-
|
144
|
-
|
145
|
-
|
148
|
+
result = token.class.new(token.type, token.value.sub(/"\z/, "") +
|
149
|
+
next_token.value.sub(/\AL?"/, ""),
|
150
|
+
token.location)
|
151
|
+
notify_string_literals_concatenated(token, next_token, result)
|
152
|
+
return result
|
146
153
|
else
|
147
154
|
@next_token = next_token
|
148
155
|
break
|
@@ -210,6 +217,10 @@ module C #:nodoc:
|
|
210
217
|
nil
|
211
218
|
end
|
212
219
|
end
|
220
|
+
|
221
|
+
def notify_string_literals_concatenated(former, latter, result)
|
222
|
+
on_string_literals_concatenated.invoke(former, latter, result)
|
223
|
+
end
|
213
224
|
end
|
214
225
|
|
215
226
|
class ScopedNameSet
|
data/lib/adlint/c/message.rb
CHANGED
@@ -11561,6 +11561,22 @@ module C #:nodoc:
|
|
11561
11561
|
end
|
11562
11562
|
end
|
11563
11563
|
|
11564
|
+
class W0646 < PassiveMessageDetection
|
11565
|
+
def initialize(context)
|
11566
|
+
super
|
11567
|
+
parser = context[:c_parser]
|
11568
|
+
parser.on_string_literals_concatenated += method(:check)
|
11569
|
+
end
|
11570
|
+
|
11571
|
+
private
|
11572
|
+
def check(former, latter, *)
|
11573
|
+
if former.value =~ /\A"/ && latter.value =~ /\AL"/i or
|
11574
|
+
former.value =~ /\AL"/i && latter.value =~ /\A"/
|
11575
|
+
W(:W0646, latter.location)
|
11576
|
+
end
|
11577
|
+
end
|
11578
|
+
end
|
11579
|
+
|
11564
11580
|
class W0653 < PassiveMessageDetection
|
11565
11581
|
def initialize(context)
|
11566
11582
|
super
|
@@ -12102,6 +12118,21 @@ module C #:nodoc:
|
|
12102
12118
|
end
|
12103
12119
|
end
|
12104
12120
|
|
12121
|
+
class W0694 < PassiveMessageDetection
|
12122
|
+
def initialize(context)
|
12123
|
+
super
|
12124
|
+
interp = context[:c_interpreter]
|
12125
|
+
interp.on_function_call_expr_evaled += method(:check)
|
12126
|
+
end
|
12127
|
+
|
12128
|
+
private
|
12129
|
+
def check(function_call_expression, function, *)
|
12130
|
+
if function.named? && function.name == "assert"
|
12131
|
+
W(:W0694, function_call_expression.location)
|
12132
|
+
end
|
12133
|
+
end
|
12134
|
+
end
|
12135
|
+
|
12105
12136
|
class W0703 < PassiveMessageDetection
|
12106
12137
|
def initialize(context)
|
12107
12138
|
super
|
@@ -14994,6 +15025,167 @@ module C #:nodoc:
|
|
14994
15025
|
end
|
14995
15026
|
end
|
14996
15027
|
|
15028
|
+
class W1073 < PassiveMessageDetection
|
15029
|
+
def initialize(context)
|
15030
|
+
super
|
15031
|
+
interp = context[:c_interpreter]
|
15032
|
+
interp.on_function_started += method(:enter_function)
|
15033
|
+
interp.on_function_ended += method(:leave_function)
|
15034
|
+
interp.on_function_call_expr_evaled += method(:add_return_value)
|
15035
|
+
interp.on_variable_value_referred += method(:refer_return_value)
|
15036
|
+
@current_function = nil
|
15037
|
+
end
|
15038
|
+
|
15039
|
+
private
|
15040
|
+
def enter_function(function_definition, *)
|
15041
|
+
@current_function = function_definition
|
15042
|
+
@return_values = {}
|
15043
|
+
end
|
15044
|
+
|
15045
|
+
def leave_function(*)
|
15046
|
+
if @current_function
|
15047
|
+
@return_values.each_value do |retval|
|
15048
|
+
unless retval[0]
|
15049
|
+
fun_name = retval[2].named? ? retval[2].name : "(anonymous)"
|
15050
|
+
W(:W1073, retval[1].location, fun_name)
|
15051
|
+
end
|
15052
|
+
end
|
15053
|
+
end
|
15054
|
+
@current_function = nil
|
15055
|
+
@return_values = nil
|
15056
|
+
end
|
15057
|
+
|
15058
|
+
def add_return_value(expr, function, arg_variables, result)
|
15059
|
+
if @current_function
|
15060
|
+
unless function.type.return_type.void?
|
15061
|
+
@return_values[result] = [false, expr, function]
|
15062
|
+
end
|
15063
|
+
end
|
15064
|
+
end
|
15065
|
+
|
15066
|
+
def refer_return_value(expr, variable)
|
15067
|
+
if @current_function
|
15068
|
+
if retval = @return_values[variable]
|
15069
|
+
retval[0] = true
|
15070
|
+
end
|
15071
|
+
end
|
15072
|
+
end
|
15073
|
+
end
|
15074
|
+
|
15075
|
+
class W1074 < PassiveMessageDetection
|
15076
|
+
def initialize(context)
|
15077
|
+
super
|
15078
|
+
visitor = context[:c_visitor]
|
15079
|
+
visitor.enter_sizeof_expression += method(:check)
|
15080
|
+
end
|
15081
|
+
|
15082
|
+
private
|
15083
|
+
def check(sizeof_expression)
|
15084
|
+
if sizeof_expression.operand.have_side_effect?
|
15085
|
+
W(:W1074, sizeof_expression.operand.location)
|
15086
|
+
end
|
15087
|
+
end
|
15088
|
+
end
|
15089
|
+
|
15090
|
+
class W1075 < PassiveMessageDetection
|
15091
|
+
def initialize(context)
|
15092
|
+
super
|
15093
|
+
interp = context[:c_interpreter]
|
15094
|
+
interp.on_variable_declared += method(:declare_variable)
|
15095
|
+
interp.on_variable_defined += method(:define_variable)
|
15096
|
+
interp.on_function_declared += method(:declare_function)
|
15097
|
+
interp.on_function_defined += method(:define_function)
|
15098
|
+
end
|
15099
|
+
|
15100
|
+
private
|
15101
|
+
def declare_variable(variable_declaration, variable)
|
15102
|
+
if variable.named?
|
15103
|
+
if variable.declared_as_static?
|
15104
|
+
sc_specifier = variable_declaration.storage_class_specifier
|
15105
|
+
unless sc_specifier && sc_specifier.type == :STATIC
|
15106
|
+
W(:W1075, variable_declaration.location, variable.name)
|
15107
|
+
end
|
15108
|
+
end
|
15109
|
+
end
|
15110
|
+
end
|
15111
|
+
|
15112
|
+
def define_variable(variable_definition, variable)
|
15113
|
+
if variable.named?
|
15114
|
+
if variable.declared_as_static?
|
15115
|
+
sc_specifier = variable_definition.storage_class_specifier
|
15116
|
+
unless sc_specifier && sc_specifier.type == :STATIC
|
15117
|
+
W(:W1075, variable_definition.location, variable.name)
|
15118
|
+
end
|
15119
|
+
end
|
15120
|
+
end
|
15121
|
+
end
|
15122
|
+
|
15123
|
+
def declare_function(function_declaration, function)
|
15124
|
+
if function.named?
|
15125
|
+
if function.declared_as_static?
|
15126
|
+
sc_specifier = function_declaration.storage_class_specifier
|
15127
|
+
unless sc_specifier && sc_specifier.type == :STATIC
|
15128
|
+
W(:W1075, function_declaration.location, function.name)
|
15129
|
+
end
|
15130
|
+
end
|
15131
|
+
end
|
15132
|
+
end
|
15133
|
+
|
15134
|
+
def define_function(function_definition, function)
|
15135
|
+
if function.named?
|
15136
|
+
if function.declared_as_static?
|
15137
|
+
sc_specifier = function_definition.storage_class_specifier
|
15138
|
+
unless sc_specifier && sc_specifier.type == :STATIC
|
15139
|
+
W(:W1075, function_definition.location, function.name)
|
15140
|
+
end
|
15141
|
+
end
|
15142
|
+
end
|
15143
|
+
end
|
15144
|
+
end
|
15145
|
+
|
15146
|
+
class W1076 < PassiveMessageDetection
|
15147
|
+
def initialize(context)
|
15148
|
+
super
|
15149
|
+
interp = context[:c_interpreter]
|
15150
|
+
interp.on_function_defined += method(:define_function)
|
15151
|
+
end
|
15152
|
+
|
15153
|
+
private
|
15154
|
+
def define_function(function_definition, function)
|
15155
|
+
if function.named? && function.declared_as_static?
|
15156
|
+
anterior_decls = function.declarations_and_definitions.reject { |decl|
|
15157
|
+
decl == function_definition
|
15158
|
+
}
|
15159
|
+
if anterior_decls.empty?
|
15160
|
+
W(:W1076, function_definition.location, function.name)
|
15161
|
+
end
|
15162
|
+
end
|
15163
|
+
end
|
15164
|
+
end
|
15165
|
+
|
15166
|
+
class W1077 < PassiveMessageDetection
|
15167
|
+
def initialize(context)
|
15168
|
+
super
|
15169
|
+
interp = context[:c_interpreter]
|
15170
|
+
interp.on_variable_declared += method(:check)
|
15171
|
+
end
|
15172
|
+
|
15173
|
+
private
|
15174
|
+
def check(variable_declaration, *)
|
15175
|
+
type = variable_declaration.type
|
15176
|
+
begin
|
15177
|
+
if type.array?
|
15178
|
+
unless type.length
|
15179
|
+
W(:W1077, variable_declaration.location)
|
15180
|
+
break
|
15181
|
+
end
|
15182
|
+
else
|
15183
|
+
break
|
15184
|
+
end
|
15185
|
+
end while type = type.base_type
|
15186
|
+
end
|
15187
|
+
end
|
15188
|
+
|
14997
15189
|
class W9001 < PassiveMessageDetection
|
14998
15190
|
def initialize(context)
|
14999
15191
|
super
|
data/lib/adlint/c/parser.rb
CHANGED
@@ -10,20 +10,22 @@ require 'racc/parser.rb'
|
|
10
10
|
require "adlint/error"
|
11
11
|
require "adlint/symbol"
|
12
12
|
require "adlint/monitor"
|
13
|
+
require "adlint/util"
|
14
|
+
require "adlint/c/lexer"
|
13
15
|
require "adlint/c/syntax"
|
14
16
|
|
15
17
|
module AdLint
|
16
18
|
module C
|
17
19
|
class Parser < Racc::Parser
|
18
20
|
|
19
|
-
module_eval(<<'...end parser.y/module_eval...', 'parser.y',
|
21
|
+
module_eval(<<'...end parser.y/module_eval...', 'parser.y', 2030)
|
20
22
|
|
21
23
|
include MonitorUtil
|
22
24
|
include ReportUtil
|
23
25
|
|
24
|
-
def initialize(context
|
26
|
+
def initialize(context)
|
25
27
|
@context = context
|
26
|
-
@lexer =
|
28
|
+
@lexer = create_lexer(context[:c_source])
|
27
29
|
@symbol_table = context[:symbol_table]
|
28
30
|
@token_array = []
|
29
31
|
@unnamed_tag_no = 0
|
@@ -35,7 +37,21 @@ def execute
|
|
35
37
|
do_parse
|
36
38
|
end
|
37
39
|
|
40
|
+
extend Pluggable
|
41
|
+
|
42
|
+
def_plugin :on_string_literals_concatenated
|
43
|
+
|
38
44
|
private
|
45
|
+
def create_lexer(c_source)
|
46
|
+
Lexer.new(c_source).tap { |lexer| attach_lexer_plugin(lexer) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def attach_lexer_plugin(lexer)
|
50
|
+
lexer.on_string_literals_concatenated += lambda { |*args|
|
51
|
+
on_string_literals_concatenated.invoke(*args)
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
39
55
|
def next_token
|
40
56
|
if token = @lexer.next_token
|
41
57
|
@token_array.push(token)
|