Skip to content

Commit e2cb53c

Browse files
authored
Merge pull request #7014 from jbj/isFromSystemMacroDefinition
C++: Add `isFromSystemMacroDefinition` predicate
2 parents 42a046e + 93dfee8 commit e2cb53c

File tree

2 files changed

+41
-4
lines changed

2 files changed

+41
-4
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
lgtm,codescanning
2+
* The QL library `semmle.code.cpp.commons.Exclusions` now contains a predicate
3+
`isFromSystemMacroDefinition` for identifying code that originates from a
4+
macro outside the project being analyzed.

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

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ predicate functionContainsPreprocCode(Function f) {
8181
}
8282

8383
/**
84-
* Holds if `e` is completely or partially from a macro definition, as opposed
85-
* to being passed in as an argument.
84+
* Holds if `e` is completely or partially from a macro invocation `mi`, as
85+
* opposed to being passed in as an argument.
8686
*
8787
* In the following example, the call to `f` is from a macro definition,
8888
* while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart
@@ -93,8 +93,8 @@ predicate functionContainsPreprocCode(Function f) {
9393
* M(y + 1);
9494
* ```
9595
*/
96-
predicate isFromMacroDefinition(Element e) {
97-
exists(MacroInvocation mi, Location eLocation, Location miLocation |
96+
private predicate isFromMacroInvocation(Element e, MacroInvocation mi) {
97+
exists(Location eLocation, Location miLocation |
9898
mi.getAnExpandedElement() = e and
9999
eLocation = e.getLocation() and
100100
miLocation = mi.getLocation() and
@@ -109,3 +109,36 @@ predicate isFromMacroDefinition(Element e) {
109109
eLocation.getEndColumn() >= miLocation.getEndColumn()
110110
)
111111
}
112+
113+
/**
114+
* Holds if `e` is completely or partially from a macro definition, as opposed
115+
* to being passed in as an argument.
116+
*
117+
* In the following example, the call to `f` is from a macro definition,
118+
* while `y`, `+`, `1`, and `;` are not. This assumes that no identifier apart
119+
* from `M` refers to a macro.
120+
* ```
121+
* #define M(x) f(x)
122+
* ...
123+
* M(y + 1);
124+
* ```
125+
*/
126+
predicate isFromMacroDefinition(Element e) { isFromMacroInvocation(e, _) }
127+
128+
/**
129+
* Holds if `e` is completely or partially from a _system macro_ definition, as
130+
* opposed to being passed in as an argument. A system macro is a macro whose
131+
* definition is outside the source directory of the database.
132+
*
133+
* If the system macro is invoked through a non-system macro, then this
134+
* predicate does not hold.
135+
*
136+
* See also `isFromMacroDefinition`.
137+
*/
138+
predicate isFromSystemMacroDefinition(Element e) {
139+
exists(MacroInvocation mi |
140+
isFromMacroInvocation(e, mi) and
141+
// Has no relative path in the database, meaning it's a system file.
142+
not exists(mi.getMacro().getFile().getRelativePath())
143+
)
144+
}

0 commit comments

Comments
 (0)