Merge branch 'master' into polymorphic_extern_classes
[nit.git] / contrib / pep8analysis / src / cfg / sanity.nit
1 module sanity
2
3 import cfg_base
4
5 redef class BasicBlock
6 private var cfg_sanity_verified = false
7
8 # reports data in code
9 private fun verify_cfg_sanity_code(v: Noter, data_in_code: Array[ALine])
10 do
11 for line in lines do if line isa ADirectiveLine then
12 data_in_code.add(line)
13 end
14
15 cfg_sanity_verified = true
16 end
17
18 # reports code in data
19 private fun verify_cfg_sanity_data(v: Noter, dead_lines: Array[ALine])
20 do
21 for line in lines do if line isa AInstructionLine then
22 dead_lines.add(line)
23 end
24
25 cfg_sanity_verified = true
26 end
27 end
28
29 redef class AnalysisManager
30 fun verify_cfg_sanity(cfg: CFG)
31 do
32 # verify executable code
33 var executed_data = new Array[ALine]
34 verify_cfg_sanity_recursively_code( cfg.start, executed_data )
35
36 # verify data or dead code
37 var dead_code = new Array[ALine]
38 for b in cfg.blocks do if not b.cfg_sanity_verified then
39 b.verify_cfg_sanity_data(self, dead_code)
40 end
41
42 group( dead_code, "unreachable instructions (dead code?)", false )
43 group( executed_data, "data in program flow (missing BR?)", true )
44 end
45
46 fun verify_cfg_sanity_recursively_code(b: BasicBlock, executed_data: Array[ALine])
47 do
48 if b.cfg_sanity_verified then return # is code
49
50 b.verify_cfg_sanity_code(self,executed_data)
51 for s in b.successors do verify_cfg_sanity_recursively_code( s, executed_data )
52 end
53
54 private fun group(lines: Array[ALine], msg: String, error: Bool)
55 do
56 lines = lines.iterator.sort.to_a
57 var len = lines.length
58 var first: nullable ALine = null
59 for i in [0..len[ do
60 var line = lines[i]
61 if first == null then
62 first = line
63 end
64 if i == len-1 or line.address + line.size != lines[i+1].address then
65 if error then
66 if first == line then
67 manager.notes.add(new P8Error(first.location, msg))
68 else
69 manager.notes.add(new P8Error.range(first.location, line.location, msg))
70 end
71 else
72 if first == line then
73 manager.notes.add(new P8Error(first.location, msg))
74 else
75 manager.notes.add(new Warn.range(first.location, line.location, msg))
76 end
77 end
78 first = null
79 end
80 end
81 end
82 end
83
84 redef class ALine
85 super Comparable
86 redef type OTHER: ALine
87 redef fun <=>(o) do return address <=> o.address
88 end