C++: Add more QLDoc to StoreNode and LoadNode classes, and related predicates. I also simplified the code a bit by moving common implementations of predicates into shared super classes. Finally, I added a getLocation predicate to StoreNode to match the structure of the LoadNode class.

This commit is contained in:
Mathias Vorreiter Pedersen
2020-06-02 13:50:00 +02:00
parent 3adc10fdb4
commit ce34d91a07

View File

@@ -462,20 +462,46 @@ private newtype TStoreChain =
)
}
/**
* A `StoreChain` represents a series of field lookups that compute the destination of a store.
* For example, given an assignment such as `a.b.c = x`, there are two `StoreChain`s:
* One corresponding to the field `b`, and one corresponding to the field `c`. Here, `b` is the parent
* `StoreChain` of `c`.
*/
private class StoreChain extends TStoreChain {
string toString() { none() }
StoreChainConsCons getParent() { none() }
/**
* Gets the parent of this `StoreChain`, if any. For example, for the assignment
* ```
* a.b.c = x;
* ```
* the parent of `c` is `b`, and `b` has no parent.
*/
final StoreChainConsCons getParent() { result.getChild() = this }
/** Gets the child of this `StoreChain`, if any. */
StoreChain getChild() { none() }
/**
* Gets the instruction that receives flow from the outermost `StoreChain` of this chain (i.e.,
* the `StoreChain` with no parent).
*/
StoreChainEndInstruction getEndInstruction() { none() }
/**
* Gets the instruction that flows to the innermost `StoreChain` of this chain (i.e.,
* the `StoreChain` with no child).
*/
Instruction getBeginInstruction() { none() }
/** Gets the `FieldAddressInstruction` of this `StoreChain` */
FieldAddressInstruction getFieldInstruction() { none() }
/** Gets the `FieldAddressInstruction` of any `StoreChain` in this chain. */
FieldAddressInstruction getAFieldInstruction() { none() }
final Location getLocation() { result = getFieldInstruction().getLocation() }
}
private class StoreChainConsNil extends StoreChain, TStoreChainConsNil {
@@ -486,8 +512,6 @@ private class StoreChainConsNil extends StoreChain, TStoreChainConsNil {
override string toString() { result = fi.getField().toString() }
override StoreChainConsCons getParent() { result = TStoreChainConsCons(_, this) }
override StoreChainEndInstruction getEndInstruction() { result = end }
override Instruction getBeginInstruction() { result = end.getBeginInstruction() }
@@ -505,8 +529,6 @@ private class StoreChainConsCons extends StoreChain, TStoreChainConsCons {
override string toString() { result = fi.getField().toString() + "." + next.toString() }
override StoreChainConsCons getParent() { result.getChild() = this }
override StoreChain getChild() { result = next }
override FieldAddressInstruction getFieldInstruction() { result = fi }
@@ -563,18 +585,34 @@ private class LoadChainEndInstructionLoad extends LoadChainEndInstruction, LoadI
override Instruction getReadValue() { result = getSourceValueOperand().getAnyDef() }
}
/**
* A `LoadChain` represents a series of field lookups that compute the source address of a load.
* For example, given the field lookup in `f(a.b.c)`, there are two `LoadChains`s:
* One corresponding to the field `b`, and one corresponding to the field `c`. Here, `b` is the parent
* `LoadChain` of `c`.
*/
private class LoadChain extends TLoadChain {
string toString() { none() }
/**
* Gets the instruction that receives flow from the innermost `LoadChain` of this chain (i.e.,
* the `LoadChain` with no child).
*/
LoadChainEndInstruction getEndInstruction() { none() }
/**
* Gets the parent of this `LoadChain`, if any. For example in `f(a.b.c)` the parent of `c` is `b`,
* and `b` has no parent.
*/
final LoadChainConsCons getParent() { result.getChild() = this }
/** Gets the child of this `LoadChain`, if any. */
LoadChain getChild() { none() }
/** Gets the `FieldAddressInstruction` of this `LoadChain` */
FieldAddressInstruction getFieldInstruction() { none() }
Location getLocation() { none() }
final Location getLocation() { result = getFieldInstruction().getLocation() }
}
private class LoadChainConsNil extends LoadChain, TLoadChainConsNil {
@@ -588,8 +626,6 @@ private class LoadChainConsNil extends LoadChain, TLoadChainConsNil {
override LoadChainEndInstruction getEndInstruction() { result = end }
override FieldAddressInstruction getFieldInstruction() { result = fi }
override Location getLocation() { result = fi.getLocation() }
}
private class LoadChainConsCons extends LoadChain, TLoadChainConsCons {
@@ -605,11 +641,21 @@ private class LoadChainConsCons extends LoadChain, TLoadChainConsCons {
override LoadChain getChild() { result = next }
override FieldAddressInstruction getFieldInstruction() { result = fi }
override Location getLocation() { result = fi.getLocation() }
}
/** `StoreNode` also extends `ReadStepNode` to participate in reverse read steps. */
/**
* A dataflow node generated by a partial definition.
* The `StoreNode` class extends `ReadStepNode` to participate in reverse read steps.
* A reverse read is a store step that is "inferred" by the DataFlow library. For example in the
* assignment:
* ```
* a.b.c = x;
* ```
* Here, the access path after the store must reflect that a value has been stored into the field `c` of
* the object at field `b`. The field `c` is added to the access path through a `storeStep`, and the
* field `b` is inferred by the DataFlow library because there's a read step (reading the field `b`) from
* the pre update node for `b.c` to the pre update node for `c`.
*/
private class StoreNode extends TStoreNode, StoreStepNode, ReadStepNode, PartialDefinitionNode {
StoreChain storeChain;
@@ -649,6 +695,7 @@ private class StoreNode extends TStoreNode, StoreStepNode, ReadStepNode, Partial
}
}
/** A dataflow node generated by loading from an address computed by a sequence of fields lookups. */
private class LoadNode extends TLoadNode, ReadStepNode {
LoadChain loadChain;