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/ld/typedef.rb
CHANGED
@@ -57,7 +57,7 @@ module Ld #:nodoc:
|
|
57
57
|
end
|
58
58
|
end
|
59
59
|
|
60
|
-
class
|
60
|
+
class TypedefMap
|
61
61
|
def initialize
|
62
62
|
@name_index = Hash.new { |hash, key| hash[key] = Set.new }
|
63
63
|
@composing_fpaths = Set.new
|
@@ -83,10 +83,10 @@ module Ld #:nodoc:
|
|
83
83
|
|
84
84
|
class TypedefMapper
|
85
85
|
def initialize
|
86
|
-
@
|
86
|
+
@map = TypedefMap.new
|
87
87
|
end
|
88
88
|
|
89
|
-
attr_reader :
|
89
|
+
attr_reader :map
|
90
90
|
|
91
91
|
def execute(met_fpath)
|
92
92
|
sma_wd = Pathname.pwd
|
@@ -96,15 +96,15 @@ module Ld #:nodoc:
|
|
96
96
|
when rec.version?
|
97
97
|
sma_wd = Pathname.new(rec.exec_working_directory)
|
98
98
|
when rec.typedef_declaration?
|
99
|
-
@
|
99
|
+
@map.add(Typedef.new(rec.type_name, rec.location))
|
100
100
|
end
|
101
101
|
end
|
102
102
|
end
|
103
103
|
end
|
104
104
|
|
105
105
|
class TypedefTraversal
|
106
|
-
def initialize(
|
107
|
-
@
|
106
|
+
def initialize(typedef_map)
|
107
|
+
@map = typedef_map
|
108
108
|
end
|
109
109
|
|
110
110
|
extend Pluggable
|
@@ -112,7 +112,7 @@ module Ld #:nodoc:
|
|
112
112
|
def_plugin :on_declaration
|
113
113
|
|
114
114
|
def execute
|
115
|
-
@
|
115
|
+
@map.all_typedefs.each { |tdef| on_declaration.invoke(tdef) }
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
data/lib/adlint/ld/util.rb
CHANGED
@@ -39,21 +39,25 @@ module Ld #:nodoc:
|
|
39
39
|
map_fname = Pathname.new("#{proj_name}.map")
|
40
40
|
map_fpath = map_fname.expand_path(phase_ctxt.msg_fpath.dirname)
|
41
41
|
|
42
|
-
|
43
|
-
call_graph = phase_ctxt[:
|
44
|
-
return unless
|
42
|
+
map = phase_ctxt[:ld_function_map]
|
43
|
+
call_graph = phase_ctxt[:ld_call_graph]
|
44
|
+
return unless map && call_graph
|
45
45
|
|
46
46
|
File.open(map_fpath, "w") do |io|
|
47
47
|
io.puts("-- Function Call Graph --")
|
48
|
-
|
48
|
+
map.all_functions.each do |callee|
|
49
49
|
io.puts("DC of #{callee.signature}")
|
50
|
-
call_graph.direct_callers_of(callee).each do |
|
51
|
-
|
50
|
+
call_graph.direct_callers_of(callee).each do |ref|
|
51
|
+
if fun = ref.function
|
52
|
+
io.puts(" #{fun.signature}")
|
53
|
+
end
|
52
54
|
end
|
53
55
|
io.puts
|
54
56
|
io.puts("IC of #{callee.signature}")
|
55
|
-
call_graph.indirect_callers_of(callee).each do |
|
56
|
-
|
57
|
+
call_graph.indirect_callers_of(callee).each do |ref|
|
58
|
+
if fun = ref.function
|
59
|
+
io.puts(" #{fun.signature}")
|
60
|
+
end
|
57
61
|
end
|
58
62
|
io.puts
|
59
63
|
end
|
@@ -68,21 +72,25 @@ module Ld #:nodoc:
|
|
68
72
|
map_fname = Pathname.new("#{proj_name}.map")
|
69
73
|
map_fpath = map_fname.expand_path(phase_ctxt.msg_fpath.dirname)
|
70
74
|
|
71
|
-
|
72
|
-
ref_graph = phase_ctxt[:
|
73
|
-
return unless
|
75
|
+
map = phase_ctxt[:ld_variable_map]
|
76
|
+
ref_graph = phase_ctxt[:ld_xref_graph]
|
77
|
+
return unless map && ref_graph
|
74
78
|
|
75
79
|
File.open(map_fpath, "a") do |io|
|
76
80
|
io.puts("-- Variable Reference Graph --")
|
77
|
-
|
81
|
+
map.all_variables.each do |accessee|
|
78
82
|
io.puts("DR of #{accessee.name}")
|
79
|
-
ref_graph.direct_referrers_of(accessee).each do |
|
80
|
-
|
83
|
+
ref_graph.direct_referrers_of(accessee).each do |ref|
|
84
|
+
if fun = ref.function
|
85
|
+
io.puts(" #{fun.signature}")
|
86
|
+
end
|
81
87
|
end
|
82
88
|
io.puts
|
83
|
-
io.puts("IR or #{accessee.
|
84
|
-
ref_graph.indirect_referrers_of(accessee).each do |
|
85
|
-
|
89
|
+
io.puts("IR or #{accessee.name}")
|
90
|
+
ref_graph.indirect_referrers_of(accessee).each do |ref|
|
91
|
+
if fun = ref.function
|
92
|
+
io.puts(" #{fun.signature}")
|
93
|
+
end
|
86
94
|
end
|
87
95
|
io.puts
|
88
96
|
end
|
data/lib/adlint/location.rb
CHANGED
@@ -69,7 +69,12 @@ module AdLint #:nodoc:
|
|
69
69
|
false
|
70
70
|
end
|
71
71
|
end
|
72
|
-
|
72
|
+
# NOTE: Value of #in_analysis_target? depends on the `traits' parameter.
|
73
|
+
# But the `traits' parameter always points the same object in an
|
74
|
+
# AdLint instance.
|
75
|
+
# So, it is safe to treat this method as nullary method for improving
|
76
|
+
# the performance.
|
77
|
+
memoize :in_analysis_target?, force_nullary: true
|
73
78
|
|
74
79
|
def ==(rhs)
|
75
80
|
self.to_a == rhs.to_a
|
data/lib/adlint/memo.rb
CHANGED
@@ -32,20 +32,29 @@
|
|
32
32
|
module AdLint #:nodoc:
|
33
33
|
|
34
34
|
module Memoizable
|
35
|
-
def memoize(name, *
|
36
|
-
|
37
|
-
|
35
|
+
def memoize(name, *opts)
|
36
|
+
force_nullary, key_indices = extract_memoize_options(opts)
|
37
|
+
case
|
38
|
+
when instance_method(name).arity == 0 || force_nullary
|
39
|
+
memoize_nullary_method(name)
|
40
|
+
when instance_method(name).arity == 1 || key_indices.size == 1
|
41
|
+
memoize_unary_method(name, key_indices.first || 0)
|
38
42
|
else
|
39
|
-
|
43
|
+
memoize_polynomial_method(name, key_indices)
|
40
44
|
end
|
41
45
|
end
|
42
46
|
|
43
47
|
private
|
44
|
-
def
|
48
|
+
def extract_memoize_options(opts)
|
49
|
+
hash = opts.first || {}
|
50
|
+
[hash[:force_nullary], hash[:key_indices] || []]
|
51
|
+
end
|
52
|
+
|
53
|
+
def memoize_nullary_method(name)
|
45
54
|
save_memoizing_method(name)
|
46
|
-
|
55
|
+
prepare_nullary_method_cache(name)
|
47
56
|
class_eval <<-EOS
|
48
|
-
define_method(:#{name}) do
|
57
|
+
define_method(:#{name}) do |*args|
|
49
58
|
if #{cache_name_of(name)}_initialized ||= false
|
50
59
|
#{cache_name_of(name)}_forbidden = false
|
51
60
|
#{cache_name_of(name)}
|
@@ -55,16 +64,43 @@ module AdLint #:nodoc:
|
|
55
64
|
#{org_name_of(name)}
|
56
65
|
else
|
57
66
|
#{cache_name_of(name)}_initialized = true
|
58
|
-
#{cache_name_of(name)} = #{org_name_of(name)}
|
67
|
+
#{cache_name_of(name)} = #{org_name_of(name)}(*args)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
EOS
|
72
|
+
end
|
73
|
+
|
74
|
+
def memoize_unary_method(name, key_index)
|
75
|
+
save_memoizing_method(name)
|
76
|
+
prepare_unary_method_cache(name, key_index)
|
77
|
+
class_eval <<-EOS
|
78
|
+
define_method(:#{name}) do |*args|
|
79
|
+
key = args[#{key_index}]
|
80
|
+
if #{cache_name_of(name)}_initialized ||= false
|
81
|
+
#{cache_name_of(name)}_forbidden = false
|
82
|
+
if #{cache_name_of(name)}.include?(key)
|
83
|
+
#{cache_name_of(name)}[key]
|
84
|
+
else
|
85
|
+
#{cache_name_of(name)}[key] = #{org_name_of(name)}(*args)
|
86
|
+
end
|
87
|
+
else
|
88
|
+
if #{cache_name_of(name)}_forbidden ||= false
|
89
|
+
#{cache_name_of(name)}_forbidden = false
|
90
|
+
#{org_name_of(name)}(*args)
|
91
|
+
else
|
92
|
+
#{cache_name_of(name)}_initialized = true
|
93
|
+
#{cache_name_of(name)} = {}
|
94
|
+
#{cache_name_of(name)}[key] = #{org_name_of(name)}(*args)
|
59
95
|
end
|
60
96
|
end
|
61
97
|
end
|
62
98
|
EOS
|
63
99
|
end
|
64
100
|
|
65
|
-
def
|
101
|
+
def memoize_polynomial_method(name, key_indices)
|
66
102
|
save_memoizing_method(name)
|
67
|
-
|
103
|
+
prepare_polynomial_method_cache(name, key_indices)
|
68
104
|
class_eval <<-EOS
|
69
105
|
define_method(:#{name}) do |*args|
|
70
106
|
key = __key_for_#{name}(*args)
|
@@ -89,7 +125,7 @@ module AdLint #:nodoc:
|
|
89
125
|
EOS
|
90
126
|
end
|
91
127
|
|
92
|
-
def
|
128
|
+
def prepare_nullary_method_cache(name)
|
93
129
|
class_eval <<-EOS
|
94
130
|
define_method(:forbid_once_memo_of__#{name}) do
|
95
131
|
#{cache_name_of(name)}_forbidden = true
|
@@ -104,7 +140,24 @@ module AdLint #:nodoc:
|
|
104
140
|
EOS
|
105
141
|
end
|
106
142
|
|
107
|
-
def
|
143
|
+
def prepare_unary_method_cache(name, key_index)
|
144
|
+
class_eval <<-EOS
|
145
|
+
define_method(:forbid_once_memo_of__#{name}) do
|
146
|
+
#{cache_name_of(name)}_forbidden = true
|
147
|
+
end
|
148
|
+
define_method(:clear_memo_of__#{name}) do
|
149
|
+
#{cache_name_of(name)} = nil
|
150
|
+
#{cache_name_of(name)}_initialized = false
|
151
|
+
end
|
152
|
+
define_method(:forget_memo_of__#{name}) do |*args|
|
153
|
+
if #{cache_name_of(name)}_initialized
|
154
|
+
#{cache_name_of(name)}.delete(args[#{key_index}])
|
155
|
+
end
|
156
|
+
end
|
157
|
+
EOS
|
158
|
+
end
|
159
|
+
|
160
|
+
def prepare_polynomial_method_cache(name, key_indices)
|
108
161
|
define_key_generator(name, key_indices)
|
109
162
|
class_eval <<-EOS
|
110
163
|
define_method(:forbid_once_memo_of__#{name}) do
|
@@ -147,7 +200,7 @@ module AdLint #:nodoc:
|
|
147
200
|
end
|
148
201
|
|
149
202
|
def cache_name_of(name)
|
150
|
-
"@__cache_of__#{name.to_s.sub("?", "
|
203
|
+
"@__cache_of__#{name.to_s.sub("?", "P")}"
|
151
204
|
end
|
152
205
|
|
153
206
|
def org_name_of(name)
|
data/lib/adlint/prelude.rb
CHANGED
@@ -327,9 +327,9 @@ end
|
|
327
327
|
# string_item: "foo${VAR}baz"
|
328
328
|
#
|
329
329
|
class Psych::TreeBuilder < Psych::Handler
|
330
|
-
alias :
|
330
|
+
alias :_org_scalar :scalar
|
331
331
|
def scalar(value, anchor, tag, plain, quoted, style)
|
332
|
-
|
332
|
+
_org_scalar(substitute_environment_variables(value),
|
333
333
|
anchor, tag, plain, quoted, style)
|
334
334
|
end
|
335
335
|
|
data/lib/adlint/report.rb
CHANGED
@@ -248,7 +248,7 @@ module AdLint #:nodoc:
|
|
248
248
|
# Writes a function declaration information on the report.
|
249
249
|
#
|
250
250
|
# Abbreviation below is available.
|
251
|
-
#
|
251
|
+
# write_fundcl(...) => FUNDCL(...)
|
252
252
|
#
|
253
253
|
# === PARAMETER
|
254
254
|
# _loc_:: Location -- Location where the declaration appears.
|
@@ -259,11 +259,10 @@ module AdLint #:nodoc:
|
|
259
259
|
#
|
260
260
|
# === RETURN VALUE
|
261
261
|
# None.
|
262
|
-
def
|
263
|
-
write_code_struct(
|
264
|
-
fun_id))
|
262
|
+
def write_fundcl(loc, linkage, scope_type, dcl_type, fun_id)
|
263
|
+
write_code_struct(FunDcl.new(loc, linkage, scope_type, dcl_type, fun_id))
|
265
264
|
end
|
266
|
-
alias :
|
265
|
+
alias :FUNDCL :write_fundcl
|
267
266
|
|
268
267
|
# === DESCRIPTION
|
269
268
|
# Writes a variable definition information on the report.
|
@@ -291,7 +290,7 @@ module AdLint #:nodoc:
|
|
291
290
|
# Writes a function definition information on the report.
|
292
291
|
#
|
293
292
|
# Abbreviation below is available.
|
294
|
-
#
|
293
|
+
# write_fundef(...) => FUNDEF(...)
|
295
294
|
#
|
296
295
|
# === PARAMETER
|
297
296
|
# _loc_:: Location -- Location where the definition appears.
|
@@ -302,10 +301,10 @@ module AdLint #:nodoc:
|
|
302
301
|
#
|
303
302
|
# === RETURN VALUE
|
304
303
|
# None.
|
305
|
-
def
|
306
|
-
write_code_struct(
|
304
|
+
def write_fundef(loc, linkage, scope_type, fun_id, lines)
|
305
|
+
write_code_struct(FunDef.new(loc, linkage, scope_type, fun_id, lines))
|
307
306
|
end
|
308
|
-
alias :
|
307
|
+
alias :FUNDEF :write_fundef
|
309
308
|
|
310
309
|
# === DESCRIPTION
|
311
310
|
# Writes a macro definition information on the report.
|
@@ -399,16 +398,16 @@ module AdLint #:nodoc:
|
|
399
398
|
# Writes a function call information on the report.
|
400
399
|
#
|
401
400
|
# Abbreviation below is available.
|
402
|
-
#
|
401
|
+
# write_funcall(...) => FUNCALL(...)
|
403
402
|
#
|
404
403
|
# === PARAMETER
|
405
404
|
# _loc_:: Location -- Location where the function call appears.
|
406
405
|
# _caller_fun_:: FunctionId -- Calling function identifier.
|
407
406
|
# _callee_fun_:: FunctionId -- Called function identifier.
|
408
|
-
def
|
409
|
-
write_code_struct(
|
407
|
+
def write_funcall(loc, caller_fun, callee_fun)
|
408
|
+
write_code_struct(Funcall.new(loc, caller_fun, callee_fun))
|
410
409
|
end
|
411
|
-
alias :
|
410
|
+
alias :FUNCALL :write_funcall
|
412
411
|
|
413
412
|
# === DESCRIPTION
|
414
413
|
# Writes a variable cross reference information on the report.
|
@@ -444,7 +443,7 @@ module AdLint #:nodoc:
|
|
444
443
|
# === RETURN VALUE
|
445
444
|
# None.
|
446
445
|
def write_xref_function(loc, referrer, ref_type, fun)
|
447
|
-
write_code_struct(
|
446
|
+
write_code_struct(XRefFun.new(loc, referrer, ref_type, fun))
|
448
447
|
end
|
449
448
|
alias :XREF_FUNC :write_xref_function
|
450
449
|
|
data/lib/adlint/util.rb
CHANGED
data/lib/adlint/version.rb
CHANGED
data/share/doc/Makefile
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
MAKEINFO = makeinfo
|
2
|
+
DOT = dot
|
2
3
|
|
3
|
-
.SUFFIXES : .texi .html .txt
|
4
|
+
.SUFFIXES : .texi .html .txt .dot .pdf
|
4
5
|
|
5
6
|
.texi.html :
|
6
7
|
$(MAKEINFO) --html --no-split --css-include=texinfo.css -o $@ $<
|
@@ -8,7 +9,10 @@ MAKEINFO = makeinfo
|
|
8
9
|
.texi.txt :
|
9
10
|
$(MAKEINFO) --plaintext -o $@ $<
|
10
11
|
|
11
|
-
|
12
|
+
.dot.pdf :
|
13
|
+
$(DOT) -Tpdf -o $@ $<
|
14
|
+
|
15
|
+
TARGET = users_guide_ja.html users_guide_en.html developers_guide_ja.html c99gram.pdf
|
12
16
|
|
13
17
|
all : $(TARGET)
|
14
18
|
|