Checking if two statements can be reached in one control flow
This can be solved with a "context-free reachability" query in a graph.  Each function call corresponds to an open parenthesis, each return corresponds to a close parenthesis, and you want to know whether there is a path in the graph such that the sequence of parentheses formed is properly nested and that traverses those two nodes in order.  If you search on that term you should find papers with algorithms for that problem.

The exact nature of the context-free language depends on how you formulate the question.  Suppose we want to know whether there is a path in the program that respects function calls and returns and visits $u$ and $v$, in that order.  One way is to ask whether there exists a path through the graph that starts at $s$ (the start point of the program), then eventually visits $u$, then eventually visits $v$, and where the word formed by this path is in the Dyck language $L$ of properly nested parentheses, e.g., $S = L(S)$ where $S := \varepsilon | (S)$.  Equivalently, you can ask whether there exists a path in the graph that starts at $u$ and ends at $v$, and where the word formed by this paths in a different context-free language $L'$, namely, the set of all suffixes of words in $L$.  Here $L'$ is context-free, as it can be recognized by the grammar $S' := S | S)$.  This then becomes a context-free reachability query on the graph.  In practice we have multiple parentheses symbols, one per function.  You can find these kinds of details in papers on context-free reachability.