C++: Better support for flow-through.

This commit is contained in:
Mathias Vorreiter Pedersen
2022-11-22 13:54:44 +00:00
parent 7658df9ebd
commit 623372238d
4 changed files with 87 additions and 11 deletions

View File

@@ -595,10 +595,33 @@ predicate indirectReturnOutNodeInstruction0(
instructionForfullyConvertedCall(instr, call)
}
/**
* Holds if `node` is an indirect operand with columns `(operand, indirectionIndex)`, and
* `operand` represents a use of the fully converted value of `call`.
*/
private predicate hasOperand(Node node, CallInstruction call, int indirectionIndex, Operand operand) {
indirectReturnOutNodeOperand0(call, operand, indirectionIndex) and
hasOperandAndIndex(node, operand, indirectionIndex)
}
/**
* Holds if `node` is an indirect instruction with columns `(instr, indirectionIndex)`, and
* `instr` represents a use of the fully converted value of `call`.
*
* Note that `hasOperand(node, _, _, _)` implies `not hasInstruction(node, _, _, _)`.
*/
private predicate hasInstruction(
Node node, CallInstruction call, int indirectionIndex, Instruction instr
) {
indirectReturnOutNodeInstruction0(call, instr, indirectionIndex) and
hasInstructionAndIndex(node, instr, indirectionIndex)
}
/**
* INTERNAL: do not use.
*
* A node representing the value of a function call.
* A node representing the indirect value of a function call (i.e., a value hidden
* behind a number of indirections).
*/
class IndirectReturnOutNode extends Node {
CallInstruction call;
@@ -607,20 +630,43 @@ class IndirectReturnOutNode extends Node {
IndirectReturnOutNode() {
// Annoyingly, we need to pick the fully converted value as the output of the function to
// make flow through in the shared dataflow library work correctly.
exists(Operand operand |
indirectReturnOutNodeOperand0(call, operand, indirectionIndex) and
hasOperandAndIndex(this, operand, indirectionIndex)
)
hasOperand(this, call, indirectionIndex, _)
or
exists(Instruction instr |
indirectReturnOutNodeInstruction0(call, instr, indirectionIndex) and
hasInstructionAndIndex(this, instr, indirectionIndex)
)
hasInstruction(this, call, indirectionIndex, _)
}
CallInstruction getCallInstruction() { result = call }
int getIndirectionIndex() { result = indirectionIndex }
/** Gets the operand associated with this node, if any. */
Operand getOperand() { hasOperand(this, call, indirectionIndex, result) }
/** Gets the instruction associated with this node, if any. */
Instruction getInstruction() { hasInstruction(this, call, indirectionIndex, result) }
}
/**
* An `IndirectReturnOutNode` which is used as a destination of a store operation.
* When it's used for a store operation it's useful to have this be a `PostUpdateNode` for
* the shared dataflow library's flow-through mechanism to detect flow in cases such as:
* ```cpp
* struct MyInt {
* int i;
* int& getRef() { return i; }
* };
* ...
* MyInt mi;
* mi.getRef() = source(); // this is detected as a store to `i` via flow-through.
* sink(mi.i);
* ```
*/
private class PostIndirectReturnOutNode extends IndirectReturnOutNode, PostUpdateNode {
PostIndirectReturnOutNode() {
any(StoreInstruction store).getDestinationAddressOperand() = this.getOperand()
}
override Node getPreUpdateNode() { result = this }
}
private Type getTypeImpl(Type t, int indirectionIndex) {

View File

@@ -21,6 +21,16 @@ compatibleTypesReflexive
unreachableNodeCCtx
localCallNodes
postIsNotPre
| A.cpp:98:12:98:18 | new indirection | PostUpdateNode should not equal its pre-update node. |
| B.cpp:6:15:6:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
| B.cpp:15:15:15:27 | new indirection | PostUpdateNode should not equal its pre-update node. |
| C.cpp:22:12:22:21 | new indirection | PostUpdateNode should not equal its pre-update node. |
| C.cpp:24:16:24:25 | new indirection | PostUpdateNode should not equal its pre-update node. |
| D.cpp:28:15:28:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
| D.cpp:35:15:35:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
| D.cpp:42:15:42:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
| D.cpp:49:15:49:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
| D.cpp:56:15:56:24 | new indirection | PostUpdateNode should not equal its pre-update node. |
postHasUniquePre
uniquePostUpdate
| aliasing.cpp:70:11:70:11 | VariableAddress indirection | Node has multiple PostUpdateNodes. |
@@ -41,6 +51,16 @@ postIsInSameCallable
reverseRead
argHasPostUpdate
postWithInFlow
| A.cpp:98:12:98:18 | new indirection | PostUpdateNode should not be the target of local flow. |
| B.cpp:6:15:6:24 | new indirection | PostUpdateNode should not be the target of local flow. |
| B.cpp:15:15:15:27 | new indirection | PostUpdateNode should not be the target of local flow. |
| C.cpp:22:12:22:21 | new indirection | PostUpdateNode should not be the target of local flow. |
| C.cpp:24:16:24:25 | new indirection | PostUpdateNode should not be the target of local flow. |
| D.cpp:28:15:28:24 | new indirection | PostUpdateNode should not be the target of local flow. |
| D.cpp:35:15:35:24 | new indirection | PostUpdateNode should not be the target of local flow. |
| D.cpp:42:15:42:24 | new indirection | PostUpdateNode should not be the target of local flow. |
| D.cpp:49:15:49:24 | new indirection | PostUpdateNode should not be the target of local flow. |
| D.cpp:56:15:56:24 | new indirection | PostUpdateNode should not be the target of local flow. |
| realistic.cpp:54:16:54:47 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
| realistic.cpp:60:16:60:18 | memcpy output argument | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge

View File

@@ -64,7 +64,7 @@ void test_myint_method_assignment()
mi.get() = source();
sink(mi); // $ MISSING: ast,ir
sink(mi.get()); // $ ast MISSING: ir
sink(mi.get()); // $ ast,ir
}
void test_myint_overloaded_assignment()
@@ -107,7 +107,7 @@ void test_myarray_method_assignment()
ma.get(0) = source();
sink(ma.get(0)); // $ MISSING: ast,ir
sink(ma.get(0)); // $ ir MISSING: ast
}
void test_myarray_overloaded_assignment()

View File

@@ -320,6 +320,11 @@ compatibleTypesReflexive
unreachableNodeCCtx
localCallNodes
postIsNotPre
| condition_decls.cpp:3:13:3:22 | new indirection | PostUpdateNode should not equal its pre-update node. |
| defdestructordeleteexpr.cpp:4:9:4:15 | new indirection | PostUpdateNode should not equal its pre-update node. |
| deleteexpr.cpp:7:9:7:15 | new indirection | PostUpdateNode should not equal its pre-update node. |
| ir.cpp:943:3:943:11 | new indirection | PostUpdateNode should not equal its pre-update node. |
| ir.cpp:947:3:947:25 | new indirection | PostUpdateNode should not equal its pre-update node. |
postHasUniquePre
uniquePostUpdate
| cpp11.cpp:82:17:82:17 | this indirection | Node has multiple PostUpdateNodes. |
@@ -343,13 +348,18 @@ postIsInSameCallable
reverseRead
argHasPostUpdate
postWithInFlow
| condition_decls.cpp:3:13:3:22 | new indirection | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:77:19:77:21 | call to Val | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:11:82:14 | call to Val | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:45:82:48 | call to Val | PostUpdateNode should not be the target of local flow. |
| cpp11.cpp:82:51:82:51 | call to Val | PostUpdateNode should not be the target of local flow. |
| defdestructordeleteexpr.cpp:4:9:4:15 | new indirection | PostUpdateNode should not be the target of local flow. |
| deleteexpr.cpp:7:9:7:15 | new indirection | PostUpdateNode should not be the target of local flow. |
| ir.cpp:809:7:809:13 | call to Base | PostUpdateNode should not be the target of local flow. |
| ir.cpp:810:7:810:26 | call to Base | PostUpdateNode should not be the target of local flow. |
| ir.cpp:823:7:823:13 | call to Base | PostUpdateNode should not be the target of local flow. |
| ir.cpp:824:7:824:26 | call to Base | PostUpdateNode should not be the target of local flow. |
| ir.cpp:943:3:943:11 | new indirection | PostUpdateNode should not be the target of local flow. |
| ir.cpp:947:3:947:25 | new indirection | PostUpdateNode should not be the target of local flow. |
| try_catch.cpp:7:8:7:8 | call to exception | PostUpdateNode should not be the target of local flow. |
viableImplInCallContextTooLarge