Merge pull request #2638 from jbj/ir-dispatch

C++ IR: Support for global virtual dispatch
This commit is contained in:
Geoffrey White
2020-01-20 12:04:09 +00:00
committed by GitHub
4 changed files with 221 additions and 46 deletions

View File

@@ -44,3 +44,89 @@ void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) {
sink(topRef.notSource2()); // no flow [FALSE POSITIVE]
topRef.notSink(source()); // no flow [FALSE POSITIVE]
}
Top *globalBottom, *globalMiddle;
Top *readGlobalBottom() {
return globalBottom;
}
void DispatchThroughGlobal() {
sink(globalBottom->isSource1()); // flow [NOT DETECTED by AST]
sink(globalMiddle->isSource1()); // no flow
sink(readGlobalBottom()->isSource1()); // flow [NOT DETECTED by AST]
globalBottom = new Bottom();
globalMiddle = new Middle();
}
Top *allocateBottom() {
return new Bottom();
}
void callSinkByPointer(Top *top) {
top->isSink(source()); // flow [NOT DETECTED by AST]
}
void callSinkByReference(Top &top) {
top.isSink(source()); // flow [NOT DETECTED by AST]
}
void globalVirtualDispatch() {
callSinkByPointer(allocateBottom());
callSinkByReference(*allocateBottom());
Top *x = allocateBottom();
x->isSink(source()); // flow [NOT DETECTED by AST]
}
Top *identity(Top *top) {
return top;
}
void callIdentityFunctions(Top *top, Bottom *bottom) {
identity(bottom)->isSink(source()); // flow [NOT DETECTED]
identity(top)->isSink(source()); // now flow
}
using SinkFunctionType = void (*)(int);
void callSink(int x) {
sink(x);
}
SinkFunctionType returnCallSink() {
return callSink;
}
void testFunctionPointer(SinkFunctionType maybeCallSink, SinkFunctionType dontCallSink, bool b) {
if (b) {
maybeCallSink = returnCallSink();
}
maybeCallSink(source()); // flow [NOT DETECTED by AST]
dontCallSink(source()); // no flow
}
namespace virtual_inheritance {
struct Top {
virtual int isSource() { return 0; }
};
struct Middle : virtual Top {
int isSource() override { return source(); }
};
struct Bottom : Middle {
};
void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) {
// Because the inheritance from `Top` is virtual, the following casts go
// directly from `Bottom` to `Top`, skipping `Middle`. That means we don't
// get flow from a `Middle` value to the call qualifier.
Top *topPtr = bottomPtr, &topRef = bottomRef;
sink(topPtr->isSource()); // flow [NOT DETECTED]
sink(topRef.isSource()); // flow [NOT DETECTED]
}
}

View File

@@ -10,8 +10,14 @@
| dispatch.cpp:16:37:16:42 | dispatch.cpp:40:15:40:23 | IR only |
| dispatch.cpp:22:37:22:42 | dispatch.cpp:31:16:31:24 | IR only |
| dispatch.cpp:22:37:22:42 | dispatch.cpp:39:15:39:23 | IR only |
| dispatch.cpp:22:37:22:42 | dispatch.cpp:55:22:55:30 | IR only |
| dispatch.cpp:22:37:22:42 | dispatch.cpp:58:28:58:36 | IR only |
| dispatch.cpp:33:18:33:23 | dispatch.cpp:23:38:23:38 | IR only |
| dispatch.cpp:41:17:41:22 | dispatch.cpp:23:38:23:38 | IR only |
| dispatch.cpp:69:15:69:20 | dispatch.cpp:23:38:23:38 | IR only |
| dispatch.cpp:73:14:73:19 | dispatch.cpp:23:38:23:38 | IR only |
| dispatch.cpp:81:13:81:18 | dispatch.cpp:23:38:23:38 | IR only |
| dispatch.cpp:107:17:107:22 | dispatch.cpp:96:8:96:8 | IR only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only |
| lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only |

View File

@@ -14,6 +14,9 @@
| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:45:18:45:23 | call to source |
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:33:18:33:23 | call to source |
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:41:17:41:22 | call to source |
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:69:15:69:20 | call to source |
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:73:14:73:19 | call to source |
| dispatch.cpp:23:38:23:38 | x | dispatch.cpp:81:13:81:18 | call to source |
| dispatch.cpp:31:16:31:24 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
| dispatch.cpp:32:16:32:24 | call to isSource2 | dispatch.cpp:16:37:16:42 | call to source |
| dispatch.cpp:35:16:35:25 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
@@ -22,6 +25,9 @@
| dispatch.cpp:40:15:40:23 | call to isSource2 | dispatch.cpp:16:37:16:42 | call to source |
| dispatch.cpp:43:15:43:24 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source |
| dispatch.cpp:44:15:44:24 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source |
| dispatch.cpp:55:22:55:30 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
| dispatch.cpp:58:28:58:36 | call to isSource1 | dispatch.cpp:22:37:22:42 | call to source |
| dispatch.cpp:96:8:96:8 | x | dispatch.cpp:107:17:107:22 | call to source |
| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source |
| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source |
| test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source |