-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Expand file tree
/
Copy pathConditionalSegmentLines.ql
More file actions
122 lines (109 loc) · 3.63 KB
/
ConditionalSegmentLines.ql
File metadata and controls
122 lines (109 loc) · 3.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/**
* @name Number of conditionally compiled lines
* @description The number of lines that are subject to conditional
* compilation constraints defined using `#if`, `#ifdef`,
* and `#ifndef`.
* @kind treemap
* @id cpp/conditional-segment-lines
* @treemap.warnOn highValues
* @metricType file
* @metricAggregate avg sum max
*/
import cpp
import semmle.code.cpp.headers.MultipleInclusion
predicate preprocessorOpenCondition(PreprocessorDirective d, File f, int line) {
(d instanceof PreprocessorIf or
d instanceof PreprocessorIfdef or
d instanceof PreprocessorIfndef)
and
exists(Location l |
l = d.getLocation() |
f = l.getFile() and line = l.getStartLine())
}
predicate preprocessorCloseCondition(PreprocessorDirective d, File f, int line) {
d instanceof PreprocessorEndif
and
exists(Location l |
l = d.getLocation() |
f = l.getFile() and line = l.getStartLine())
}
private
predicate relevantLine(File f, int line) {
preprocessorOpenCondition(_, f, line) or
preprocessorCloseCondition(_, f, line)
}
predicate relevantDirective(PreprocessorDirective d, File f, int line) {
preprocessorOpenCondition(d, f, line) or
preprocessorCloseCondition(d, f, line)
}
private
predicate relevantLineWithRank(File f, int rnk, int line) {
line = rank[rnk](int l | relevantLine(f, l) | l)
}
private
PreprocessorDirective next(PreprocessorDirective ppd) {
exists(File f, int line, int rnk, int nextLine |
relevantDirective(ppd, f, line) and
relevantLineWithRank(f, rnk, line) and
relevantLineWithRank(f, rnk + 1, nextLine) and
relevantDirective(result, f, nextLine)
)
}
private
int level(PreprocessorDirective ppd) {
(relevantDirective(ppd, _, _)
and not exists(PreprocessorDirective previous | ppd = next(previous))
and result = 0)
or
exists(PreprocessorDirective previous |
ppd = next(previous) and
preprocessorOpenCondition(previous, _, _) and
result = level(previous) + 1)
or
exists(PreprocessorDirective previous |
ppd = next(previous) and
preprocessorCloseCondition(previous, _, _) and
result = level(previous) - 1)
}
private
predicate openWithDepth(int depth, File f, PreprocessorDirective open, int line) {
preprocessorOpenCondition(open, f, line) and
depth = level(open) and
depth < 2 // beyond 2, we don't care about the macros anymore
}
private
predicate closeWithDepth(int depth, File f, PreprocessorDirective close, int line) {
preprocessorCloseCondition(close, f, line) and
depth = level(close) - 1 and
depth < 2 // beyond 2, we don't care about the macros anymore
}
predicate length(PreprocessorDirective open, int length) {
exists(int depth, File f, int start, int end |
openWithDepth(depth, f, open, start) and
end = min(PreprocessorDirective endif, int closeLine |
closeWithDepth(depth, f, endif, closeLine) and
closeLine > start|
closeLine) and
length = end - start - 1
)
}
predicate headerGuard(PreprocessorDirective notdef, File f) {
exists(CorrectIncludeGuard g |
notdef = g.getIfndef() and f = notdef.getFile())
}
predicate headerGuardChild(PreprocessorDirective open) {
exists(File f, PreprocessorDirective headerGuard |
headerGuard(headerGuard, f) and
openWithDepth(1, f, open, _))
}
predicate topLevelOpen(PreprocessorDirective open) {
(openWithDepth(0, _, open, _) and not headerGuard(open,_))
or
headerGuardChild(open)
}
from File f
where f.fromSource()
select f, sum(PreprocessorDirective open, int length |
open.getFile() = f and
topLevelOpen(open) and length(open, length) |
length)