Predicate ExprFlowCached::asExprInternal
Gets the expression associated with node n, if any.
Unlike n.asExpr(), this predicate will also get the
expression *(x + i) when n is the indirect node
for x. This ensures that an assignment in a long chain
of assignments in a macro expansion is properly mapped
to the previous assignment. For example, in:
*x = source();
use(x[0]);
use(x[1]);
...
use(x[i]);
use(x[i+1]);
...
use(x[N]);
To see what the problem would be if asExpr(n) was replaced
with n.asExpr(), consider the transitive closure over
localStepFromNonExpr in localStepsToExpr. We start at n2
for which n.asExpr() exists. For example, n2 in the above
example could be a x[i] in any of the use(x[i]) above.
We then step to a dataflow predecessor of n2. In the above
code fragment, thats the indirect node corresponding to x in
x[i-1]. Since this doesn’t have a result for Node::asExpr()
we continue with the recursion until we reach *x = source()
which does have a result for Node::asExpr().
If N is very large this blows up.
To fix this, we map the indirect node corresponding to x to
in x[i - 1] to the x[i - 1] expression. This ensures that
x[i] steps to the expression x[i - 1] without traversing the
entire chain.
Import path
import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil