adlint 3.0.4 → 3.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. data/ChangeLog +374 -13
  2. data/INSTALL +1 -3
  3. data/MANIFEST +12 -0
  4. data/NEWS +30 -4
  5. data/README +0 -4
  6. data/TODO +2 -1
  7. data/etc/mesg.d/c_builtin/en_US/messages.yml +2 -2
  8. data/etc/mesg.d/c_builtin/ja_JP/messages.yml +2 -2
  9. data/etc/mesg.d/core/en_US/messages.yml +5 -1
  10. data/etc/mesg.d/core/ja_JP/messages.yml +5 -1
  11. data/features/code_check/W0422.feature +128 -0
  12. data/features/code_check/W0491.feature +57 -0
  13. data/features/code_check/W0492.feature +80 -0
  14. data/features/code_check/W0542.feature +20 -0
  15. data/features/code_check/W0580.feature +25 -0
  16. data/features/code_check/W0610.feature +36 -0
  17. data/features/code_check/W0642.feature +67 -0
  18. data/features/code_check/W0786.feature +39 -0
  19. data/features/code_check/W0830.feature +27 -0
  20. data/features/code_check/W1047.feature +72 -0
  21. data/features/code_check/W9003.feature +22 -0
  22. data/features/code_extraction/TODO +1 -0
  23. data/features/metric_measurement/TODO +1 -0
  24. data/lib/adlint/analyzer.rb +2 -2
  25. data/lib/adlint/cc1/ctrlexpr.rb +27 -6
  26. data/lib/adlint/cc1/domain.rb +72 -12
  27. data/lib/adlint/cc1/enum.rb +4 -0
  28. data/lib/adlint/cc1/expr.rb +31 -29
  29. data/lib/adlint/cc1/interp.rb +45 -56
  30. data/lib/adlint/cc1/lexer.rb +26 -5
  31. data/lib/adlint/cc1/mediator.rb +35 -6
  32. data/lib/adlint/cc1/object.rb +62 -19
  33. data/lib/adlint/cc1/parser.rb +948 -904
  34. data/lib/adlint/cc1/parser.y +59 -29
  35. data/lib/adlint/cc1/phase.rb +6 -8
  36. data/lib/adlint/cc1/syntax.rb +70 -17
  37. data/lib/adlint/cc1/util.rb +4 -4
  38. data/lib/adlint/code.rb +16 -6
  39. data/lib/adlint/cpp/eval.rb +31 -25
  40. data/lib/adlint/cpp/lexer.rb +11 -5
  41. data/lib/adlint/cpp/macro.rb +34 -7
  42. data/lib/adlint/cpp/phase.rb +8 -8
  43. data/lib/adlint/error.rb +6 -0
  44. data/lib/adlint/exam/c_builtin/cc1_check.rb +557 -594
  45. data/lib/adlint/exam/c_builtin/cc1_check_shima.rb +72 -72
  46. data/lib/adlint/exam/c_builtin/cc1_code.rb +72 -52
  47. data/lib/adlint/exam/c_builtin/cc1_metric.rb +131 -131
  48. data/lib/adlint/exam/c_builtin/cpp_check.rb +48 -48
  49. data/lib/adlint/exam/c_builtin/cpp_check_shima.rb +2 -2
  50. data/lib/adlint/exam/c_builtin/cpp_code.rb +21 -21
  51. data/lib/adlint/exam/c_builtin/ld_check.rb +88 -87
  52. data/lib/adlint/exam/c_builtin/ld_metric.rb +4 -5
  53. data/lib/adlint/exam/c_builtin.rb +6 -6
  54. data/lib/adlint/ld/object.rb +269 -186
  55. data/lib/adlint/ld/phase.rb +19 -19
  56. data/lib/adlint/ld/typedef.rb +7 -7
  57. data/lib/adlint/ld/util.rb +25 -17
  58. data/lib/adlint/location.rb +6 -1
  59. data/lib/adlint/memo.rb +66 -13
  60. data/lib/adlint/prelude.rb +2 -2
  61. data/lib/adlint/report.rb +13 -14
  62. data/lib/adlint/util.rb +1 -1
  63. data/lib/adlint/version.rb +2 -2
  64. data/share/doc/Makefile +6 -2
  65. data/share/doc/c99gram.dot +502 -0
  66. data/share/doc/c99gram.pdf +0 -0
  67. data/share/doc/developers_guide_ja.html +4 -3
  68. data/share/doc/developers_guide_ja.texi +2 -1
  69. data/share/doc/users_guide_en.html +9 -9
  70. data/share/doc/users_guide_en.texi +7 -7
  71. data/share/doc/users_guide_ja.html +9 -9
  72. data/share/doc/users_guide_ja.texi +7 -7
  73. metadata +14 -2
@@ -57,7 +57,7 @@ module Ld #:nodoc:
57
57
  end
58
58
  end
59
59
 
60
- class TypedefMapping
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
- @result = TypedefMapping.new
86
+ @map = TypedefMap.new
87
87
  end
88
88
 
89
- attr_reader :result
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
- @result.add(Typedef.new(rec.type_name, rec.location))
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(typedef_mapping)
107
- @typedef_mapping = typedef_mapping
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
- @typedef_mapping.all_typedefs.each { |tdef| on_declaration.invoke(tdef) }
115
+ @map.all_typedefs.each { |tdef| on_declaration.invoke(tdef) }
116
116
  end
117
117
  end
118
118
 
@@ -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
- mapping = phase_ctxt[:ld_function_mapping]
43
- call_graph = phase_ctxt[:ld_function_call_graph]
44
- return unless mapping && call_graph
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
- mapping.all_functions.each do |callee|
48
+ map.all_functions.each do |callee|
49
49
  io.puts("DC of #{callee.signature}")
50
- call_graph.direct_callers_of(callee).each do |fun|
51
- io.puts(" #{fun.signature}")
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 |fun|
56
- io.puts(" #{fun.signature}")
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
- mapping = phase_ctxt[:ld_variable_mapping]
72
- ref_graph = phase_ctxt[:ld_variable_reference_graph]
73
- return unless mapping && ref_graph
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
- mapping.all_variables.each do |accessee|
81
+ map.all_variables.each do |accessee|
78
82
  io.puts("DR of #{accessee.name}")
79
- ref_graph.direct_referrers_of(accessee).each do |fun|
80
- io.puts(" #{fun.signature}")
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.signature}")
84
- ref_graph.indirect_referrers_of(accessee).each do |fun|
85
- io.puts(" #{fun.signature}")
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
@@ -69,7 +69,12 @@ module AdLint #:nodoc:
69
69
  false
70
70
  end
71
71
  end
72
- memoize :in_analysis_target?
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, *key_indices)
36
- if instance_method(name).arity == 0
37
- memoize_noarg_method(name)
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
- memoize_ordinary_method(name, key_indices)
43
+ memoize_polynomial_method(name, key_indices)
40
44
  end
41
45
  end
42
46
 
43
47
  private
44
- def memoize_noarg_method(name)
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
- prepare_noarg_method_cache(name)
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 memoize_ordinary_method(name, key_indices)
101
+ def memoize_polynomial_method(name, key_indices)
66
102
  save_memoizing_method(name)
67
- prepare_ordinary_method_cache(name, key_indices)
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 prepare_noarg_method_cache(name)
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 prepare_ordinary_method_cache(name, key_indices)
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("?", "Q")}"
203
+ "@__cache_of__#{name.to_s.sub("?", "P")}"
151
204
  end
152
205
 
153
206
  def org_name_of(name)
@@ -327,9 +327,9 @@ end
327
327
  # string_item: "foo${VAR}baz"
328
328
  #
329
329
  class Psych::TreeBuilder < Psych::Handler
330
- alias :_orig_scalar :scalar
330
+ alias :_org_scalar :scalar
331
331
  def scalar(value, anchor, tag, plain, quoted, style)
332
- _orig_scalar(substitute_environment_variables(value),
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
- # write_funcdcl(...) => FUNCDCL(...)
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 write_funcdcl(loc, linkage, scope_type, dcl_type, fun_id)
263
- write_code_struct(FuncDcl.new(loc, linkage, scope_type, dcl_type,
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 :FUNCDCL :write_funcdcl
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
- # write_funcdef(...) => FUNCDEF(...)
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 write_funcdef(loc, linkage, scope_type, fun_id, lines)
306
- write_code_struct(FuncDef.new(loc, linkage, scope_type, fun_id, lines))
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 :FUNCDEF :write_funcdef
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
- # write_call(...) => CALL(...)
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 write_call(loc, caller_fun, callee_fun)
409
- write_code_struct(Call.new(loc, caller_fun, callee_fun))
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 :CALL :write_call
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(XRefFunc.new(loc, referrer, ref_type, fun))
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
@@ -517,7 +517,7 @@ if $0 == __FILE__
517
517
  p "foo"
518
518
  end
519
519
 
520
- extend ::AdLint::Pluggable
520
+ extend AdLint::Pluggable
521
521
 
522
522
  def_plugin :on_initialization
523
523
 
@@ -33,8 +33,8 @@ module AdLint #:nodoc:
33
33
 
34
34
  MAJOR_VERSION = 3
35
35
  MINOR_VERSION = 0
36
- PATCH_VERSION = 4
37
- RELEASE_DATE = "2013-04-12"
36
+ PATCH_VERSION = 8
37
+ RELEASE_DATE = "2013-05-31"
38
38
 
39
39
  TRAITS_SCHEMA_VERSION = "3.0.0"
40
40
 
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
- TARGET = users_guide_ja.html users_guide_en.html developers_guide_ja.html
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