Merge pull request #517 from dave-bartolomeo/dave/IRFilter

C++: Don't generate IR for functions with bad ASTs
This commit is contained in:
Jonas Jensen
2018-11-22 10:02:18 +01:00
committed by GitHub
12 changed files with 540 additions and 24 deletions

View File

@@ -59,18 +59,36 @@ private predicate locationSortKeys(Locatable ast, string file, int line,
)
}
private Function getEnclosingFunction(Locatable ast) {
result = ast.(Expr).getEnclosingFunction() or
result = ast.(Stmt).getEnclosingFunction() or
result = ast.(Initializer).getExpr().getEnclosingFunction() or
result = ast.(Parameter).getFunction() or
exists(DeclStmt stmt |
stmt.getADeclarationEntry() = ast and
result = stmt.getEnclosingFunction()
) or
result = ast
}
/**
* Most nodes are just a wrapper around `Locatable`, but we do synthesize new
* nodes for things like parameter lists and constructor init lists.
*/
private newtype TPrintASTNode =
TASTNode(Locatable ast) or
TParametersNode(Function func) or
TASTNode(Locatable ast) {
shouldPrintFunction(getEnclosingFunction(ast))
} or
TParametersNode(Function func) {
shouldPrintFunction(func)
} or
TConstructorInitializersNode(Constructor ctor) {
ctor.hasEntryPoint()
ctor.hasEntryPoint() and
shouldPrintFunction(ctor)
} or
TDestructorDestructionsNode(Destructor dtor) {
dtor.hasEntryPoint()
dtor.hasEntryPoint() and
shouldPrintFunction(dtor)
}
/**

View File

@@ -0,0 +1,19 @@
import cpp
private newtype TIRConfiguration = MkIRConfiguration()
/**
* The query can extend this class to control which functions have IR generated for them.
*/
class IRConfiguration extends TIRConfiguration {
string toString() {
result = "IRConfiguration"
}
/**
* Holds if IR should be created for function `func`. By default, holds for all functions.
*/
predicate shouldCreateIRForFunction(Function func) {
any()
}
}

View File

@@ -1,5 +1,40 @@
private import IR
import cpp
import semmle.code.cpp.ir.IRConfiguration
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
/**
* The query can extend this class to control which functions are printed.
*/
class PrintIRConfiguration extends TPrintIRConfiguration {
string toString() {
result = "PrintIRConfiguration"
}
/**
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Function func) {
any()
}
}
private predicate shouldPrintFunction(Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
}
/**
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
*/
private class FilteredIRConfiguration extends IRConfiguration {
override predicate shouldCreateIRForFunction(Function func) {
shouldPrintFunction(func)
}
}
private string getAdditionalInstructionProperty(Instruction instr, string key) {
exists(IRPropertyProvider provider |
@@ -14,9 +49,15 @@ private string getAdditionalBlockProperty(IRBlock block, string key) {
}
private newtype TPrintableIRNode =
TPrintableFunctionIR(FunctionIR funcIR) or
TPrintableIRBlock(IRBlock block) or
TPrintableInstruction(Instruction instr)
TPrintableFunctionIR(FunctionIR funcIR) {
shouldPrintFunction(funcIR.getFunction())
} or
TPrintableIRBlock(IRBlock block) {
shouldPrintFunction(block.getFunction())
} or
TPrintableInstruction(Instruction instr) {
shouldPrintFunction(instr.getFunction())
}
/**
* A node to be emitted in the IR graph.

View File

@@ -1,5 +1,40 @@
private import IR
import cpp
import semmle.code.cpp.ir.IRConfiguration
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
/**
* The query can extend this class to control which functions are printed.
*/
class PrintIRConfiguration extends TPrintIRConfiguration {
string toString() {
result = "PrintIRConfiguration"
}
/**
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Function func) {
any()
}
}
private predicate shouldPrintFunction(Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
}
/**
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
*/
private class FilteredIRConfiguration extends IRConfiguration {
override predicate shouldCreateIRForFunction(Function func) {
shouldPrintFunction(func)
}
}
private string getAdditionalInstructionProperty(Instruction instr, string key) {
exists(IRPropertyProvider provider |
@@ -14,9 +49,15 @@ private string getAdditionalBlockProperty(IRBlock block, string key) {
}
private newtype TPrintableIRNode =
TPrintableFunctionIR(FunctionIR funcIR) or
TPrintableIRBlock(IRBlock block) or
TPrintableInstruction(Instruction instr)
TPrintableFunctionIR(FunctionIR funcIR) {
shouldPrintFunction(funcIR.getFunction())
} or
TPrintableIRBlock(IRBlock block) {
shouldPrintFunction(block.getFunction())
} or
TPrintableInstruction(Instruction instr) {
shouldPrintFunction(instr.getFunction())
}
/**
* A node to be emitted in the IR graph.

View File

@@ -1,5 +1,7 @@
import cpp
import cpp
import semmle.code.cpp.ir.implementation.raw.IR
private import semmle.code.cpp.ir.IRConfiguration
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
private import semmle.code.cpp.ir.internal.TempVariableTag
@@ -83,7 +85,8 @@ private predicate ignoreExprOnly(Expr expr) {
// Ignore the allocator call, because we always synthesize it. Don't ignore
// its arguments, though, because we use them as part of the synthesis.
newExpr.getAllocatorCall() = expr
)
) or
not translateFunction(expr.getEnclosingFunction())
}
/**
@@ -94,6 +97,49 @@ private predicate ignoreExpr(Expr expr) {
ignoreExprAndDescendants(getRealParent*(expr))
}
/**
* Holds if `func` contains an AST that cannot be translated into IR. This is mostly used to work
* around extractor bugs. Once the relevant extractor bugs are fixed, this predicate can be removed.
*/
private predicate isInvalidFunction(Function func) {
exists(Literal literal |
// Constructor field inits within a compiler-generated copy constructor have a source expression
// that is a `Literal` with no value.
literal = func.(Constructor).getAnInitializer().(ConstructorFieldInit).getExpr() and
not exists(literal.getValue())
) or
exists(ThisExpr thisExpr |
// An instantiation of a member function template is not treated as a `MemberFunction` if it has
// only non-type template arguments.
thisExpr.getEnclosingFunction() = func and
not func instanceof MemberFunction
) or
exists(Expr expr |
// Expression missing a type.
expr.getEnclosingFunction() = func and
not exists(expr.getType())
)
}
/**
* Holds if `func` should be translated to IR.
*/
private predicate translateFunction(Function func) {
not func.isFromUninstantiatedTemplate(_) and
func.hasEntryPoint() and
not isInvalidFunction(func) and
exists(IRConfiguration config |
config.shouldCreateIRForFunction(func)
)
}
/**
* Holds if `stmt` should be translated to IR.
*/
private predicate translateStmt(Stmt stmt) {
translateFunction(stmt.getEnclosingFunction())
}
/**
* Holds if `expr` is most naturally evaluated as control flow, rather than as
* a value.
@@ -236,7 +282,7 @@ newtype TTranslatedElement =
} or
// The initialization of a field via a member of an initializer list.
TTranslatedExplicitFieldInitialization(Expr ast, Field field,
Expr expr) {
Expr expr) {
exists(ClassAggregateLiteral initList |
not ignoreExpr(initList) and
ast = initList and
@@ -260,14 +306,14 @@ newtype TTranslatedElement =
} or
// The initialization of an array element via a member of an initializer list.
TTranslatedExplicitElementInitialization(
ArrayAggregateLiteral initList, int elementIndex) {
ArrayAggregateLiteral initList, int elementIndex) {
not ignoreExpr(initList) and
exists(initList.getElementExpr(elementIndex))
} or
// The value initialization of a range of array elements that were omitted
// from an initializer list.
TTranslatedElementValueInitialization(ArrayAggregateLiteral initList,
int elementIndex, int elementCount) {
int elementIndex, int elementCount) {
not ignoreExpr(initList) and
isFirstValueInitializedElementInRange(initList, elementIndex) and
elementCount =
@@ -287,28 +333,35 @@ newtype TTranslatedElement =
not ignoreExpr(destruction)
} or
// A statement
TTranslatedStmt(Stmt stmt) or
TTranslatedStmt(Stmt stmt) {
translateStmt(stmt)
} or
// A function
TTranslatedFunction(Function func) {
func.hasEntryPoint() and
not func.isFromUninstantiatedTemplate(_)
translateFunction(func)
} or
// A constructor init list
TTranslatedConstructorInitList(Function func) {
func.hasEntryPoint()
translateFunction(func)
} or
// A destructor destruction list
TTranslatedDestructorDestructionList(Function func) {
func.hasEntryPoint()
translateFunction(func)
} or
// A function parameter
TTranslatedParameter(Parameter param) {
param.getFunction().hasEntryPoint() or
exists(param.getCatchBlock())
exists(Function func |
(
func = param.getFunction() or
func = param.getCatchBlock().getEnclosingFunction()
) and
translateFunction(func)
)
} or
// A local declaration
TTranslatedDeclarationEntry(DeclarationEntry entry) {
exists(DeclStmt declStmt |
translateStmt(declStmt) and
declStmt.getADeclarationEntry() = entry
)
} or

View File

@@ -1,5 +1,40 @@
private import IR
import cpp
import semmle.code.cpp.ir.IRConfiguration
private newtype TPrintIRConfiguration = MkPrintIRConfiguration()
/**
* The query can extend this class to control which functions are printed.
*/
class PrintIRConfiguration extends TPrintIRConfiguration {
string toString() {
result = "PrintIRConfiguration"
}
/**
* Holds if the IR for `func` should be printed. By default, holds for all
* functions.
*/
predicate shouldPrintFunction(Function func) {
any()
}
}
private predicate shouldPrintFunction(Function func) {
exists(PrintIRConfiguration config |
config.shouldPrintFunction(func)
)
}
/**
* Override of `IRConfiguration` to only create IR for the functions that are to be dumped.
*/
private class FilteredIRConfiguration extends IRConfiguration {
override predicate shouldCreateIRForFunction(Function func) {
shouldPrintFunction(func)
}
}
private string getAdditionalInstructionProperty(Instruction instr, string key) {
exists(IRPropertyProvider provider |
@@ -14,9 +49,15 @@ private string getAdditionalBlockProperty(IRBlock block, string key) {
}
private newtype TPrintableIRNode =
TPrintableFunctionIR(FunctionIR funcIR) or
TPrintableIRBlock(IRBlock block) or
TPrintableInstruction(Instruction instr)
TPrintableFunctionIR(FunctionIR funcIR) {
shouldPrintFunction(funcIR.getFunction())
} or
TPrintableIRBlock(IRBlock block) {
shouldPrintFunction(block.getFunction())
} or
TPrintableInstruction(Instruction instr) {
shouldPrintFunction(instr.getFunction())
}
/**
* A node to be emitted in the IR graph.