Merge pull request #4562 from criemen/printast-labels

C++: Change PrintAST to provide the predicates that can be used to traverse the AST.
This commit is contained in:
Cornelius Riemenschneider
2020-10-30 15:48:46 +01:00
committed by GitHub
3 changed files with 5571 additions and 5314 deletions

View File

@@ -124,23 +124,38 @@ class PrintASTNode extends TPrintASTNode {
* regular parent/child relation traversal.
*/
final PrintASTNode getChild(int childIndex) {
result = getChildInternal(childIndex)
or
// We first compute the first available child index that is not used by
// `getChildInternal`, then we synthesize the child for fully converted
// expressions at `nextAvailableIndex` plus the childIndex of the non-converted
// expression. This ensures that both disjuncts are disjoint.
exists(int nonConvertedIndex, int nextAvailableIndex, Expr expr |
nextAvailableIndex = max(int idx | exists(this.getChildInternal(idx))) + 1 and
childIndex - nextAvailableIndex = nonConvertedIndex and
expr = getChildInternal(nonConvertedIndex).(ASTNode).getAST()
|
// The exact value of `childIndex` doesn't matter, as long as we preserve the correct order.
result =
rank[childIndex](PrintASTNode child, int nonConvertedIndex, boolean isConverted |
childAndAccessorPredicate(child, _, nonConvertedIndex, isConverted)
|
// Unconverted children come first, then sort by original child index within each group.
child order by isConverted, nonConvertedIndex
)
}
/**
* Gets the node for the `.getFullyConverted()` version of the child originally at index
* `childIndex`, if that node has any conversions.
*/
private PrintASTNode getConvertedChild(int childIndex) {
exists(Expr expr |
expr = getChildInternal(childIndex).(ASTNode).getAST() and
expr.getFullyConverted() instanceof Conversion and
result.(ASTNode).getAST() = expr.getFullyConverted() and
not expr instanceof Conversion
)
}
/**
* Gets the child access predicate for the `.getFullyConverted()` version of the child originally
* at index `childIndex`, if that node has any conversions.
*/
private string getConvertedChildAccessorPredicate(int childIndex) {
exists(getConvertedChild(childIndex)) and
result = getChildAccessorPredicateInternal(childIndex) + ".getFullyConverted()"
}
/**
* Holds if this node should be printed in the output. By default, all nodes
* within a function are printed, but the query can override
@@ -173,33 +188,46 @@ class PrintASTNode extends TPrintASTNode {
}
/**
* Gets the label for the edge from this node to the specified child. By
* default, this is just the index of the child, but subclasses can override
* this.
* Holds if there is a child node `child` for original child index `nonConvertedIndex` with
* predicate name `childPredicate`. If the original child at that index has any conversions, there
* will be two result tuples for this predicate: one with the original child and predicate, with
* `isConverted = false`, and the other with the `.getFullyConverted()` version of the child and
* predicate, with `isConverted = true`. For a child without any conversions, there will be only
* one result tuple, with `isConverted = false`.
*/
string getChildEdgeLabelInternal(int childIndex) {
exists(getChild(childIndex)) and
result = childIndex.toString()
private predicate childAndAccessorPredicate(
PrintASTNode child, string childPredicate, int nonConvertedIndex, boolean isConverted
) {
child = getChildInternal(nonConvertedIndex) and
childPredicate = getChildAccessorPredicateInternal(nonConvertedIndex) and
isConverted = false
or
child = getConvertedChild(nonConvertedIndex) and
childPredicate = getConvertedChildAccessorPredicate(nonConvertedIndex) and
isConverted = true
}
/**
* Gets the label for the edge from this node to the specified child,
* including labels for edges to nodes that represent conversions.
* Gets the QL predicate that can be used to access the child at `childIndex`.
* May not always return a QL predicate, see for example `FunctionNode`.
*/
final string getChildEdgeLabel(int childIndex) {
exists(getChildInternal(childIndex)) and
result = getChildEdgeLabelInternal(childIndex)
or
not exists(getChildInternal(childIndex)) and
exists(getChild(childIndex)) and
exists(int nonConvertedIndex, int nextAvailableIndex |
nextAvailableIndex = max(int idx | exists(this.getChildInternal(idx))) + 1 and
childIndex - nextAvailableIndex = nonConvertedIndex
|
result = getChildEdgeLabelInternal(nonConvertedIndex) + " converted"
)
final string getChildAccessorPredicate(int childIndex) {
// The exact value of `childIndex` doesn't matter, as long as we preserve the correct order.
result =
rank[childIndex](string childPredicate, int nonConvertedIndex, boolean isConverted |
childAndAccessorPredicate(_, childPredicate, nonConvertedIndex, isConverted)
|
// Unconverted children come first, then sort by original child index within each group.
childPredicate order by isConverted, nonConvertedIndex
)
}
/**
* Gets the QL predicate that can be used to access the child at `childIndex`.
* INTERNAL DO NOT USE: Does not contain accessors for the synthesized nodes for conversions.
*/
abstract string getChildAccessorPredicateInternal(int childIndex);
/**
* Gets the `Function` that contains this node.
*/
@@ -261,6 +289,10 @@ class ExprNode extends ASTNode {
result = expr.getValueCategoryString()
}
override string getChildAccessorPredicateInternal(int childIndex) {
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAST())
}
/**
* Gets the value of this expression, if it is a constant.
*/
@@ -291,8 +323,6 @@ class ConversionNode extends ExprNode {
result.getAST() = conv.getExpr() and
conv.getExpr() instanceof Conversion
}
override string getChildEdgeLabelInternal(int childIndex) { childIndex = 0 and result = "expr" }
}
/**
@@ -322,6 +352,8 @@ class DeclarationEntryNode extends BaseASTNode, TDeclarationEntryNode {
override PrintASTNode getChildInternal(int childIndex) { none() }
override string getChildAccessorPredicateInternal(int childIndex) { none() }
override string getProperty(string key) {
result = BaseASTNode.super.getProperty(key)
or
@@ -341,7 +373,10 @@ class VariableDeclarationEntryNode extends DeclarationEntryNode {
result.getAST() = ast.getVariable().getInitializer()
}
override string getChildEdgeLabelInternal(int childIndex) { childIndex = 0 and result = "init" }
override string getChildAccessorPredicateInternal(int childIndex) {
childIndex = 0 and
result = "getVariable().getInitializer()"
}
}
/**
@@ -361,6 +396,10 @@ class StmtNode extends ASTNode {
)
)
}
override string getChildAccessorPredicateInternal(int childIndex) {
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAST())
}
}
/**
@@ -389,6 +428,8 @@ class ParameterNode extends ASTNode {
final override PrintASTNode getChildInternal(int childIndex) { none() }
final override string getChildAccessorPredicateInternal(int childIndex) { none() }
final override string getProperty(string key) {
result = super.getProperty(key)
or
@@ -410,9 +451,9 @@ class InitializerNode extends ASTNode {
result.getAST() = init.getExpr()
}
override string getChildEdgeLabelInternal(int childIndex) {
override string getChildAccessorPredicateInternal(int childIndex) {
childIndex = 0 and
result = "expr"
result = "getExpr()"
}
}
@@ -432,6 +473,11 @@ class ParametersNode extends PrintASTNode, TParametersNode {
result.getAST() = func.getParameter(childIndex)
}
override string getChildAccessorPredicateInternal(int childIndex) {
exists(getChildInternal(childIndex)) and
result = "getParameter(" + childIndex.toString() + ")"
}
/**
* Gets the `Function` for which this node represents the parameters.
*/
@@ -454,6 +500,11 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
result.getAST() = ctor.getInitializer(childIndex)
}
final override string getChildAccessorPredicateInternal(int childIndex) {
exists(getChildInternal(childIndex)) and
result = "getInitializer(" + childIndex.toString() + ")"
}
/**
* Gets the `Constructor` for which this node represents the initializer list.
*/
@@ -476,6 +527,11 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
result.getAST() = dtor.getDestruction(childIndex)
}
final override string getChildAccessorPredicateInternal(int childIndex) {
exists(getChildInternal(childIndex)) and
result = "getDestruction(" + childIndex.toString() + ")"
}
/**
* Gets the `Destructor` for which this node represents the destruction list.
*/
@@ -506,14 +562,14 @@ class FunctionNode extends ASTNode {
result.(DestructorDestructionsNode).getDestructor() = func
}
override string getChildEdgeLabelInternal(int childIndex) {
childIndex = 0 and result = "params"
override string getChildAccessorPredicateInternal(int childIndex) {
childIndex = 0 and result = "<params>"
or
childIndex = 1 and result = "initializations"
childIndex = 1 and result = "<initializations>"
or
childIndex = 2 and result = "body"
childIndex = 2 and result = "getEntryPoint()"
or
childIndex = 3 and result = "destructions"
childIndex = 3 and result = "<destructions>"
}
private int getOrder() {
@@ -538,36 +594,237 @@ class FunctionNode extends ASTNode {
final Function getFunction() { result = func }
}
/**
* A node representing an `ClassAggregateLiteral`.
*/
class ClassAggregateLiteralNode extends ExprNode {
ClassAggregateLiteral list;
ClassAggregateLiteralNode() { list = ast }
override string getChildEdgeLabelInternal(int childIndex) {
exists(Field field |
list.getFieldExpr(field) = list.getChild(childIndex) and
result = "." + field.getName()
private string getChildAccessorWithoutConversions(Locatable parent, Element child) {
shouldPrintFunction(getEnclosingFunction(parent)) and
(
exists(Stmt s | s = parent |
namedStmtChildPredicates(s, child, result)
or
not namedStmtChildPredicates(s, child, _) and
exists(int n | s.getChild(n) = child and result = "getChild(" + n + ")")
)
}
or
exists(Expr expr | expr = parent |
namedExprChildPredicates(expr, child, result)
or
not namedExprChildPredicates(expr, child, _) and
exists(int n | expr.getChild(n) = child and result = "getChild(" + n + ")")
)
)
}
/**
* A node representing an `ArrayAggregateLiteral`.
*/
class ArrayAggregateLiteralNode extends ExprNode {
ArrayAggregateLiteral list;
ArrayAggregateLiteralNode() { list = ast }
override string getChildEdgeLabelInternal(int childIndex) {
exists(int elementIndex |
list.getElementExpr(elementIndex) = list.getChild(childIndex) and
result = "[" + elementIndex.toString() + "]"
private predicate namedStmtChildPredicates(Locatable s, Element e, string pred) {
shouldPrintFunction(getEnclosingFunction(s)) and
(
exists(int n | s.(BlockStmt).getStmt(n) = e and pred = "getStmt(" + n + ")")
or
s.(ComputedGotoStmt).getExpr() = e and pred = "getExpr()"
or
s.(ConstexprIfStmt).getCondition() = e and pred = "getCondition()"
or
s.(ConstexprIfStmt).getThen() = e and pred = "getThen()"
or
s.(ConstexprIfStmt).getElse() = e and pred = "getElse()"
or
s.(IfStmt).getCondition() = e and pred = "getCondition()"
or
s.(IfStmt).getThen() = e and pred = "getThen()"
or
s.(IfStmt).getElse() = e and pred = "getElse()"
or
s.(SwitchStmt).getExpr() = e and pred = "getExpr()"
or
s.(SwitchStmt).getStmt() = e and pred = "getStmt()"
or
s.(DoStmt).getCondition() = e and pred = "getCondition()"
or
s.(DoStmt).getStmt() = e and pred = "getStmt()"
or
s.(ForStmt).getInitialization() = e and pred = "getInitialization()"
or
s.(ForStmt).getCondition() = e and pred = "getCondition()"
or
s.(ForStmt).getUpdate() = e and pred = "getUpdate()"
or
s.(ForStmt).getStmt() = e and pred = "getStmt()"
or
s.(RangeBasedForStmt).getChild(0) = e and pred = "getChild(0)"
or
s.(RangeBasedForStmt).getBeginEndDeclaration() = e and pred = "getBeginEndDeclaration()"
or
s.(RangeBasedForStmt).getCondition() = e and pred = "getCondition()"
or
s.(RangeBasedForStmt).getUpdate() = e and pred = "getUpdate()"
or
s.(RangeBasedForStmt).getChild(4) = e and pred = "getChild(4)"
or
s.(RangeBasedForStmt).getStmt() = e and pred = "getStmt()"
or
s.(WhileStmt).getCondition() = e and pred = "getCondition()"
or
s.(WhileStmt).getStmt() = e and pred = "getStmt()"
or
exists(int n |
s.(DeclStmt).getDeclarationEntry(n) = e and pred = "getDeclarationEntry(" + n.toString() + ")"
)
}
or
// EmptyStmt does not have children
s.(ExprStmt).getExpr() = e and pred = "getExpr()"
or
s.(Handler).getBlock() = e and pred = "getBlock()"
or
s.(JumpStmt).getTarget() = e and pred = "getTarget()"
or
s.(MicrosoftTryStmt).getStmt() = e and pred = "getStmt()"
or
s.(MicrosoftTryExceptStmt).getCondition() = e and pred = "getCondition()"
or
s.(MicrosoftTryExceptStmt).getExcept() = e and pred = "getExcept()"
or
s.(MicrosoftTryFinallyStmt).getFinally() = e and pred = "getFinally()"
or
s.(ReturnStmt).getExpr() = e and pred = "getExpr()"
or
s.(SwitchCase).getExpr() = e and pred = "getExpr()"
or
s.(SwitchCase).getEndExpr() = e and pred = "getEndExpr()"
or
s.(TryStmt).getStmt() = e and pred = "getStmt()"
or
s.(VlaDimensionStmt).getDimensionExpr() = e and pred = "getDimensionExpr()"
)
}
private predicate namedExprChildPredicates(Expr expr, Element ele, string pred) {
shouldPrintFunction(expr.getEnclosingFunction()) and
(
expr.(Access).getTarget() = ele and pred = "getTarget()"
or
expr.(VariableAccess).getQualifier() = ele and pred = "getQualifier()"
or
exists(Field f |
expr.(ClassAggregateLiteral).getFieldExpr(f) = ele and
pred = "getFieldExpr(" + f.toString() + ")"
)
or
exists(int n |
expr.(ArrayOrVectorAggregateLiteral).getElementExpr(n) = ele and
pred = "getElementExpr(" + n.toString() + ")"
)
or
expr.(AlignofExprOperator).getExprOperand() = ele and pred = "getExprOperand()"
or
expr.(ArrayExpr).getArrayBase() = ele and pred = "getArrayBase()"
or
expr.(ArrayExpr).getArrayOffset() = ele and pred = "getArrayOffset()"
or
expr.(AssumeExpr).getOperand() = ele and pred = "getOperand()"
or
expr.(BuiltInComplexOperation).getRealOperand() = ele and pred = "getRealOperand()"
or
expr.(BuiltInComplexOperation).getImaginaryOperand() = ele and pred = "getImaginaryOperand()"
or
expr.(BuiltInVarArg).getVAList() = ele and pred = "getVAList()"
or
expr.(BuiltInVarArgCopy).getDestinationVAList() = ele and pred = "getDestinationVAList()"
or
expr.(BuiltInVarArgCopy).getSourceVAList() = ele and pred = "getSourceVAList()"
or
expr.(BuiltInVarArgsEnd).getVAList() = ele and pred = "getVAList()"
or
expr.(BuiltInVarArgsStart).getVAList() = ele and pred = "getVAList()"
or
expr.(BuiltInVarArgsStart).getLastNamedParameter() = ele and pred = "getLastNamedParameter()"
or
expr.(Call).getQualifier() = ele and pred = "getQualifier()"
or
exists(int n | expr.(Call).getArgument(n) = ele and pred = "getArgument(" + n.toString() + ")")
or
expr.(ExprCall).getExpr() = ele and pred = "getExpr()"
or
expr.(OverloadedArrayExpr).getArrayBase() = ele and pred = "getArrayBase()"
or
expr.(OverloadedArrayExpr).getArrayOffset() = ele and pred = "getArrayOffset()"
or
expr.(OverloadedPointerDereferenceExpr).getExpr() = ele and pred = "getExpr()"
or
expr.(CommaExpr).getLeftOperand() = ele and pred = "getLeftOperand()"
or
expr.(CommaExpr).getRightOperand() = ele and pred = "getRightOperand()"
or
expr.(ConditionDeclExpr).getVariableAccess() = ele and pred = "getVariableAccess()"
or
expr.(ConstructorFieldInit).getExpr() = ele and pred = "getExpr()"
or
expr.(Conversion).getExpr() = ele and pred = "getExpr()"
or
expr.(DeleteArrayExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()"
or
expr.(DeleteArrayExpr).getDestructorCall() = ele and pred = "getDestructorCall()"
or
expr.(DeleteArrayExpr).getExpr() = ele and pred = "getExpr()"
or
expr.(DeleteExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()"
or
expr.(DeleteExpr).getDestructorCall() = ele and pred = "getDestructorCall()"
or
expr.(DeleteExpr).getExpr() = ele and pred = "getExpr()"
or
expr.(DestructorFieldDestruction).getExpr() = ele and pred = "getExpr()"
or
expr.(FoldExpr).getInitExpr() = ele and pred = "getInitExpr()"
or
expr.(FoldExpr).getPackExpr() = ele and pred = "getPackExpr()"
or
expr.(LambdaExpression).getInitializer() = ele and pred = "getInitializer()"
or
expr.(NewOrNewArrayExpr).getAllocatorCall() = ele and pred = "getAllocatorCall()"
or
expr.(NewOrNewArrayExpr).getAlignmentArgument() = ele and pred = "getAlignmentArgument()"
or
expr.(NewArrayExpr).getInitializer() = ele and pred = "getInitializer()"
or
expr.(NewArrayExpr).getExtent() = ele and pred = "getExtent()"
or
expr.(NewExpr).getInitializer() = ele and pred = "getInitializer()"
or
expr.(NoExceptExpr).getExpr() = ele and pred = "getExpr()"
or
expr.(Assignment).getLValue() = ele and pred = "getLValue()"
or
expr.(Assignment).getRValue() = ele and pred = "getRValue()"
or
not expr instanceof RelationalOperation and
expr.(BinaryOperation).getLeftOperand() = ele and
pred = "getLeftOperand()"
or
not expr instanceof RelationalOperation and
expr.(BinaryOperation).getRightOperand() = ele and
pred = "getRightOperand()"
or
expr.(RelationalOperation).getGreaterOperand() = ele and pred = "getGreaterOperand()"
or
expr.(RelationalOperation).getLesserOperand() = ele and pred = "getLesserOperand()"
or
expr.(ConditionalExpr).getCondition() = ele and pred = "getCondition()"
or
// If ConditionalExpr is in two-operand form, getThen() = getCondition() holds
not expr.(ConditionalExpr).isTwoOperand() and
expr.(ConditionalExpr).getThen() = ele and
pred = "getThen()"
or
expr.(ConditionalExpr).getElse() = ele and pred = "getElse()"
or
expr.(UnaryOperation).getOperand() = ele and pred = "getOperand()"
or
expr.(SizeofExprOperator).getExprOperand() = ele and pred = "getExprOperand()"
or
expr.(StmtExpr).getStmt() = ele and pred = "getStmt()"
or
expr.(ThrowExpr).getExpr() = ele and pred = "getExpr()"
or
expr.(TypeidOperator).getExpr() = ele and pred = "getExpr()"
)
}
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
@@ -586,7 +843,7 @@ query predicate edges(PrintASTNode source, PrintASTNode target, string key, stri
target.shouldPrint() and
target = source.getChild(childIndex) and
(
key = "semmle.label" and value = source.getChildEdgeLabel(childIndex)
key = "semmle.label" and value = source.getChildAccessorPredicate(childIndex)
or
key = "semmle.order" and value = childIndex.toString()
)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff