Merge pull request #1744 from jbj/ast-field-flow-aggregate-init

C++: Field flow through ClassAggregateLiteral
This commit is contained in:
Geoffrey White
2019-08-16 09:56:11 +01:00
committed by GitHub
7 changed files with 88 additions and 20 deletions

View File

@@ -6,7 +6,7 @@ private import DataFlowDispatch
private Node getInstanceArgument(Call call) {
result.asExpr() = call.getQualifier()
or
result.(PreConstructorCallNode).getConstructorCall() = call
result.(PreObjectInitializerNode).getExpr().(ConstructorCall) = call
// This does not include the implicit `this` argument on auto-generated
// base class destructor calls as those do not have an AST element.
}
@@ -169,6 +169,14 @@ private class ArrayContent extends Content, TArrayContent {
* value of `node1`.
*/
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
exists(ClassAggregateLiteral aggr, Field field |
// The following line requires `node2` to be both an `ExprNode` and a
// `PostUpdateNode`, which means it must be an `ObjectInitializerNode`.
node2.asExpr() = aggr and
f.(FieldContent).getField() = field and
aggr.getFieldExpr(field) = node1.asExpr()
)
or
exists(FieldAccess fa |
exists(Assignment a |
node1.asExpr() = a and

View File

@@ -10,7 +10,11 @@ cached
private newtype TNode =
TExprNode(Expr e) or
TPartialDefinitionNode(PartialDefinition pd) or
TPreConstructorCallNode(ConstructorCall call) or
TPreObjectInitializerNode(Expr e) {
e instanceof ConstructorCall
or
e instanceof ClassAggregateLiteral
} or
TExplicitParameterNode(Parameter p) { exists(p.getFunction().getBlock()) } or
TInstanceParameterNode(MemberFunction f) { exists(f.getBlock()) and not f.isStatic() } or
TUninitializedNode(LocalVariable v) { not v.hasInitializer() }
@@ -256,16 +260,24 @@ class PartialDefinitionNode extends PostUpdateNode, TPartialDefinitionNode {
}
/**
* A node representing the object that was just constructed and is identified
* with the "return value" of the constructor call.
* A node representing the temporary value of an object that was just
* constructed by a constructor call or an aggregate initializer. This is only
* for objects, not for pointers to objects.
*
* These expressions are their own post-update nodes but instead have synthetic
* pre-update nodes.
*/
private class PostConstructorCallNode extends PostUpdateNode, TExprNode {
PostConstructorCallNode() { this = TExprNode(any(ConstructorCall c)) }
private class ObjectInitializerNode extends PostUpdateNode, TExprNode {
PreObjectInitializerNode pre;
override PreConstructorCallNode getPreUpdateNode() {
TExprNode(result.getConstructorCall()) = this
ObjectInitializerNode() {
// If a `Node` is associated with a `PreObjectInitializerNode`, then it's
// an `ObjectInitializerNode`.
pre.getExpr() = this.asExpr()
}
override PreObjectInitializerNode getPreUpdateNode() { result = pre }
// No override of `toString` since these nodes already have a `toString` from
// their overlap with `ExprNode`.
}
@@ -273,19 +285,19 @@ private class PostConstructorCallNode extends PostUpdateNode, TExprNode {
/**
* INTERNAL: do not use.
*
* A synthetic data-flow node that plays the role of the qualifier (or
* `this`-argument) to a constructor call.
* A synthetic data-flow node that plays the role of a temporary object that
* has not yet been initialized.
*/
class PreConstructorCallNode extends Node, TPreConstructorCallNode {
ConstructorCall getConstructorCall() { this = TPreConstructorCallNode(result) }
class PreObjectInitializerNode extends Node, TPreObjectInitializerNode {
Expr getExpr() { this = TPreObjectInitializerNode(result) }
override Function getFunction() { result = getConstructorCall().getEnclosingFunction() }
override Function getFunction() { result = getExpr().getEnclosingFunction() }
override Type getType() { result = getConstructorCall().getType() }
override Type getType() { result = getExpr().getType() }
override Location getLocation() { result = getConstructorCall().getLocation() }
override Location getLocation() { result = getExpr().getLocation() }
override string toString() { result = getConstructorCall().toString() + " [pre constructor call]" }
override string toString() { result = getExpr().toString() + " [pre init]" }
}
/**