Skip to content

Commit 8d79634

Browse files
committed
C++: Factor out isFromMacroDefinition predicate
This trick for excluding elements from macro bodies but not macro arguments looks promising and should probably be used much more. With this commit, it's now easy to use from any query. Performance is still good because the new predicate gets appropriately magiced.
1 parent d2009c5 commit 8d79634

5 files changed

Lines changed: 40 additions & 7 deletions

File tree

cpp/ql/src/Likely Bugs/Arithmetic/PointlessSelfComparison.ql

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,13 @@
1313

1414
import cpp
1515
import PointlessSelfComparison
16+
import semmle.code.cpp.commons.Exclusions
1617

1718
from ComparisonOperation cmp
1819
where
1920
pointlessSelfComparison(cmp) and
2021
not nanTest(cmp) and
2122
not overflowTest(cmp) and
2223
not cmp.isFromTemplateInstantiation(_) and
23-
not exists(MacroInvocation mi |
24-
// cmp is in mi
25-
mi.getAnExpandedElement() = cmp and
26-
// and cmp was apparently not passed in as a macro parameter
27-
cmp.getLocation().getStartLine() = mi.getLocation().getStartLine() and
28-
cmp.getLocation().getStartColumn() = mi.getLocation().getStartColumn()
29-
)
24+
not isFromMacroDefinition(cmp)
3025
select cmp, "Self comparison."

cpp/ql/src/semmle/code/cpp/commons/Exclusions.qll

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,26 @@ predicate functionContainsPreprocCode(Function f) {
7979
pbdStartLine >= fBlockStartLine
8080
)
8181
}
82+
83+
/**
84+
* Holds if `e` is completely or partially from a macro definition, as opposed
85+
* to being passed in as an argument.
86+
*
87+
* In the following example, the call to `f` is from a macro definition,
88+
* while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart
89+
* from `M` refers to a macro.
90+
* ```
91+
* #define M(x) f(x)
92+
* ...
93+
* M(y + 1);
94+
* ```
95+
*/
96+
predicate isFromMacroDefinition(Element e) {
97+
exists(MacroInvocation mi |
98+
// e is in mi
99+
mi.getAnExpandedElement() = e and
100+
// and e was apparently not passed in as a macro parameter
101+
e.getLocation().getStartLine() = mi.getLocation().getStartLine() and
102+
e.getLocation().getStartColumn() = mi.getLocation().getStartColumn()
103+
)
104+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// This is the example from the QLDoc of `isFromMacroDefinition`.
2+
3+
void f(int);
4+
5+
#define M(x) f(x)
6+
7+
void useM(int y) {
8+
M(y + 1);
9+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
| exclusions.cpp:8:3:8:10 | call to f |
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import semmle.code.cpp.commons.Exclusions
2+
3+
from Element e
4+
where isFromMacroDefinition(e)
5+
select e

0 commit comments

Comments
 (0)