Skip to content

Commit e062851

Browse files
authored
Merge pull request #517 from dave-bartolomeo/dave/IRFilter
C++: Don't generate IR for functions with bad ASTs
2 parents 1739cab + beb9c9c commit e062851

File tree

12 files changed

+540
-24
lines changed

12 files changed

+540
-24
lines changed

cpp/ql/src/semmle/code/cpp/PrintAST.qll

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,36 @@ private predicate locationSortKeys(Locatable ast, string file, int line,
5959
)
6060
}
6161

62+
private Function getEnclosingFunction(Locatable ast) {
63+
result = ast.(Expr).getEnclosingFunction() or
64+
result = ast.(Stmt).getEnclosingFunction() or
65+
result = ast.(Initializer).getExpr().getEnclosingFunction() or
66+
result = ast.(Parameter).getFunction() or
67+
exists(DeclStmt stmt |
68+
stmt.getADeclarationEntry() = ast and
69+
result = stmt.getEnclosingFunction()
70+
) or
71+
result = ast
72+
}
73+
6274
/**
6375
* Most nodes are just a wrapper around `Locatable`, but we do synthesize new
6476
* nodes for things like parameter lists and constructor init lists.
6577
*/
6678
private newtype TPrintASTNode =
67-
TASTNode(Locatable ast) or
68-
TParametersNode(Function func) or
79+
TASTNode(Locatable ast) {
80+
shouldPrintFunction(getEnclosingFunction(ast))
81+
} or
82+
TParametersNode(Function func) {
83+
shouldPrintFunction(func)
84+
} or
6985
TConstructorInitializersNode(Constructor ctor) {
70-
ctor.hasEntryPoint()
86+
ctor.hasEntryPoint() and
87+
shouldPrintFunction(ctor)
7188
} or
7289
TDestructorDestructionsNode(Destructor dtor) {
73-
dtor.hasEntryPoint()
90+
dtor.hasEntryPoint() and
91+
shouldPrintFunction(dtor)
7492
}
7593

7694
/**
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import cpp
2+
3+
private newtype TIRConfiguration = MkIRConfiguration()
4+
5+
/**
6+
* The query can extend this class to control which functions have IR generated for them.
7+
*/
8+
class IRConfiguration extends TIRConfiguration {
9+
string toString() {
10+
result = "IRConfiguration"
11+
}
12+
13+
/**
14+
* Holds if IR should be created for function `func`. By default, holds for all functions.
15+
*/
16+
predicate shouldCreateIRForFunction(Function func) {
17+
any()
18+
}
19+
}

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
private import IR
22
import cpp
3+
import semmle.code.cpp.ir.IRConfiguration
4+
5+
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
6+
7+
/**
8+
* The query can extend this class to control which functions are printed.
9+
*/
10+
class PrintIRConfiguration extends TPrintIRConfiguration {
11+
string toString() {
12+
result = "PrintIRConfiguration"
13+
}
14+
15+
/**
16+
* Holds if the IR for `func` should be printed. By default, holds for all
17+
* functions.
18+
*/
19+
predicate shouldPrintFunction(Function func) {
20+
any()
21+
}
22+
}
23+
24+
private predicate shouldPrintFunction(Function func) {
25+
exists(PrintIRConfiguration config |
26+
config.shouldPrintFunction(func)
27+
)
28+
}
29+
30+
/**
31+
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
32+
*/
33+
private class FilteredIRConfiguration extends IRConfiguration {
34+
override predicate shouldCreateIRForFunction(Function func) {
35+
shouldPrintFunction(func)
36+
}
37+
}
338

439
private string getAdditionalInstructionProperty(Instruction instr, string key) {
540
exists(IRPropertyProvider provider |
@@ -14,9 +49,15 @@ private string getAdditionalBlockProperty(IRBlock block, string key) {
1449
}
1550

1651
private newtype TPrintableIRNode =
17-
TPrintableFunctionIR(FunctionIR funcIR) or
18-
TPrintableIRBlock(IRBlock block) or
19-
TPrintableInstruction(Instruction instr)
52+
TPrintableFunctionIR(FunctionIR funcIR) {
53+
shouldPrintFunction(funcIR.getFunction())
54+
} or
55+
TPrintableIRBlock(IRBlock block) {
56+
shouldPrintFunction(block.getFunction())
57+
} or
58+
TPrintableInstruction(Instruction instr) {
59+
shouldPrintFunction(instr.getFunction())
60+
}
2061

2162
/**
2263
* A node to be emitted in the IR graph.

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/PrintIR.qll

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
private import IR
22
import cpp
3+
import semmle.code.cpp.ir.IRConfiguration
4+
5+
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
6+
7+
/**
8+
* The query can extend this class to control which functions are printed.
9+
*/
10+
class PrintIRConfiguration extends TPrintIRConfiguration {
11+
string toString() {
12+
result = "PrintIRConfiguration"
13+
}
14+
15+
/**
16+
* Holds if the IR for `func` should be printed. By default, holds for all
17+
* functions.
18+
*/
19+
predicate shouldPrintFunction(Function func) {
20+
any()
21+
}
22+
}
23+
24+
private predicate shouldPrintFunction(Function func) {
25+
exists(PrintIRConfiguration config |
26+
config.shouldPrintFunction(func)
27+
)
28+
}
29+
30+
/**
31+
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
32+
*/
33+
private class FilteredIRConfiguration extends IRConfiguration {
34+
override predicate shouldCreateIRForFunction(Function func) {
35+
shouldPrintFunction(func)
36+
}
37+
}
338

439
private string getAdditionalInstructionProperty(Instruction instr, string key) {
540
exists(IRPropertyProvider provider |
@@ -14,9 +49,15 @@ private string getAdditionalBlockProperty(IRBlock block, string key) {
1449
}
1550

1651
private newtype TPrintableIRNode =
17-
TPrintableFunctionIR(FunctionIR funcIR) or
18-
TPrintableIRBlock(IRBlock block) or
19-
TPrintableInstruction(Instruction instr)
52+
TPrintableFunctionIR(FunctionIR funcIR) {
53+
shouldPrintFunction(funcIR.getFunction())
54+
} or
55+
TPrintableIRBlock(IRBlock block) {
56+
shouldPrintFunction(block.getFunction())
57+
} or
58+
TPrintableInstruction(Instruction instr) {
59+
shouldPrintFunction(instr.getFunction())
60+
}
2061

2162
/**
2263
* A node to be emitted in the IR graph.

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import cpp
2+
import cpp
23
import semmle.code.cpp.ir.implementation.raw.IR
4+
private import semmle.code.cpp.ir.IRConfiguration
35
private import semmle.code.cpp.ir.implementation.Opcode
46
private import semmle.code.cpp.ir.internal.OperandTag
57
private import semmle.code.cpp.ir.internal.TempVariableTag
@@ -83,7 +85,8 @@ private predicate ignoreExprOnly(Expr expr) {
8385
// Ignore the allocator call, because we always synthesize it. Don't ignore
8486
// its arguments, though, because we use them as part of the synthesis.
8587
newExpr.getAllocatorCall() = expr
86-
)
88+
) or
89+
not translateFunction(expr.getEnclosingFunction())
8790
}
8891

8992
/**
@@ -94,6 +97,49 @@ private predicate ignoreExpr(Expr expr) {
9497
ignoreExprAndDescendants(getRealParent*(expr))
9598
}
9699

100+
/**
101+
* Holds if `func` contains an AST that cannot be translated into IR. This is mostly used to work
102+
* around extractor bugs. Once the relevant extractor bugs are fixed, this predicate can be removed.
103+
*/
104+
private predicate isInvalidFunction(Function func) {
105+
exists(Literal literal |
106+
// Constructor field inits within a compiler-generated copy constructor have a source expression
107+
// that is a `Literal` with no value.
108+
literal = func.(Constructor).getAnInitializer().(ConstructorFieldInit).getExpr() and
109+
not exists(literal.getValue())
110+
) or
111+
exists(ThisExpr thisExpr |
112+
// An instantiation of a member function template is not treated as a `MemberFunction` if it has
113+
// only non-type template arguments.
114+
thisExpr.getEnclosingFunction() = func and
115+
not func instanceof MemberFunction
116+
) or
117+
exists(Expr expr |
118+
// Expression missing a type.
119+
expr.getEnclosingFunction() = func and
120+
not exists(expr.getType())
121+
)
122+
}
123+
124+
/**
125+
* Holds if `func` should be translated to IR.
126+
*/
127+
private predicate translateFunction(Function func) {
128+
not func.isFromUninstantiatedTemplate(_) and
129+
func.hasEntryPoint() and
130+
not isInvalidFunction(func) and
131+
exists(IRConfiguration config |
132+
config.shouldCreateIRForFunction(func)
133+
)
134+
}
135+
136+
/**
137+
* Holds if `stmt` should be translated to IR.
138+
*/
139+
private predicate translateStmt(Stmt stmt) {
140+
translateFunction(stmt.getEnclosingFunction())
141+
}
142+
97143
/**
98144
* Holds if `expr` is most naturally evaluated as control flow, rather than as
99145
* a value.
@@ -236,7 +282,7 @@ newtype TTranslatedElement =
236282
} or
237283
// The initialization of a field via a member of an initializer list.
238284
TTranslatedExplicitFieldInitialization(Expr ast, Field field,
239-
Expr expr) {
285+
Expr expr) {
240286
exists(ClassAggregateLiteral initList |
241287
not ignoreExpr(initList) and
242288
ast = initList and
@@ -260,14 +306,14 @@ newtype TTranslatedElement =
260306
} or
261307
// The initialization of an array element via a member of an initializer list.
262308
TTranslatedExplicitElementInitialization(
263-
ArrayAggregateLiteral initList, int elementIndex) {
309+
ArrayAggregateLiteral initList, int elementIndex) {
264310
not ignoreExpr(initList) and
265311
exists(initList.getElementExpr(elementIndex))
266312
} or
267313
// The value initialization of a range of array elements that were omitted
268314
// from an initializer list.
269315
TTranslatedElementValueInitialization(ArrayAggregateLiteral initList,
270-
int elementIndex, int elementCount) {
316+
int elementIndex, int elementCount) {
271317
not ignoreExpr(initList) and
272318
isFirstValueInitializedElementInRange(initList, elementIndex) and
273319
elementCount =
@@ -287,28 +333,35 @@ newtype TTranslatedElement =
287333
not ignoreExpr(destruction)
288334
} or
289335
// A statement
290-
TTranslatedStmt(Stmt stmt) or
336+
TTranslatedStmt(Stmt stmt) {
337+
translateStmt(stmt)
338+
} or
291339
// A function
292340
TTranslatedFunction(Function func) {
293-
func.hasEntryPoint() and
294-
not func.isFromUninstantiatedTemplate(_)
341+
translateFunction(func)
295342
} or
296343
// A constructor init list
297344
TTranslatedConstructorInitList(Function func) {
298-
func.hasEntryPoint()
345+
translateFunction(func)
299346
} or
300347
// A destructor destruction list
301348
TTranslatedDestructorDestructionList(Function func) {
302-
func.hasEntryPoint()
349+
translateFunction(func)
303350
} or
304351
// A function parameter
305352
TTranslatedParameter(Parameter param) {
306-
param.getFunction().hasEntryPoint() or
307-
exists(param.getCatchBlock())
353+
exists(Function func |
354+
(
355+
func = param.getFunction() or
356+
func = param.getCatchBlock().getEnclosingFunction()
357+
) and
358+
translateFunction(func)
359+
)
308360
} or
309361
// A local declaration
310362
TTranslatedDeclarationEntry(DeclarationEntry entry) {
311363
exists(DeclStmt declStmt |
364+
translateStmt(declStmt) and
312365
declStmt.getADeclarationEntry() = entry
313366
)
314367
} or

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
private import IR
22
import cpp
3+
import semmle.code.cpp.ir.IRConfiguration
4+
5+
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
6+
7+
/**
8+
* The query can extend this class to control which functions are printed.
9+
*/
10+
class PrintIRConfiguration extends TPrintIRConfiguration {
11+
string toString() {
12+
result = "PrintIRConfiguration"
13+
}
14+
15+
/**
16+
* Holds if the IR for `func` should be printed. By default, holds for all
17+
* functions.
18+
*/
19+
predicate shouldPrintFunction(Function func) {
20+
any()
21+
}
22+
}
23+
24+
private predicate shouldPrintFunction(Function func) {
25+
exists(PrintIRConfiguration config |
26+
config.shouldPrintFunction(func)
27+
)
28+
}
29+
30+
/**
31+
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
32+
*/
33+
private class FilteredIRConfiguration extends IRConfiguration {
34+
override predicate shouldCreateIRForFunction(Function func) {
35+
shouldPrintFunction(func)
36+
}
37+
}
338

439
private string getAdditionalInstructionProperty(Instruction instr, string key) {
540
exists(IRPropertyProvider provider |
@@ -14,9 +49,15 @@ private string getAdditionalBlockProperty(IRBlock block, string key) {
1449
}
1550

1651
private newtype TPrintableIRNode =
17-
TPrintableFunctionIR(FunctionIR funcIR) or
18-
TPrintableIRBlock(IRBlock block) or
19-
TPrintableInstruction(Instruction instr)
52+
TPrintableFunctionIR(FunctionIR funcIR) {
53+
shouldPrintFunction(funcIR.getFunction())
54+
} or
55+
TPrintableIRBlock(IRBlock block) {
56+
shouldPrintFunction(block.getFunction())
57+
} or
58+
TPrintableInstruction(Instruction instr) {
59+
shouldPrintFunction(instr.getFunction())
60+
}
2061

2162
/**
2263
* A node to be emitted in the IR graph.

0 commit comments

Comments
 (0)