Merge pull request #724 from jbj/cfg-pr

C++: Construct a CFG with QL
This commit is contained in:
ian-semmle
2019-01-09 13:12:39 +00:00
committed by GitHub
103 changed files with 22748 additions and 7 deletions

View File

@@ -60,7 +60,7 @@ predicate nullCheckInCondition(Expr e, Variable v, Declaration qualifier) {
or exists(NotExpr exp | exp = e and nullCheckInCondition(exp.getAnOperand(), v, qualifier))
or exists(FunctionCall c | c = e and nullCheckInCondition(c.getAnArgument(), v, qualifier) and
c.getTarget().getName() = "__builtin_expect")
or exists(ConditionDeclExpr d | d = e and nullCheckInCondition(d.getExpr(), v, qualifier))
or exists(ConditionDeclExpr d | d = e and nullCheckInCondition(d.getVariableAccess(), v, qualifier))
}
predicate hasNullCheck(Function enclosing, Variable v, Declaration qualifier) {

View File

@@ -283,7 +283,11 @@ deprecated class StackVariable extends Variable {
/**
* A C/C++ local variable. In other words, any variable that has block
* scope [N4140 3.3.3], but is not a function parameter.
* scope [N4140 3.3.3], but is not a parameter of a `Function` or `CatchBlock`.
* Local variables can be static; use the `isStatic` member predicate to detect
* those.
*
* A local variable can be declared by a `DeclStmt` or a `ConditionDeclExpr`.
*/
class LocalVariable extends LocalScopeVariable, @localvariable {
override string getName() { localvariables(underlyingElement(this),_,result) }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,247 @@
/**
* Provides classes and predicates for approximating where compiler-generated
* destructor calls should be placed. This file can be removed when the
* extractor produces this information directly.
*/
private import cpp
private predicate isDeleteDestructorCall(DestructorCall c) {
exists(DeleteExpr del | c = del.getDestructorCall())
or
exists(DeleteArrayExpr del | c = del.getDestructorCall())
}
// Things we know about these calls
// - isCompilerGenerated() always holds
// - They all have a predecessor of type VariableAccess
// - They all have successors
// - After subtracting all the jumpy dtor calls for a particular variable
// (PrematureScopeExitNode), there's at most one call left, and that will be
// the ordinary one.
// - Except for ConditionDeclExpr! One chain should be directly connected to
// the false edge out of the parent, and the other should not.
class SyntheticDestructorCall extends FunctionCall {
SyntheticDestructorCall() {
(
this instanceof DestructorCall
or
// Workaround for CPP-320
exists(Function target |
target = this.(FunctionCall).getTarget() and
not exists(target.getName())
)
) and
not exists(this.getParent()) and
not isDeleteDestructorCall(this) and
not this.isUnevaluated() and
this.isCompilerGenerated()
}
VariableAccess getAccess() { successors(result, this) }
SyntheticDestructorCall getNext() { successors(this, result.getAccess()) }
SyntheticDestructorCall getPrev() { this = result.getNext() }
}
// Things we know about these blocks
// - If they follow a JumpStmt, the VariableAccesses of their calls never
// have multiple predecessors.
// - But after ReturnStmt, that may happen.
/**
* Describes a straight line of `SyntheticDestructorCall`s. Note that such
* lines can share tails.
*/
private class SyntheticDestructorBlock extends ControlFlowNodeBase {
SyntheticDestructorBlock() {
this = any(SyntheticDestructorCall call |
not exists(call.getPrev())
or
exists(ControlFlowNodeBase pred |
not pred instanceof SyntheticDestructorCall and
successors(pred, call.getAccess())
)
)
}
SyntheticDestructorCall getCall(int i) {
i = 0 and result = this
or
result = this.getCall(i - 1).getNext()
}
ControlFlowNode getAPredecessor() {
successors(result, this.(SyntheticDestructorCall).getAccess()) and
not result instanceof SyntheticDestructorCall
}
ControlFlowNode getSuccessor() {
successors(this.getCall(max(int i | exists(this.getCall(i)))), result)
}
}
private class PrematureScopeExitNode extends ControlFlowNodeBase {
PrematureScopeExitNode() {
this instanceof JumpStmt
or
this instanceof Handler
or
this instanceof ThrowExpr
or
this instanceof ReturnStmt
or
this instanceof MicrosoftTryExceptStmt
or
// Detecting exception edges out of a MicrosoftTryFinallyStmt is not
// implemented. It may not be easy to do. It'll be something like finding
// the first synthetic destructor call that crosses out of the scope of the
// statement and does not belong to some other `PrematureScopeExitNode`.
// Note that the exception destructors after __try can follow right after
// ordinary cleanup from the __finally block.
this instanceof MicrosoftTryFinallyStmt
}
SyntheticDestructorBlock getSyntheticDestructorBlock() {
result.getAPredecessor() = this
or
// StmtExpr not handled properly here.
result.getAPredecessor().(Expr).getParent+() = this.(ReturnStmt)
or
// Only handles post-order conditions. Won't work with
// short-circuiting operators.
falsecond_base(this.(MicrosoftTryExceptStmt).getCondition(),
result.(SyntheticDestructorCall).getAccess())
}
}
private class DestructedVariable extends LocalScopeVariable {
DestructedVariable() {
exists(SyntheticDestructorCall call | call.getAccess().getTarget() = this)
}
/**
* Gets the single destructor call that that corresponds to falling off the
* end of the scope of this variable.
*/
SyntheticDestructorCall getOrdinaryCall() {
exists(SyntheticDestructorBlock block |
block.getCall(_) = result and
not exists(PrematureScopeExitNode exit | exit.getSyntheticDestructorBlock() = block) and
result.getAccess().getTarget() = this
|
falsecond_base(getDeclaringLoop().getCondition(), block.getCall(0).getAccess())
or
not exists(this.getDeclaringLoop())
)
}
predicate hasPositionInScope(int x, int y, Stmt scope) {
exists(DeclStmt declStmt |
this = declStmt.getDeclaration(y) and
declStmt = scope.getChild(x)
)
or
exists(ConditionDeclExpr decl |
this = decl.getVariable() and
// These coordinates are chosen to place the destruction correctly
// relative to the destruction of other variables declared in
// `decl.getParent()`. Only a `for` loop can have other declarations in
// it. These show up as a `DeclStmt` with `x = 0`, so by choosing `x = 1`
// here we get the `ConditionDeclExpr` placed after all variables
// declared in the init statement of the `for` loop.
x = 1 and
y = 0 and
scope = decl.getParent()
)
or
exists(CatchBlock cb |
this = cb.getParameter() and
scope = cb and
// A `CatchBlock` is a `Block`, so there might be other variables
// declared in it. These coordinates are chosen to place the Parameter
// before any such declarations.
x = -1 and
y = 0
)
}
SyntheticDestructorCall getInnerScopeCall() {
exists(SyntheticDestructorBlock block |
block.getCall(_) = result and
not exists(PrematureScopeExitNode exit | exit.getSyntheticDestructorBlock() = block) and
result.getAccess().getTarget() = this
|
exists(Loop loop | loop = this.getDeclaringLoop() |
not falsecond_base(loop.getCondition(), block.getCall(0).getAccess())
)
)
}
predicate hasPositionInInnerScope(int x, int y, ControlFlowNodeBase scope) {
exists(ConditionDeclExpr decl |
this = decl.getVariable() and
// These coordinates are chosen to place the destruction correctly
// relative to the destruction of other variables in `scope`. Only in the
// `while` case can there be other variables in `scope`, and in that case
// `scope` will be a `Block`, whose smallest `x` coordinate can be 0.
x = -1 and
y = 0 and
(
scope = decl.getParent().(ForStmt).getUpdate()
or
scope = decl.getParent().(WhileStmt).getStmt()
)
)
}
private Loop getDeclaringLoop() {
exists(ConditionDeclExpr decl | this = decl.getVariable() and result = decl.getParent())
}
}
/**
* Gets the `index`'th synthetic destructor call that should follow `node`. The
* exact placement of that call in the CFG depends on the type of `node` as
* follows:
*
* - `Block`: after ordinary control flow falls off the end of the block
* without jumps or exceptions.
* - `ReturnStmt`: After the statement itself or after its operand (if
* present).
* - `ThrowExpr`: After the `throw` expression or after its operand (if
* present).
* - `JumpStmt` (`BreakStmt`, `ContinueStmt`, `GotoStmt`): after the statement.
* - A `ForStmt`, `WhileStmt`, `SwitchStmt`, or `IfStmt`: after control flow
* falls off the end of the statement without jumping. Destruction can occur
* here for `for`-loops that have an initializer (`for (C x = a; ...; ...)`)
* and for statements whose condition is a `ConditionDeclExpr`
* (`if (C x = a)`).
* - The `getUpdate()` of a `ForStmt`: after the `getUpdate()` expression. This
* can happen when the condition is a `ConditionDeclExpr`
* - `Handler`: On the edge out of the `Handler` for the case where the
* exception was not matched and is propagated to the next handler or
* function exit point.
* - `MicrosoftTryExceptStmt`: After the false-edge out of the `e` in
* `__except(e)`, before propagating the exception up to the next handler or
* function exit point.
* - `MicrosoftTryFinallyStmt`: On the edge following the `__finally` block for
* the case where an exception was thrown and needs to be propagated.
*/
SyntheticDestructorCall getDestructorCallAfterNode(ControlFlowNodeBase node, int index) {
result = rank[index + 1](SyntheticDestructorCall call, DestructedVariable var, int x, int y |
call = var.getOrdinaryCall() and
var.hasPositionInScope(x, y, node)
or
call = var.getInnerScopeCall() and
var.hasPositionInInnerScope(x, y, node)
|
call
order by
x desc, y desc
)
or
exists(SyntheticDestructorBlock block |
node.(PrematureScopeExitNode).getSyntheticDestructorBlock() = block and
result = block.getCall(index)
)
}

View File

@@ -144,13 +144,31 @@ class AssignPointerSubExpr extends AssignOperation, @assignpsubexpr {
/**
* A C++ variable declaration in an expression where a condition is expected.
* For example, on the `ConditionDeclExpr` in `if (bool c = x < y)`,
* `getExpr()` is an access to `c` (with possible casts), and `getVariable` is
* the variable `c`, which has an initializer `x < y`.
* `getVariableAccess()` is an access to `c` (with possible casts),
* `getVariable()` is the variable `c` (which has an initializer `x < y`), and
* `getInitializingExpr()` is `x < y`.
*/
class ConditionDeclExpr extends Expr, @condition_decl {
/** Gets the access using the condition for this declaration. */
/**
* DEPRECATED: Use `getVariableAccess()` or `getInitializingExpr()` instead.
*
* Gets the access using the condition for this declaration.
*/
deprecated
Expr getExpr() { result = this.getChild(0) }
/**
* Gets the compiler-generated variable access that conceptually occurs after
* the initialization of the declared variable.
*/
VariableAccess getVariableAccess() { result = this.getChild(0) }
/**
* Gets the expression that initializes the declared variable. This predicate
* always has a result.
*/
Expr getInitializingExpr() { result = this.getVariable().getInitializer().getExpr() }
/** Gets the variable that is declared. */
Variable getVariable() { condition_decl_bind(underlyingElement(this),unresolveElement(result)) }

View File

@@ -42,12 +42,19 @@ class BuiltInNoOp extends BuiltInOperation, @noopexpr {
}
/**
* A C++ `__offsetof` expression (used by some implementations of offsetof in the presence of user-defined `operator&amp;`).
* A C++ `__offsetof` expression (used by some implementations of offsetof in the presence of user-defined `operator&`).
*/
class BuiltInOperationOffsetOf extends BuiltInOperation, @offsetofexpr {
override string toString() { result = "__offsetof" }
}
/**
* A C/C++ `__INTADDR__` expression, used by EDG to implement `offsetof` in the presence of user-defined `operator&`.
*/
class BuiltInIntAddr extends BuiltInOperation, @intaddrexpr {
override string toString() { result = "__INTADDR__" }
}
/**
* A C++ `__has_assign` expression (used by some implementations of the type_traits header).
*/

View File

@@ -2691,6 +2691,6 @@ class TranslatedConditionDeclExpr extends TranslatedNonConstantExpr {
}
private TranslatedExpr getConditionExpr() {
result = getTranslatedExpr(condDeclExpr.getExpr().getFullyConverted())
result = getTranslatedExpr(condDeclExpr.getVariableAccess().getFullyConverted())
}
}

View File

@@ -702,6 +702,13 @@ class RangeBasedForStmt extends Loop, @stmt_range_based_for {
override Expr getCondition() { result = this.getChild(2) }
override Expr getControllingExpr() { result = this.getCondition() }
/**
* Gets a declaration statement that declares first `__begin` and then
* `__end`, initializing them to the values they have before entering the
* desugared loop.
*/
DeclStmt getBeginEndDeclaration() { result = this.getChild(1) }
/**
* Gets the compiler-generated `++__begin` which is the update
* expression of this for statement after desugaring. It will

View File

@@ -8,6 +8,7 @@
| edg.c:13:14:13:45 | (...) | 0 | 0 |
| edg.c:13:14:13:45 | (mystruct *)... | 0 | 0 |
| edg.c:13:14:13:45 | (size_t)... | 0 | 0 |
| edg.c:13:14:13:45 | __INTADDR__ | 1 | 1 |
| edg.c:13:43:13:44 | f2 | 0 | 0 |
| file://:0:0:0:0 | 0 | 0 | 0 |
| file://:0:0:0:0 | * ... | 0 | 0 |

View File

@@ -0,0 +1,12 @@
typedef unsigned long size_t;
void * operator new[](size_t count, int arg1, int arg2);
template<typename T>
void callNew(T arg) {
new(2, 3) int[5];
}
void callCallNew() {
callNew(1);
}

View File

@@ -0,0 +1,146 @@
import cpp
import semmle.code.cpp.controlflow.internal.CFG
class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then
result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." +
this.getTarget().getName()
else result = super.toString()
}
}
predicate differentEdge(ControlFlowNode n1, ControlFlowNode n2, string msg) {
successors(n1, n2) and
not qlCFGSuccessor(n1, n2) and
msg = "Standard edge, only from extractor"
or
not successors(n1, n2) and
qlCFGSuccessor(n1, n2) and
msg = "Standard edge, only from QL"
or
truecond_base(n1, n2) and
not qlCFGTrueSuccessor(n1, n2) and
msg = "True edge, only from extractor"
or
not truecond_base(n1, n2) and
qlCFGTrueSuccessor(n1, n2) and
msg = "True edge, only from QL"
or
falsecond_base(n1, n2) and
not qlCFGFalseSuccessor(n1, n2) and
msg = "False edge, only from extractor"
or
not falsecond_base(n1, n2) and
qlCFGFalseSuccessor(n1, n2) and
msg = "False edge, only from QL"
}
predicate differentScope(Element e) {
exists(ControlFlowNode n1 |
getScopeElement(n1) = e and
differentEdge(n1, _, _)
)
}
private predicate isInFunction(ControlFlowNode x, Function f) {
f = x.getControlFlowScope()
or
exists(ControlFlowNode y |
successors(unresolveElement(x), unresolveElement(y))
or
successors(unresolveElement(y), unresolveElement(x))
|
isInFunction(y, f)
)
}
Element getScopeElement(ControlFlowNode x) {
isInFunction(x, result)
or
not isInFunction(x, _) and
result = x.getFile()
}
string getScopeName(ControlFlowNode x) {
exists(Function scope | scope = getScopeElement(x) |
differentScope(scope) and
result = scope.getFile().getBaseName().splitAt(".", 0) + "__" +
scope.getQualifiedName().replaceAll("::", "_")
)
or
exists(File scope | scope = getScopeElement(x) |
differentScope(scope) and
result = scope.getBaseName()
)
}
module QLCFG {
private predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) {
isEdge = false and x = y and label = x.toString()
}
private predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) {
exists(string truelabel, string falselabel |
isEdge = true and
qlCFGSuccessor(x, y) and
(if qlCFGTrueSuccessor(x, y) then truelabel = "T" else truelabel = "") and
(if qlCFGFalseSuccessor(x, y) then falselabel = "F" else falselabel = "") and
label = truelabel + falselabel
)
}
predicate qltestGraph(
Element scopeElement, string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y,
string label
) {
scopeElement = getScopeElement(x) and
scopeString = getScopeName(x) + "_ql" and
(
isNode(isEdge, x, y, label)
or
isSuccessor(isEdge, x, y, label)
)
}
}
module ExtractorCFG {
predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) {
isEdge = false and x = y and label = x.toString()
}
predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) {
exists(string truelabel, string falselabel |
isEdge = true and
successors(x, y) and
(if truecond_base(x, y) then truelabel = "T" else truelabel = "") and
(if falsecond_base(x, y) then falselabel = "F" else falselabel = "") and
label = truelabel + falselabel
)
}
predicate qltestGraph(
Element scopeElement, string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y,
string label
) {
scopeElement = getScopeElement(x) and
scopeString = getScopeName(x) + "_extractor" and
(
isNode(isEdge, x, y, label)
or
isSuccessor(isEdge, x, y, label)
)
}
}
module AllCFG {
predicate qltestGraph(
Element scopeElement, string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y,
string label
) {
QLCFG::qltestGraph(scopeElement, scopeString, isEdge, x, y, label)
or
ExtractorCFG::qltestGraph(scopeElement, scopeString, isEdge, x, y, label)
}
}

View File

@@ -0,0 +1,16 @@
int foo() try {
return 0;
}
catch(...) {
throw;
}
class Bar
{
Bar() try {
return;
}
catch(...) {
throw;
}
};

View File

@@ -0,0 +1,11 @@
template<class T>
void CallDestructor(T x, T *y) {
x.T::~T();
y->T::~T();
}
void Vacuous(int i) {
// An int doesn't have a destructor, but we get to call it anyway through a
// template.
CallDestructor(i, &i);
}

View File

@@ -0,0 +1,50 @@
typedef int jmp_buf;
void longjmp(jmp_buf env, int val);
[[noreturn]]
void noReturn0();
void noReturn1() {
noReturn0();
}
void noReturn2() {
do {
noReturn0();
}
while (0);
}
void noReturn3(int i) {
if (i > 0) {
noReturn1();
} else {
noReturn2();
}
}
void noReturn4() {
while (true) { }
}
void mayReturn(int i) {
if (i > 0) {
noReturn0();
}
}
#define mayReturnMacro(i) \
do { if (i > 0) { noReturn0(); } } while (0);
void noReturn5() {
mayReturnMacro(1);
}
void noReturn6() {
longjmp(0, 0);
}
void noReturn7() { // NOT REPORTED
throw 42;
}

View File

@@ -0,0 +1,4 @@
void f() {
int a, b, c, d;
int x[] = { a + b, c - d };
}

View File

@@ -0,0 +1,20 @@
struct Foo
{
Foo(int x, int y) : m_x(x), m_y(y) {}
~Foo() {m_x = m_y = 0;}
// NB: In Microsoft mode, size_t is predeclared.
static void* operator new(size_t sz, int z, int w) { return nullptr; }
static void operator delete(void* self) {}
int m_x;
int m_y;
};
int main()
{
auto foo = new(11, 22) Foo(33, 44);
delete foo;
}
// semmle-extractor-options: --microsoft

View File

@@ -0,0 +1,7 @@
struct Foo {
~Foo();
};
void f() {
delete[] (Foo*)nullptr;
}

View File

@@ -0,0 +1,11 @@
class C {
public:
int i;
};
void f() {
C c;
int a, b;
c.i = a + b;
;
}

View File

@@ -0,0 +1,20 @@
// semmle-extractor-options: --microsoft
void f();
void g();
void h()
{
f();
__assume(0);
g(); // unreachable
}
void i();
void j();
void k()
{
i();
h();
j(); // unreachable
}

View File

@@ -0,0 +1,29 @@
// semmle-extractor-options: -std=c++17
// Test cases that illustrate known bad ASTs that we have to work around in IR generation.
namespace Bad {
struct S {
int x;
template<int t>
int MemberFunction(int y) {
return t + x + y;
}
};
void CallBadMemberFunction() {
S s = {};
s.MemberFunction<6>(1); // Not marked as member function in AST.
}
struct Point {
int x;
int y;
Point() {
}
};
void CallCopyConstructor(const Point& a) {
Point b = a; // Copy constructor contains literal expressions with no values.
}
}

View File

@@ -0,0 +1,30 @@
int f(int i) {
int result = 0;
if (i != 0) {
result++;
while (i < 10) {
if (i++ == 5) {
result = 7;
break;
}
}
}
return result;
}
void f_for(void) {
int i;
int x = 0;
for(i = 0; i < 10; i++) {
if (i == 5) {
continue;
}
if (i == 7) {
break;
}
x++;
}
}

View File

@@ -0,0 +1,57 @@
// semmle-extractor-options: --clang
#define vector(elcount, type) __attribute__((vector_size((elcount)*sizeof(type)))) type
int builtin(int x, int y) {
int acc;
acc += __builtin_choose_expr(0, x+0, y);
__builtin_assume(x != 42);
acc += (int)__builtin_readcyclecounter();
vector(4, int) vec = { 0, 1, 2, 3 };
vector(4, int) vec2 = __builtin_shufflevector(vec, vec, 3+0, 2, 1, 0);
// Clang extension causes trap import errors, at least in 1.18
(void)__builtin_convertvector(vec, short __attribute__((__vector_size__(8))));
acc += __builtin_bitreverse32(x+0);
acc += __builtin_rotateleft32(x+1, y);
acc += __builtin_rotateright32(x+1, y);
if (y == 42) {
__builtin_unreachable();
}
if (__builtin_unpredictable(acc == 1)) {
return acc;
}
static int staticint = 0;
acc += __sync_swap(&staticint, x);
// There's a whole class of "Multiprecision Arithmetic Builtins" in Clang.
// This is just one example.
unsigned int carry_out;
acc += __builtin_addc(x+0, y, 1, &carry_out);
// There's a whole class of "Checked Arithmetic Builtins" in Clang. This is
// just one example.
__builtin_add_overflow(x+1, (long)y, &staticint);
acc += __builtin_canonicalize(0.7 + 0.7);
if (__builtin_memchr("Hello", 'e', 5)) {
acc++;
}
acc += __atomic_fetch_min(&staticint, x+y, 0);
static _Atomic int atomic_int;
acc += __c11_atomic_load(&atomic_int, 0);
return acc;
}

View File

@@ -0,0 +1,16 @@
// semmle-extractor-options: --clang
template<typename T>
T *addressof(T &x) noexcept {
return __builtin_addressof(x);
}
void call_addressof() {
int i;
int *p = addressof(i); // Doesn't work in 1.18 extractor
}
void builtin_cpp(int x, int y) {
void *ptr = __builtin_operator_new(x - y);
__builtin_operator_delete(*&ptr);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
// query-type: graph
import cpp
import semmle.code.cpp.controlflow.internal.CFG
class DestructorCallEnhanced extends DestructorCall {
override string toString() {
if exists(this.getQualifier().(VariableAccess).getTarget().getName())
then result = "call to " + this.getQualifier().(VariableAccess).getTarget().getName() + "." + this.getTarget().getName()
else result = super.toString()
}
}
string scope(ControlFlowNode x) {
if exists(x.getControlFlowScope().getQualifiedName())
then result = x.getControlFlowScope().getQualifiedName()
else result = "<no scope>"
}
predicate isNode(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) {
isEdge = false and x = y and label = x.toString()
}
predicate isSuccessor(boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label) {
exists(string truelabel, string falselabel |
isEdge = true
and qlCFGSuccessor(x, y)
and if qlCFGTrueSuccessor(x, y) then truelabel = "T" else truelabel = ""
and if qlCFGFalseSuccessor(x, y) then falselabel = "F" else falselabel = ""
and label = truelabel + falselabel)
}
from boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label
where isNode(isEdge, x, y, label) or isSuccessor(isEdge, x, y, label)
select scope(x), isEdge, x, y, label

View File

@@ -0,0 +1,5 @@
void ConditionDecl() {
int j = 0;
while(int k = j < 5) {
}
}

View File

@@ -0,0 +1,52 @@
struct BoxedInt {
BoxedInt(int x) {
m_ptr = new int(x);
}
~BoxedInt() {
delete m_ptr;
}
operator int() {
return *m_ptr;
}
int* m_ptr;
};
void if_decl_bind(int x) {
if(BoxedInt bi = x) {
++*bi.m_ptr;
}
else {
--*bi.m_ptr;
}
x = 1;
}
void switch_decl_bind(int x) {
switch(BoxedInt bi = x) {
case 0:
--*bi.m_ptr;
break;
case 1:
++*bi.m_ptr;
break;
default:
*bi.m_ptr /= 2;
/* no break -- this is important */
}
x = 1;
}
void while_decl_bind(int x) {
while(BoxedInt bi = x) {
--x;
}
++x;
}
void for_decl_bind(int x) {
for(BoxedInt init = -x, init2 = -x; BoxedInt bi = x; x *= 2) {
++x;
}
--x;
}

View File

@@ -0,0 +1,46 @@
class C1 {
public:
int val;
C1(int x) {
val = x;
}
bool operator==(const C1 &other) const {
return val == other.val;
}
};
class C2 {
public:
int val;
C2(int x) {
val = x;
}
~C2() {
;
}
bool operator==(const C2 &other) const {
return val == other.val;
}
};
void f1(void) {
if (C1(1) == C1(2)) {
;
}
if (C1(3) == C1(3)) {
;
}
}
void f2(void) {
if (C2(1) == C2(2)) {
;
}
if (C2(3) == C2(3)) {
;
}
}

View File

@@ -0,0 +1,10 @@
class C {
public:
int x;
};
void f() {
C *c;
int i;
i = c->x;
}

View File

@@ -0,0 +1,9 @@
class C {
public:
C(int x, int y);
};
void f() {
int i, j, k, l;
C c(i + j, k - l);
}

View File

@@ -0,0 +1,169 @@
// semmle-extractor-options: --c++11
namespace range_based_for_11 {
void array() {
int arr[4];
for (auto &el : arr) {
el = 0;
}
}
struct Iterator {
void *pos_data;
bool operator!=(const Iterator &other);
Iterator &operator++();
int &operator*();
~Iterator();
};
struct Iterable {
void *container_data;
Iterator begin();
Iterator end();
};
Iterable getContainer();
int getFirst() {
for (auto& el : getContainer()) {
return el;
}
return 0;
}
}
const int global_const = 5;
int global_int = 5;
void skip_init() {
static int x1 = 0;
static int x2 = 1;
static int x3 = 0 + 0;
static int *x4 = 0;
static int *x5 = &x3;
static int *x6 = (&x3 + 1) - 1;
static int x7[] = { 0, 1 };
static int *x8[] = { &x1, &global_int };
static struct { int x; } x9[] = { { 1 } };
static const char *s1 = "Hello";
static char s2[] = "World";
// TODO: non-POD types that may have constructors and such
}
void run_init() {
int nonstatic;
static int x1 = global_int;
static int *x2 = &nonstatic;
}
namespace lambda {
void simple(int x) {
auto closure = [=]() -> int { return x; };
}
class Val {
void *m_data;
public:
Val(int);
Val(const Val &);
};
template<typename Fn>
void apply(Val arg, Fn unaryFunction) {
unaryFunction(arg);
}
template <typename Fn>
void apply2(Fn binaryFunction, Val arg1, Val arg2) {
apply(arg2, [=](Val x) { binaryFunction(arg1, x); });
}
int doSomething(Val arg1, Val arg2);
void main() {
apply2(doSomething, Val(1), Val(2));
}
}
namespace synthetic_dtor_calls {
struct C {
~C();
};
void thrw() {
C c1, c2;
throw 1;
}
void fallthrough() {
C c1, c2;
}
int ret() {
C c1, c2;
return 2 + 2;
}
void leavescope() {
{
C c1, c2;
}
}
void f(int x) {
while (x > 0) {
C c;
if (x == 1) {
0;
} else if (x == 2) {
1;
} else if (x == 4) {
goto end;
} else if (x == 5) {
goto end;
} else if (x == 3) {
break;
} else {
break;
}
}
end:
;
}
// This function is interesting because its extractor CFG has unreachable
// calls to `c2.~C()` and `c3.~C()`. It's the calls that would have come from
// leaving the block of `c2` by falling off the end, but no path does that.
int g(int x) {
do {
C c1;
if (x > 0) {
if (x < 10) {
C c2;
if (x == 1) {
return 0;
} else {
return 1;
}
} else {
C c3;
if (x == 11) {
break;
} else {
break;
}
}
}
} while (0);
}
void localClass(int x) {
struct L {
~L() { }
} l;
if (x) {
throw 1;
}
}
}

View File

@@ -0,0 +1,21 @@
// semmle-extractor-options: --c++17
namespace std { typedef unsigned long size_t; }
void* operator new ( std::size_t count, void* ptr );
namespace placement_new {
struct HasTwoArgCtor {
int x;
HasTwoArgCtor(int a, int b);
};
template<typename T, typename... Args>
void make(T *ptr, Args&&... args) {
::new((void *)ptr) HasTwoArgCtor(args...);
}
void make_HasTwoArgCtor(HasTwoArgCtor *p) {
make(p, 1, 2);
}
}

View File

@@ -0,0 +1,6 @@
class C { };
void f() {
new C;
return;
}

View File

@@ -0,0 +1,6 @@
class C { };
void f() {
C* c = new C();
delete c;
}

View File

@@ -0,0 +1,9 @@
class C {
public:
~C();
};
void f() {
C* c = new C();
delete c;
}

View File

@@ -0,0 +1,38 @@
struct HasDtor {
int x;
~HasDtor();
};
int destructors_main(HasDtor p) {
HasDtor fscope;
{
HasDtor inner;
if (p.x == 1) {
return 1;
}
;
}
if (p.x == 2) {
return 2;
}
;
return 3;
;
}
void destructor_after_handler() {
HasDtor x;
try {
} catch (const HasDtor&) {
return;
}
}
void destructor_catch() {
try {
} catch (HasDtor d) {
HasDtor d2 = { 0 };
}
}

View File

@@ -0,0 +1,38 @@
void always_false() {
do {
l1:;
} while(0);
l2:;
}
void always_true_1() {
do {
l1:;
break;
} while(1);
l2:;
}
void always_true_2() {
do {
l1:;
break;
l2:;
} while(1);
l3:;
}
void always_true_3() {
do {
l1:;
} while(1);
l2:;
}
void normal() {
int i = 0;
do {
++i;
} while(i < 10);
l:;
}

View File

@@ -0,0 +1,310 @@
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14359 | 14359 | ms_empty_finally_at_end |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14364 | 14364 | declaration |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14368 | 14368 | 3 |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14369 | 14369 | throw ... |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14371 | 14371 | ExprStmt |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14373 | 14373 | { ... } |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14375 | 14375 | { ... } |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14377 | 14377 | __try { ... } __finally { ... } |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14379 | 14379 | return ... |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14381 | 14381 | { ... } |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14383 | 14383 | c201 |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14385 | 14385 | call to c201.~C |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14386 | 14386 | c201 |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14387 | 14387 | call to c201.~C |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14389 | 14389 | call to C |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14394 | 14394 | 201 |
| ms_try_mix__ms_empty_finally_at_end_extractor | false | 14395 | 14395 | initializer for c201 |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14364 | 14395 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14368 | 14369 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14369 | 14386 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14371 | 14368 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14373 | 14371 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14375 | 14379 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14375 | 14386 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14377 | 14373 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14379 | 14383 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14381 | 14364 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14383 | 14385 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14385 | 14359 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14386 | 14387 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14387 | 14359 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14387 | 14375 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14389 | 14377 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14394 | 14389 | |
| ms_try_mix__ms_empty_finally_at_end_extractor | true | 14395 | 14394 | |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14359 | 14359 | ms_empty_finally_at_end |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14364 | 14364 | declaration |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14368 | 14368 | 3 |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14369 | 14369 | throw ... |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14371 | 14371 | ExprStmt |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14373 | 14373 | { ... } |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14375 | 14375 | { ... } |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14377 | 14377 | __try { ... } __finally { ... } |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14379 | 14379 | return ... |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14381 | 14381 | { ... } |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14383 | 14383 | c201 |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14385 | 14385 | call to c201.~C |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14386 | 14386 | c201 |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14387 | 14387 | call to c201.~C |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14389 | 14389 | call to C |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14394 | 14394 | 201 |
| ms_try_mix__ms_empty_finally_at_end_ql | false | 14395 | 14395 | initializer for c201 |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14364 | 14395 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14368 | 14369 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14369 | 14386 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14371 | 14368 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14373 | 14371 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14375 | 14359 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14375 | 14379 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14377 | 14373 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14379 | 14383 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14381 | 14364 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14383 | 14385 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14385 | 14359 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14386 | 14387 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14387 | 14375 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14389 | 14377 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14394 | 14389 | |
| ms_try_mix__ms_empty_finally_at_end_ql | true | 14395 | 14394 | |
| ms_try_mix__ms_finally_mix_extractor | false | 14398 | 14398 | ms_finally_mix |
| ms_try_mix__ms_finally_mix_extractor | false | 14406 | 14406 | declaration |
| ms_try_mix__ms_finally_mix_extractor | false | 14409 | 14409 | call to C |
| ms_try_mix__ms_finally_mix_extractor | false | 14413 | 14413 | 106 |
| ms_try_mix__ms_finally_mix_extractor | false | 14414 | 14414 | initializer for c106 |
| ms_try_mix__ms_finally_mix_extractor | false | 14418 | 14418 | call to C |
| ms_try_mix__ms_finally_mix_extractor | false | 14422 | 14422 | 107 |
| ms_try_mix__ms_finally_mix_extractor | false | 14423 | 14423 | initializer for c107 |
| ms_try_mix__ms_finally_mix_extractor | false | 14426 | 14426 | declaration |
| ms_try_mix__ms_finally_mix_extractor | false | 14428 | 14428 | b2 |
| ms_try_mix__ms_finally_mix_extractor | false | 14430 | 14430 | (bool)... |
| ms_try_mix__ms_finally_mix_extractor | false | 14433 | 14433 | 2 |
| ms_try_mix__ms_finally_mix_extractor | false | 14434 | 14434 | throw ... |
| ms_try_mix__ms_finally_mix_extractor | false | 14436 | 14436 | ExprStmt |
| ms_try_mix__ms_finally_mix_extractor | false | 14438 | 14438 | { ... } |
| ms_try_mix__ms_finally_mix_extractor | false | 14440 | 14440 | if (...) ... |
| ms_try_mix__ms_finally_mix_extractor | false | 14442 | 14442 | declaration |
| ms_try_mix__ms_finally_mix_extractor | false | 14444 | 14444 | { ... } |
| ms_try_mix__ms_finally_mix_extractor | false | 14447 | 14447 | call to C |
| ms_try_mix__ms_finally_mix_extractor | false | 14451 | 14451 | 108 |
| ms_try_mix__ms_finally_mix_extractor | false | 14452 | 14452 | initializer for c108 |
| ms_try_mix__ms_finally_mix_extractor | false | 14455 | 14455 | declaration |
| ms_try_mix__ms_finally_mix_extractor | false | 14457 | 14457 | { ... } |
| ms_try_mix__ms_finally_mix_extractor | false | 14459 | 14459 | __try { ... } __finally { ... } |
| ms_try_mix__ms_finally_mix_extractor | false | 14461 | 14461 | declaration |
| ms_try_mix__ms_finally_mix_extractor | false | 14463 | 14463 | return ... |
| ms_try_mix__ms_finally_mix_extractor | false | 14465 | 14465 | { ... } |
| ms_try_mix__ms_finally_mix_extractor | false | 14467 | 14467 | c101 |
| ms_try_mix__ms_finally_mix_extractor | false | 14469 | 14469 | call to c101.~C |
| ms_try_mix__ms_finally_mix_extractor | false | 14470 | 14470 | c109 |
| ms_try_mix__ms_finally_mix_extractor | false | 14471 | 14471 | call to c109.~C |
| ms_try_mix__ms_finally_mix_extractor | false | 14472 | 14472 | c101 |
| ms_try_mix__ms_finally_mix_extractor | false | 14473 | 14473 | call to c101.~C |
| ms_try_mix__ms_finally_mix_extractor | false | 14474 | 14474 | c108 |
| ms_try_mix__ms_finally_mix_extractor | false | 14476 | 14476 | call to c108.~C |
| ms_try_mix__ms_finally_mix_extractor | false | 14477 | 14477 | c106 |
| ms_try_mix__ms_finally_mix_extractor | false | 14479 | 14479 | call to c106.~C |
| ms_try_mix__ms_finally_mix_extractor | false | 14480 | 14480 | c107 |
| ms_try_mix__ms_finally_mix_extractor | false | 14481 | 14481 | call to c107.~C |
| ms_try_mix__ms_finally_mix_extractor | false | 14482 | 14482 | c106 |
| ms_try_mix__ms_finally_mix_extractor | false | 14483 | 14483 | call to c106.~C |
| ms_try_mix__ms_finally_mix_extractor | false | 14485 | 14485 | call to C |
| ms_try_mix__ms_finally_mix_extractor | false | 14489 | 14489 | 101 |
| ms_try_mix__ms_finally_mix_extractor | false | 14490 | 14490 | initializer for c101 |
| ms_try_mix__ms_finally_mix_extractor | false | 14494 | 14494 | call to C |
| ms_try_mix__ms_finally_mix_extractor | false | 14498 | 14498 | 109 |
| ms_try_mix__ms_finally_mix_extractor | false | 14499 | 14499 | initializer for c109 |
| ms_try_mix__ms_finally_mix_extractor | true | 14406 | 14490 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14409 | 14440 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14413 | 14409 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14414 | 14413 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14418 | 14480 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14422 | 14418 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14423 | 14422 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14426 | 14414 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14428 | 14438 | T |
| ms_try_mix__ms_finally_mix_extractor | true | 14428 | 14442 | F |
| ms_try_mix__ms_finally_mix_extractor | true | 14433 | 14434 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14434 | 14482 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14436 | 14433 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14438 | 14436 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14440 | 14428 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14442 | 14423 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14444 | 14426 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14447 | 14474 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14451 | 14447 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14452 | 14451 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14455 | 14452 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14457 | 14455 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14459 | 14444 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14461 | 14499 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14463 | 14470 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14465 | 14406 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14467 | 14469 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14469 | 14398 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14470 | 14471 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14471 | 14467 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14472 | 14473 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14473 | 14398 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14474 | 14476 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14476 | 14461 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14476 | 14472 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14477 | 14479 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14479 | 14457 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14480 | 14481 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14481 | 14477 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14482 | 14483 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14483 | 14457 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14485 | 14459 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14489 | 14485 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14490 | 14489 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14494 | 14463 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14498 | 14494 | |
| ms_try_mix__ms_finally_mix_extractor | true | 14499 | 14498 | |
| ms_try_mix__ms_finally_mix_ql | false | 14398 | 14398 | ms_finally_mix |
| ms_try_mix__ms_finally_mix_ql | false | 14406 | 14406 | declaration |
| ms_try_mix__ms_finally_mix_ql | false | 14409 | 14409 | call to C |
| ms_try_mix__ms_finally_mix_ql | false | 14413 | 14413 | 106 |
| ms_try_mix__ms_finally_mix_ql | false | 14414 | 14414 | initializer for c106 |
| ms_try_mix__ms_finally_mix_ql | false | 14418 | 14418 | call to C |
| ms_try_mix__ms_finally_mix_ql | false | 14422 | 14422 | 107 |
| ms_try_mix__ms_finally_mix_ql | false | 14423 | 14423 | initializer for c107 |
| ms_try_mix__ms_finally_mix_ql | false | 14426 | 14426 | declaration |
| ms_try_mix__ms_finally_mix_ql | false | 14428 | 14428 | b2 |
| ms_try_mix__ms_finally_mix_ql | false | 14430 | 14430 | (bool)... |
| ms_try_mix__ms_finally_mix_ql | false | 14433 | 14433 | 2 |
| ms_try_mix__ms_finally_mix_ql | false | 14434 | 14434 | throw ... |
| ms_try_mix__ms_finally_mix_ql | false | 14436 | 14436 | ExprStmt |
| ms_try_mix__ms_finally_mix_ql | false | 14438 | 14438 | { ... } |
| ms_try_mix__ms_finally_mix_ql | false | 14440 | 14440 | if (...) ... |
| ms_try_mix__ms_finally_mix_ql | false | 14442 | 14442 | declaration |
| ms_try_mix__ms_finally_mix_ql | false | 14444 | 14444 | { ... } |
| ms_try_mix__ms_finally_mix_ql | false | 14447 | 14447 | call to C |
| ms_try_mix__ms_finally_mix_ql | false | 14451 | 14451 | 108 |
| ms_try_mix__ms_finally_mix_ql | false | 14452 | 14452 | initializer for c108 |
| ms_try_mix__ms_finally_mix_ql | false | 14455 | 14455 | declaration |
| ms_try_mix__ms_finally_mix_ql | false | 14457 | 14457 | { ... } |
| ms_try_mix__ms_finally_mix_ql | false | 14459 | 14459 | __try { ... } __finally { ... } |
| ms_try_mix__ms_finally_mix_ql | false | 14461 | 14461 | declaration |
| ms_try_mix__ms_finally_mix_ql | false | 14463 | 14463 | return ... |
| ms_try_mix__ms_finally_mix_ql | false | 14465 | 14465 | { ... } |
| ms_try_mix__ms_finally_mix_ql | false | 14467 | 14467 | c101 |
| ms_try_mix__ms_finally_mix_ql | false | 14469 | 14469 | call to c101.~C |
| ms_try_mix__ms_finally_mix_ql | false | 14470 | 14470 | c109 |
| ms_try_mix__ms_finally_mix_ql | false | 14471 | 14471 | call to c109.~C |
| ms_try_mix__ms_finally_mix_ql | false | 14472 | 14472 | c101 |
| ms_try_mix__ms_finally_mix_ql | false | 14473 | 14473 | call to c101.~C |
| ms_try_mix__ms_finally_mix_ql | false | 14474 | 14474 | c108 |
| ms_try_mix__ms_finally_mix_ql | false | 14476 | 14476 | call to c108.~C |
| ms_try_mix__ms_finally_mix_ql | false | 14477 | 14477 | c106 |
| ms_try_mix__ms_finally_mix_ql | false | 14479 | 14479 | call to c106.~C |
| ms_try_mix__ms_finally_mix_ql | false | 14480 | 14480 | c107 |
| ms_try_mix__ms_finally_mix_ql | false | 14481 | 14481 | call to c107.~C |
| ms_try_mix__ms_finally_mix_ql | false | 14482 | 14482 | c106 |
| ms_try_mix__ms_finally_mix_ql | false | 14483 | 14483 | call to c106.~C |
| ms_try_mix__ms_finally_mix_ql | false | 14485 | 14485 | call to C |
| ms_try_mix__ms_finally_mix_ql | false | 14489 | 14489 | 101 |
| ms_try_mix__ms_finally_mix_ql | false | 14490 | 14490 | initializer for c101 |
| ms_try_mix__ms_finally_mix_ql | false | 14494 | 14494 | call to C |
| ms_try_mix__ms_finally_mix_ql | false | 14498 | 14498 | 109 |
| ms_try_mix__ms_finally_mix_ql | false | 14499 | 14499 | initializer for c109 |
| ms_try_mix__ms_finally_mix_ql | true | 14406 | 14490 | |
| ms_try_mix__ms_finally_mix_ql | true | 14409 | 14440 | |
| ms_try_mix__ms_finally_mix_ql | true | 14413 | 14409 | |
| ms_try_mix__ms_finally_mix_ql | true | 14414 | 14413 | |
| ms_try_mix__ms_finally_mix_ql | true | 14418 | 14480 | |
| ms_try_mix__ms_finally_mix_ql | true | 14422 | 14418 | |
| ms_try_mix__ms_finally_mix_ql | true | 14423 | 14422 | |
| ms_try_mix__ms_finally_mix_ql | true | 14426 | 14414 | |
| ms_try_mix__ms_finally_mix_ql | true | 14428 | 14438 | T |
| ms_try_mix__ms_finally_mix_ql | true | 14428 | 14442 | F |
| ms_try_mix__ms_finally_mix_ql | true | 14433 | 14434 | |
| ms_try_mix__ms_finally_mix_ql | true | 14434 | 14482 | |
| ms_try_mix__ms_finally_mix_ql | true | 14436 | 14433 | |
| ms_try_mix__ms_finally_mix_ql | true | 14438 | 14436 | |
| ms_try_mix__ms_finally_mix_ql | true | 14440 | 14428 | |
| ms_try_mix__ms_finally_mix_ql | true | 14442 | 14423 | |
| ms_try_mix__ms_finally_mix_ql | true | 14444 | 14426 | |
| ms_try_mix__ms_finally_mix_ql | true | 14447 | 14474 | |
| ms_try_mix__ms_finally_mix_ql | true | 14451 | 14447 | |
| ms_try_mix__ms_finally_mix_ql | true | 14452 | 14451 | |
| ms_try_mix__ms_finally_mix_ql | true | 14455 | 14452 | |
| ms_try_mix__ms_finally_mix_ql | true | 14457 | 14455 | |
| ms_try_mix__ms_finally_mix_ql | true | 14459 | 14444 | |
| ms_try_mix__ms_finally_mix_ql | true | 14461 | 14499 | |
| ms_try_mix__ms_finally_mix_ql | true | 14463 | 14470 | |
| ms_try_mix__ms_finally_mix_ql | true | 14465 | 14406 | |
| ms_try_mix__ms_finally_mix_ql | true | 14467 | 14469 | |
| ms_try_mix__ms_finally_mix_ql | true | 14469 | 14398 | |
| ms_try_mix__ms_finally_mix_ql | true | 14470 | 14471 | |
| ms_try_mix__ms_finally_mix_ql | true | 14471 | 14467 | |
| ms_try_mix__ms_finally_mix_ql | true | 14472 | 14473 | |
| ms_try_mix__ms_finally_mix_ql | true | 14473 | 14398 | |
| ms_try_mix__ms_finally_mix_ql | true | 14474 | 14476 | |
| ms_try_mix__ms_finally_mix_ql | true | 14476 | 14398 | |
| ms_try_mix__ms_finally_mix_ql | true | 14476 | 14461 | |
| ms_try_mix__ms_finally_mix_ql | true | 14477 | 14479 | |
| ms_try_mix__ms_finally_mix_ql | true | 14479 | 14457 | |
| ms_try_mix__ms_finally_mix_ql | true | 14480 | 14481 | |
| ms_try_mix__ms_finally_mix_ql | true | 14481 | 14477 | |
| ms_try_mix__ms_finally_mix_ql | true | 14482 | 14483 | |
| ms_try_mix__ms_finally_mix_ql | true | 14483 | 14457 | |
| ms_try_mix__ms_finally_mix_ql | true | 14485 | 14459 | |
| ms_try_mix__ms_finally_mix_ql | true | 14489 | 14485 | |
| ms_try_mix__ms_finally_mix_ql | true | 14490 | 14489 | |
| ms_try_mix__ms_finally_mix_ql | true | 14494 | 14463 | |
| ms_try_mix__ms_finally_mix_ql | true | 14498 | 14494 | |
| ms_try_mix__ms_finally_mix_ql | true | 14499 | 14498 | |
| staticlocals__staticlocals_f2_extractor | false | 21781 | 21781 | f2 |
| staticlocals__staticlocals_f2_extractor | false | 21786 | 21786 | declaration |
| staticlocals__staticlocals_f2_extractor | false | 21788 | 21788 | declaration |
| staticlocals__staticlocals_f2_extractor | false | 21790 | 21790 | declaration |
| staticlocals__staticlocals_f2_extractor | false | 21792 | 21792 | declaration |
| staticlocals__staticlocals_f2_extractor | false | 21794 | 21794 | return ... |
| staticlocals__staticlocals_f2_extractor | false | 21796 | 21796 | { ... } |
| staticlocals__staticlocals_f2_extractor | false | 21798 | 21798 | call to C |
| staticlocals__staticlocals_f2_extractor | false | 21800 | 21800 | initializer for c |
| staticlocals__staticlocals_f2_extractor | false | 21802 | 21802 | call to addOne |
| staticlocals__staticlocals_f2_extractor | false | 21806 | 21806 | 2 |
| staticlocals__staticlocals_f2_extractor | false | 21809 | 21809 | initializer for j |
| staticlocals__staticlocals_f2_extractor | false | 21810 | 21810 | call to addOne |
| staticlocals__staticlocals_f2_extractor | false | 21815 | 21815 | 2 |
| staticlocals__staticlocals_f2_extractor | false | 21816 | 21816 | initializer for two |
| staticlocals__staticlocals_f2_extractor | false | 21819 | 21819 | two |
| staticlocals__staticlocals_f2_extractor | false | 21824 | 21824 | initializer for i |
| staticlocals__staticlocals_f2_extractor | true | 21786 | 21816 | |
| staticlocals__staticlocals_f2_extractor | true | 21788 | 21790 | |
| staticlocals__staticlocals_f2_extractor | true | 21790 | 21792 | |
| staticlocals__staticlocals_f2_extractor | true | 21792 | 21794 | |
| staticlocals__staticlocals_f2_extractor | true | 21794 | 21781 | |
| staticlocals__staticlocals_f2_extractor | true | 21796 | 21786 | |
| staticlocals__staticlocals_f2_extractor | true | 21815 | 21788 | |
| staticlocals__staticlocals_f2_extractor | true | 21816 | 21815 | |
| staticlocals__staticlocals_f2_ql | false | 21781 | 21781 | f2 |
| staticlocals__staticlocals_f2_ql | false | 21786 | 21786 | declaration |
| staticlocals__staticlocals_f2_ql | false | 21788 | 21788 | declaration |
| staticlocals__staticlocals_f2_ql | false | 21790 | 21790 | declaration |
| staticlocals__staticlocals_f2_ql | false | 21792 | 21792 | declaration |
| staticlocals__staticlocals_f2_ql | false | 21794 | 21794 | return ... |
| staticlocals__staticlocals_f2_ql | false | 21796 | 21796 | { ... } |
| staticlocals__staticlocals_f2_ql | false | 21798 | 21798 | call to C |
| staticlocals__staticlocals_f2_ql | false | 21800 | 21800 | initializer for c |
| staticlocals__staticlocals_f2_ql | false | 21802 | 21802 | call to addOne |
| staticlocals__staticlocals_f2_ql | false | 21806 | 21806 | 2 |
| staticlocals__staticlocals_f2_ql | false | 21809 | 21809 | initializer for j |
| staticlocals__staticlocals_f2_ql | false | 21810 | 21810 | call to addOne |
| staticlocals__staticlocals_f2_ql | false | 21815 | 21815 | 2 |
| staticlocals__staticlocals_f2_ql | false | 21816 | 21816 | initializer for two |
| staticlocals__staticlocals_f2_ql | false | 21819 | 21819 | two |
| staticlocals__staticlocals_f2_ql | false | 21824 | 21824 | initializer for i |
| staticlocals__staticlocals_f2_ql | true | 21786 | 21816 | |
| staticlocals__staticlocals_f2_ql | true | 21788 | 21790 | |
| staticlocals__staticlocals_f2_ql | true | 21790 | 21792 | |
| staticlocals__staticlocals_f2_ql | true | 21792 | 21794 | |
| staticlocals__staticlocals_f2_ql | true | 21792 | 21800 | |
| staticlocals__staticlocals_f2_ql | true | 21794 | 21781 | |
| staticlocals__staticlocals_f2_ql | true | 21796 | 21786 | |
| staticlocals__staticlocals_f2_ql | true | 21798 | 21794 | |
| staticlocals__staticlocals_f2_ql | true | 21800 | 21798 | |
| staticlocals__staticlocals_f2_ql | true | 21815 | 21788 | |
| staticlocals__staticlocals_f2_ql | true | 21816 | 21815 | |

View File

@@ -0,0 +1,11 @@
// query-type: graph
import Compare
from
Element scopeElement,
string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y, string label
where
AllCFG::qltestGraph(scopeElement, scopeString, isEdge, x, y, label) and
differentScope(scopeElement)
select
scopeString, isEdge, x, y, label

View File

@@ -0,0 +1,16 @@
void f(int i) {
int n = (i + 7) / 8;
switch (i % 8) {
case 0: do { 10;
case 7: 17;
case 6: 16;
case 5: 15;
case 4: 14;
case 3: 13;
case 2: 12;
case 1: 11;
} while (--n > 0);
}
}

View File

@@ -0,0 +1,23 @@
void duff2_8(int i) {
int n = (i + 7) / 8;
switch (i % 8) do {
case 0: 10;
case 7: 17;
case 6: 16;
case 5: 15;
case 4: 14;
case 3: 13;
case 2: 12;
case 1: 11;
} while (--n > 0);
}
void duff2_2(int i) {
int n = (i + 1) / 2;
switch (i % 2) do {
case 0: 10;
case 1: 11;
} while (--n > 0);
}

View File

@@ -0,0 +1,4 @@
void f() {
if (1)
;
}

View File

@@ -0,0 +1,20 @@
namespace eehandler {
void f() {
try {
try {
throw 1;
} catch (int i) {
} catch (...) {
}
} catch (int j) {
}
}
void g(bool condition) {
try {
if (condition) throw 1;
} catch (...) {
}
}
}

View File

@@ -0,0 +1,5 @@
void f() {
{
}
;
}

View File

@@ -0,0 +1,7 @@
enum {
a = 1 + 1
};
int f() {
return a;
}

View File

@@ -0,0 +1,25 @@
namespace ehandler {
class C { };
class D { };
void g() {
throw 1;
}
void f() {
try {
try {
g();
throw 2;
l:
} catch (int) {
4;
}
} catch (C) {
5;
} catch (D) {
6;
}
}
}

View File

@@ -0,0 +1,4 @@
void f() {
1;
;
}

View File

@@ -0,0 +1,10 @@
class C {
public:
int x;
};
void f() {
C *c;
int i;
i = c->x;
}

View File

@@ -0,0 +1,21 @@
void f1() {
for (int i = 0; i < 10; i++) {
l1:
}
;
}
void f2() {
for (int i = 0; false; i++) { // true edge pruned
}
}
void f3() {
for (int i = 0; true; i++) { // false edge pruned
}
}
void f4() {
for (int i = 0; i < 0; i++) { // true edge pruned
}
}

View File

@@ -0,0 +1,5 @@
void v() {
goto label;
;
label:
}

View File

@@ -0,0 +1,45 @@
void always_false_1() {
if(0) {
l1:;
}
else {
l2:;
}
l3:;
}
void always_false_2() {
if(0)
l1:;
else
l2:;
l3:;
}
void always_true_1() {
if(1) {
l1:;
}
else {
l2:;
}
l3:;
}
void always_true_2() {
if(1)
l1:;
else
l2:;
l3:;
}
void normal(int x, int y) {
if(x == y) {
l1:;
}
else {
l2:;
}
l3:;
}

View File

@@ -0,0 +1,32 @@
void always_false_1() {
if(0) {
l1:;
}
l2:;
}
void always_false_2() {
if(0)
l1:;
l2:;
}
void always_true_1() {
if(1) {
l1:;
}
l2:;
}
void always_true_2() {
if(1)
l1:;
l2:;
}
void normal(int x, int y) {
if(x == y) {
l1:;
}
l2:;
}

View File

@@ -0,0 +1,4 @@
void f() {
int a, b;
int i = a + b;
}

View File

@@ -0,0 +1,984 @@
void Constants() {
char c_i = 1;
char c_c = 'A';
signed char sc_i = -1;
signed char sc_c = 'A';
unsigned char uc_i = 5;
unsigned char uc_c = 'A';
short s = 5;
unsigned short us = 5;
int i = 5;
unsigned int ui = 5;
long l = 5;
unsigned long ul = 5;
long long ll_i = 5;
long long ll_ll = 5LL;
unsigned long long ull_i = 5;
unsigned long long ull_ull = 5ULL;
bool b_t = true;
bool b_f = false;
wchar_t wc_i = 5;
wchar_t wc_c = L'A';
char16_t c16 = u'A';
char32_t c32 = U'A';
float f_i = 1;
float f_f = 1.0f;
float f_d = 1.0;
double d_i = 1;
double d_f = 1.0f;
double d_d = 1.0;
}
void Foo() {
int x = 5 + 12;
short y = 7;
y = x + y;
x = x * y;
}
void IntegerOps(int x, int y) {
int z;
z = x + y;
z = x - y;
z = x * y;
z = x / y;
z = x % y;
z = x & y;
z = x | y;
z = x ^ y;
z = x << y;
z = x >> y;
z = x;
z += x;
z -= x;
z *= x;
z /= x;
z %= x;
z &= x;
z |= x;
z ^= x;
z <<= x;
z >>= x;
z = +x;
z = -x;
z = ~x;
z = !x;
}
void IntegerCompare(int x, int y) {
bool b;
b = x == y;
b = x != y;
b = x < y;
b = x > y;
b = x <= y;
b = x >= y;
}
void IntegerCrement(int x) {
int y;
y = ++x;
y = --x;
y = x++;
y = x--;
}
void IntegerCrement_LValue(int x) {
int* p;
p = &(++x);
p = &(--x);
}
void FloatOps(double x, double y) {
double z;
z = x + y;
z = x - y;
z = x * y;
z = x / y;
z = x;
z += x;
z -= x;
z *= x;
z /= x;
z = +x;
z = -x;
}
void FloatCompare(double x, double y) {
bool b;
b = x == y;
b = x != y;
b = x < y;
b = x > y;
b = x <= y;
b = x >= y;
}
void FloatCrement(float x) {
float y;
y = ++x;
y = --x;
y = x++;
y = x--;
}
void PointerOps(int* p, int i) {
int* q;
bool b;
q = p + i;
q = i + p;
q = p - i;
i = p - q;
q = p;
q += i;
q -= i;
b = p;
b = !p;
}
void ArrayAccess(int* p, int i) {
int x;
x = p[i];
x = i[p];
p[i] = x;
i[p] = x;
int a[10];
x = a[i];
x = i[a];
a[i] = x;
i[a] = x;
}
void StringLiteral(int i) {
char c = "Foo"[i];
wchar_t* pwc = L"Bar";
wchar_t wc = pwc[i];
}
void PointerCompare(int* p, int* q) {
bool b;
b = p == q;
b = p != q;
b = p < q;
b = p > q;
b = p <= q;
b = p >= q;
}
void PointerCrement(int* p) {
int* q;
q = ++p;
q = --p;
q = p++;
q = p--;
}
void CompoundAssignment() {
// No conversion necessary
int x = 5;
x += 7;
// Left side is converted to 'int'
short y = 5;
y += x;
// Technically the left side is promoted to int, but we don't model that
y <<= 1;
// Left side is converted to 'float'
long z = 7;
z += 2.0f;
}
void UninitializedVariables() {
int x;
int y = x;
}
int Parameters(int x, int y) {
return x % y;
}
void IfStatements(bool b, int x, int y) {
if (b) {
}
if (b) {
x = y;
}
if (x < 7)
x = 2;
else
x = 7;
}
void WhileStatements(int n) {
while (n > 0) {
n -= 1;
}
}
void DoStatements(int n) {
do {
n -= 1;
} while (n > 0);
}
void For_Empty() {
int j;
for (;;) {
;
}
}
void For_Init() {
for (int i = 0;;) {
;
}
}
void For_Condition() {
int i = 0;
for (; i < 10;) {
;
}
}
void For_Update() {
int i = 0;
for (;; i += 1) {
;
}
}
void For_InitCondition() {
for (int i = 0; i < 10;) {
;
}
}
void For_InitUpdate() {
for (int i = 0;; i += 1) {
;
}
}
void For_ConditionUpdate() {
int i = 0;
for (; i < 10; i += 1) {
;
}
}
void For_InitConditionUpdate() {
for (int i = 0; i < 10; i += 1) {
;
}
}
void For_Break() {
for (int i = 0; i < 10; i += 1) {
if (i == 5) {
break;
}
}
}
void For_Continue_Update() {
for (int i = 0; i < 10; i += 1) {
if (i == 5) {
continue;
}
}
}
void For_Continue_NoUpdate() {
for (int i = 0; i < 10;) {
if (i == 5) {
continue;
}
}
}
int Dereference(int* p) {
*p = 1;
return *p;
}
int g;
int* AddressOf() {
return &g;
}
void Break(int n) {
while (n > 0) {
if (n == 1)
break;
n -= 1;
}
}
void Continue(int n) {
do {
if (n == 1) {
continue;
}
n -= 1;
} while (n > 0);
}
void VoidFunc();
int Add(int x, int y);
void Call() {
VoidFunc();
}
int CallAdd(int x, int y) {
return Add(x, y);
}
int Comma(int x, int y) {
return VoidFunc(), CallAdd(x, y);
}
void Switch(int x) {
int y;
switch (x) {
y = 1234;
case -1:
y = -1;
break;
case 1:
case 2:
y = 1;
break;
case 3:
y = 3;
case 4:
y = 4;
break;
default:
y = 0;
break;
y = 5678;
}
}
struct Point {
int x;
int y;
};
struct Rect {
Point topLeft;
Point bottomRight;
};
Point ReturnStruct(Point pt) {
return pt;
}
void FieldAccess() {
Point pt;
pt.x = 5;
pt.y = pt.x;
int* p = &pt.y;
}
void LogicalOr(bool a, bool b) {
int x;
if (a || b) {
x = 7;
}
if (a || b) {
x = 1;
}
else {
x = 5;
}
}
void LogicalAnd(bool a, bool b) {
int x;
if (a && b) {
x = 7;
}
if (a && b) {
x = 1;
}
else {
x = 5;
}
}
void LogicalNot(bool a, bool b) {
int x;
if (!a) {
x = 1;
}
if (!(a && b)) {
x = 2;
}
else {
x = 3;
}
}
void ConditionValues(bool a, bool b) {
bool x;
x = a && b;
x = a || b;
x = !(a || b);
}
void Conditional(bool a, int x, int y) {
int z = a ? x : y;
}
void Conditional_LValue(bool a) {
int x;
int y;
(a ? x : y) = 5;
}
void Conditional_Void(bool a) {
a ? VoidFunc() : VoidFunc();
}
void Nullptr() {
int* p = nullptr;
int* q = 0;
p = nullptr;
q = 0;
}
void InitList(int x, float f) {
Point pt1 = { x, f };
Point pt2 = { x };
Point pt3 = {};
int x1 = { 1 };
int x2 = {};
}
void NestedInitList(int x, float f) {
Rect r1 = {};
Rect r2 = { { x, f } };
Rect r3 = { { x, f }, { x, f } };
Rect r4 = { { x }, { x } };
}
void ArrayInit(int x, float f) {
int a1[3] = {};
int a2[3] = { x, f, 0 };
int a3[3] = { x };
}
union U {
double d;
int i;
};
void UnionInit(int x, float f) {
U u1 = { f };
// U u2 = {}; Waiting for fix
}
void EarlyReturn(int x, int y) {
if (x < y) {
return;
}
y = x;
}
int EarlyReturnValue(int x, int y) {
if (x < y) {
return x;
}
return x + y;
}
int CallViaFuncPtr(int (*pfn)(int)) {
return pfn(5);
}
typedef enum {
E_0,
E_1
} E;
int EnumSwitch(E e) {
switch (e) {
case E_0:
return 0;
case E_1:
return 1;
default:
return -1;
}
}
void InitArray() {
char a_pad[32] = "";
char a_nopad[4] = "foo";
char a_infer[] = "blah";
char b[2];
char c[2] = {};
char d[2] = { 0 };
char e[2] = { 0, 1 };
char f[3] = { 0 };
}
void VarArgFunction(const char* s, ...);
void VarArgs() {
VarArgFunction("%d %s", 1, "string");
}
int FuncPtrTarget(int);
void SetFuncPtr() {
int (*pfn)(int) = FuncPtrTarget;
pfn = &FuncPtrTarget;
pfn = *FuncPtrTarget;
pfn = ***&FuncPtrTarget;
}
struct String {
String();
String(const String&);
String(String&&);
String(const char*);
~String();
String& operator=(const String&);
String& operator=(String&&);
const char* c_str() const;
private:
const char* p;
};
String ReturnObject();
void DeclareObject() {
String s1;
String s2("hello");
String s3 = ReturnObject();
String s4 = String("test");
}
void CallMethods(String& r, String* p, String s) {
r.c_str();
p->c_str();
s.c_str();
}
class C {
public:
static int StaticMemberFunction(int x) {
return x;
}
int InstanceMemberFunction(int x) {
return x;
}
virtual int VirtualMemberFunction(int x) {
return x;
}
void FieldAccess() {
this->m_a = 0;
(*this).m_a = 1;
m_a = 2;
int x;
x = this->m_a;
x = (*this).m_a;
x = m_a;
}
void MethodCalls() {
this->InstanceMemberFunction(0);
(*this).InstanceMemberFunction(1);
InstanceMemberFunction(2);
}
C() :
m_a(1),
m_c(3),
m_e{},
m_f("test")
{
}
private:
int m_a;
String m_b;
char m_c;
float m_d;
void* m_e;
String m_f;
};
int DerefReference(int& r) {
return r;
}
int& TakeReference() {
return g;
}
String& ReturnReference();
void InitReference(int x) {
int& r = x;
int& r2 = r;
const String& r3 = ReturnReference();
}
void ArrayReferences() {
int a[10];
int (&ra)[10] = a;
int x = ra[5];
}
void FunctionReferences() {
int(&rfn)(int) = FuncPtrTarget;
int(*pfn)(int) = rfn;
rfn(5);
}
template<typename T>
T min(T x, T y) {
return (x < y) ? x : y;
}
int CallMin(int x, int y) {
return min(x, y);
}
template<typename T>
struct Outer {
template<typename U, typename V>
static T Func(U x, V y) {
return T();
}
};
double CallNestedTemplateFunc() {
return Outer<long>::Func<void*, char>(nullptr, 'o');
}
void TryCatch(bool b) {
try {
int x = 5;
if (b) {
throw "string literal";
}
else if (x < 2) {
x = b ? 7 : throw String("String object");
}
x = 7;
}
catch (const char* s) {
throw String(s);
}
catch (const String& e) {
}
catch (...) {
throw;
}
}
struct Base {
String base_s;
Base() {
}
~Base() {
}
};
struct Middle : Base {
String middle_s;
Middle() {
}
~Middle() {
}
};
struct Derived : Middle {
String derived_s;
Derived() {
}
~Derived() {
}
};
struct MiddleVB1 : virtual Base {
String middlevb1_s;
MiddleVB1() {
}
~MiddleVB1() {
}
};
struct MiddleVB2 : virtual Base {
String middlevb2_s;
MiddleVB2() {
}
~MiddleVB2() {
}
};
struct DerivedVB : MiddleVB1, MiddleVB2 {
String derivedvb_s;
DerivedVB() {
}
~DerivedVB() {
}
};
void HierarchyConversions() {
Base b;
Middle m;
Derived d;
Base* pb = &b;
Middle* pm = &m;
Derived* pd = &d;
b = m;
b = (Base)m;
b = static_cast<Base>(m);
pb = pm;
pb = (Base*)pm;
pb = static_cast<Base*>(pm);
pb = reinterpret_cast<Base*>(pm);
m = (Middle&)b;
m = static_cast<Middle&>(b);
pm = (Middle*)pb;
pm = static_cast<Middle*>(pb);
pm = reinterpret_cast<Middle*>(pb);
b = d;
b = (Base)d;
b = static_cast<Base>(d);
pb = pd;
pb = (Base*)pd;
pb = static_cast<Base*>(pd);
pb = reinterpret_cast<Base*>(pd);
d = (Derived&)b;
d = static_cast<Derived&>(b);
pd = (Derived*)pb;
pd = static_cast<Derived*>(pb);
pd = reinterpret_cast<Derived*>(pb);
MiddleVB1* pmv = nullptr;
DerivedVB* pdv = nullptr;
pb = pmv;
pb = pdv;
}
struct PolymorphicBase {
virtual ~PolymorphicBase();
};
struct PolymorphicDerived : PolymorphicBase {
};
void DynamicCast() {
PolymorphicBase b;
PolymorphicDerived d;
PolymorphicBase* pb = &b;
PolymorphicDerived* pd = &d;
// These two casts are represented as BaseClassCasts because they can be resolved at compile time.
pb = dynamic_cast<PolymorphicBase*>(pd);
PolymorphicBase& rb = dynamic_cast<PolymorphicBase&>(d);
pd = dynamic_cast<PolymorphicDerived*>(pb);
PolymorphicDerived& rd = dynamic_cast<PolymorphicDerived&>(b);
void* pv = dynamic_cast<void*>(pb);
const void* pcv = dynamic_cast<const void*>(pd);
}
String::String() :
String("") { // Delegating constructor call
}
void ArrayConversions() {
char a[5];
const char* p = a;
p = "test";
p = &a[0];
p = &"test"[0];
char (&ra)[5] = a;
const char (&rs)[5] = "test";
const char (*pa)[5] = &a;
pa = &"test";
}
void FuncPtrConversions(int(*pfn)(int), void* p) {
p = (void*)pfn;
pfn = (int(*)(int))p;
}
void VarArgUsage(int x, ...) {
__builtin_va_list args;
__builtin_va_start(args, x);
__builtin_va_list args2;
__builtin_va_start(args2, args);
double d = __builtin_va_arg(args, double);
float f = __builtin_va_arg(args, float);
__builtin_va_end(args);
__builtin_va_end(args2);
}
void CastToVoid(int x) {
(void)x;
}
void ConstantConditions(int x) {
bool a = true && true;
int b = (true) ? x : x;
}
typedef unsigned long size_t;
namespace std {
enum class align_val_t : size_t {};
}
void* operator new(size_t, float);
void* operator new[](size_t, float);
void* operator new(size_t, std::align_val_t, float);
void* operator new[](size_t, std::align_val_t, float);
void operator delete(void*, float);
void operator delete[](void*, float);
void operator delete(void*, std::align_val_t, float);
void operator delete[](void*, std::align_val_t, float);
struct SizedDealloc {
char a[32];
void* operator new(size_t);
void* operator new[](size_t);
void operator delete(void*, size_t);
void operator delete[](void*, size_t);
};
struct alignas(128) Overaligned {
char a[256];
};
struct DefaultCtorWithDefaultParam {
DefaultCtorWithDefaultParam(double d = 1.0);
};
void OperatorNew() {
new int; // No constructor
new(1.0f) int; // Placement new, no constructor
new int(); // Zero-init
new String(); // Constructor
new(1.0f) String("hello"); // Placement new, constructor with args
new Overaligned; // Aligned new
new(1.0f) Overaligned(); // Placement aligned new with zero-init
}
void OperatorNewArray(int n) {
new int[10]; // Constant size
new int[n]; // No constructor
new(1.0f) int[n]; // Placement new, no constructor
new String[n]; // Constructor
new Overaligned[n]; // Aligned new
new(1.0f) Overaligned[10]; // Aligned placement new
new DefaultCtorWithDefaultParam[n];
new int[n] { 0, 1, 2 };
}
int designatedInit() {
int a1[1000] = { [2] = 10002, [900] = 10900 };
return a1[900];
}
#if 0
void OperatorDelete() {
delete static_cast<int*>(nullptr); // No destructor
delete static_cast<String*>(nullptr); // Non-virtual destructor, with size.
delete static_cast<SizedDealloc*>(nullptr); // No destructor, with size.
delete static_cast<Overaligned*>(nullptr); // No destructor, with size and alignment.
delete static_cast<PolymorphicBase*>(nullptr); // Virtual destructor
}
void OperatorDeleteArray() {
delete[] static_cast<int*>(nullptr); // No destructor
delete[] static_cast<String*>(nullptr); // Non-virtual destructor, with size.
delete[] static_cast<SizedDealloc*>(nullptr); // No destructor, with size.
delete[] static_cast<Overaligned*>(nullptr); // No destructor, with size and alignment.
delete[] static_cast<PolymorphicBase*>(nullptr); // Virtual destructor
}
#endif
// semmle-extractor-options: -std=c++17

View File

@@ -0,0 +1,6 @@
void f() {
int a, b;
if (a && b) {
}
;
}

View File

@@ -0,0 +1,6 @@
void f() {
int a, b;
if (a || b) {
}
;
}

View File

@@ -0,0 +1,43 @@
void f() {
int i, j;
int* p, q;
i + j;
i - j;
i * j;
i / j;
i % j;
p + i;
p - i;
//q - p;
i << j;
i >> j;
i & j;
i | j;
i ^ j;
i == j;
i != j;
i > j;
i < j;
i >= j;
i <= j;
i += j;
i -= j;
i *= j;
i /= j;
i %= j;
i <<= j;
i >>= j;
i &= j;
i |= j;
i ^= j;
p += i;
p -= i;
i, j;
}

View File

@@ -0,0 +1,10 @@
class C {
public:
void g();
};
void f() {
C *c;
c->g();
;
}

View File

@@ -0,0 +1,11 @@
class C {
public:
C* d;
void g(int x, int y);
};
void f() {
int i, j, k, l;
C *c;
c->d->g(i + j, k - l);
}

View File

@@ -0,0 +1,232 @@
extern void somefun0(void);
extern void somefun2(int i, int j);
struct someStruct {
int i;
int j;
};
int topLevel1 = 1;
int topLevel2 = 1 + 2;
void (*pfunvv)(void);
int getInt(void);
void misc1(int argi, int argj) {
int i, j, is[3];
i = 0;
i = 1 + 2;
++i;
i += 1;
if (argi && argj) {
i = 3;
} else {
i = 4;
}
if (argi || argj) {
i = 3;
} else {
i = 4;
}
if (i && j) {
i = 3;
} else {
i = 4;
}
if (i || j) {
i = 3;
} else {
i = 4;
}
{ }
;
while(i) {
j++;
}
while(i && j) {
j++;
}
while(i || j) {
j++;
}
while(argi) {
j++;
}
do {
j++;
} while(i);
do {
j++;
} while(argi);
for(i = 0; i < 10; i++) {
}
for(; i < 10; i++) {
}
for(i = 0; ; i++) {
}
for(i = 0; i < 10;) {
}
for(; ; i++) {
}
for(; i < 10;) {
}
for(i = 0; ;) {
}
for(;;) {
}
goto LAB;
;
LAB:
;
somefun0();
somefun2(i, j);
(somefun2)(i, j);
i = is[1];
if (i > 3) ;
if (!i) ;
i = j ? 1 : 2;
}
void gnuConditionalOmittedOperand(struct someStruct *sp) {
int i, j;
i = j ? : 2;
i = sp->i ? : i;
}
void misc3(void) {
int i, j;
i, j;
switch (i) {
case 1: ;
case 2: break;
default: ;
}
switch (i) {
case 1: ;
case 2: break;
default: break;
}
switch (i) {
case -1: ;
case 1: ;
case 2: break;
}
switch (i) {
case 1: break;
case 2: ;
}
switch (i) {
case 1: ;
case 2: ;
}
int x = i + j;
int x1 = i + j, x2, x3 = i;
({ ; });
i = sizeof(j);
struct someStruct s, *sp;
sp = &s;
s.i = j;
sp->i = j;
j = s.i;
j = sp->i;
i = i & j;
i = i | j;
i = i ^ j;
if ((sp->i & j) && (sp->i & j)) ;
if (i && i && i) ;
if (i || i || i) ;
}
void funptr(void) {
int i, j;
int (*intFun) (int, int);
i = intFun(i, j);
pfunvv();
}
void aggInit(void) {
int x;
struct someStruct ss[] = {{1, 2}, {3, 4}};
static struct someStruct sssc[] = {{1, 2}, {3, 4}};
struct someStruct sInit1 = {
.i = x + x,
.j = x - x
};
struct someStruct sInit2 = {};
}
void offsetof_test(void) {
int i, j;
i = __builtin_offsetof(struct someStruct, j);
}
void vla(void) {
int i;
char str1[1 + 2 + 3 + 4];
char str2[i + 2 + 3 + 4 + 5];
char buf[80 * getInt()], *ptr = buf;
char matrix[getInt()][2][getInt()][2], ****ptr2 = matrix;
}
void magicvars(void) {
const char *pf = __PRETTY_FUNCTION__;
const char *strfunc = __func__;
;
}
void fret(void) {
return;
}
int freti(int i) {
return i;
}
void unreachable_end(void) {
while(1) {
;
}
}
void f_va(const char *fmt, ...) {
__builtin_va_list args;
;
__builtin_va_start(args,fmt);
;
__builtin_va_end(args);
;
}
extern int fmac (void);
#define MAC int fmac (void) { return 5; }
MAC
int global_with_init = 0 + 1;
int extern_local() {
// The variable declared here has an initializer, but it's not one that gets
// control flow in this function.
extern int global_with_init;
return global_with_init;
}
int assign_designated_init(struct someStruct *sp) {
*sp = (struct someStruct) {
.i = 1,
.j = 2,
};
}
static int global_int;
void *builtin_addressof_test() {
int *p = __builtin_addressof(global_int);
int *p1 = __builtin_addressof(global_int) + 1;
p1 = __builtin_addressof(global_int) + 1;
return __builtin_addressof(global_int);
}

View File

@@ -0,0 +1,34 @@
// semmle-extractor-options: --microsoft
char *Xstrdup(const char *string);
void abort();
struct FILE;
char *fgets(char *str, int num, FILE *stream);
int ignore_return_value();
#define IGNORE_RETURN_VALUE() ignore_return_value()
void myIgnoreReturnValue();
int main(int argc, char *argv[])
{
char *s1 = Xstrdup("Hello, world!");
char *s2 = Xstrdup(0);
if (argc == 0)
{
abort();
} else if (argc == 1) {
__assume(0);
}
{
char buffer[256];
char *result;
FILE *s;
result = fgets(buffer, 256, s);
}
IGNORE_RETURN_VALUE();
myIgnoreReturnValue();
}

View File

@@ -0,0 +1,24 @@
// semmle-extractor-options: --microsoft
void ms_try_except(int j) {
int x;
__try {
__try {
x = 1;
}
__except (j) {
x = 2;
}
__try {
x = 3;
}
__finally {
x = 4;
}
} __except (j - 1) {
x = 5;
}
;
}

View File

@@ -0,0 +1,55 @@
// semmle-extractor-options: --microsoft
#define EXCEPTION_EXECUTE_HANDLER 1
class C {
public:
C(int x);
~C();
};
void ms_except_mix(int b1) {
C c101(101);
__try {
C c102(102);
if (b1) {
throw 1;
}
C c103(103);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
C c104(104);
}
C c105(105);
}
void ms_finally_mix(int b2) {
C c101(101);
__try {
C c106(106);
if (b2) {
throw 2;
}
C c107(107);
}
__finally {
C c108(108);
}
C c109(109);
}
// This function gets a buggy CFG from both the extractor and the QL CFG
// implementation. The extractor-produced CFG contains a loop (!), and the QL
// CFG may destruct c201 twice.
void ms_empty_finally_at_end() {
C c201(201);
__try {
throw 3;
}
__finally {
}
}

View File

@@ -0,0 +1,9 @@
class C {
public:
C(int i, int j);
};
void f() {
int a, b, c, d;
new C(a + b, c - d);
}

View File

@@ -0,0 +1,12 @@
extern "C" int printf(const char*, ...);
struct Magic {
~Magic() {
printf("Goodbye cruel world.\n");
}
};
int main() {
static Magic m;
return 0;
}

View File

@@ -0,0 +1,7 @@
void f(int x) {
switch (x) {
case 1:
case 2:
}
;
}

View File

@@ -0,0 +1,6 @@
void g() { }
void f() {
g();
;
}

View File

@@ -0,0 +1,6 @@
void (*g())();
void f() {
g()();
;
}

View File

@@ -0,0 +1,5 @@
void f() {
int (*g)();
g();
;
}

View File

@@ -0,0 +1,28 @@
extern "C++" {
namespace std {
typedef unsigned long size_t;
}
void* operator new(std::size_t);
void* operator new[](std::size_t);
void operator delete(void*);
void operator delete[](void*);
}
class C_with_constr_destr {
public:
C_with_constr_destr() { };
~C_with_constr_destr() { };
};
void f_with_op(int i) {
char *c = new char;
char *buf1 = new char[500];
char *buf2 = new char[500 + i];
delete[] buf2;
delete[] buf1;
delete c;
C_with_constr_destr *cd = new C_with_constr_destr;
delete cd;
}

View File

@@ -0,0 +1,31 @@
void printf(char *format, ...);
int g(void) {
return 5;
}
void f(int i = g()) {
printf("Got %d\n", i);
}
class c {
public:
c(int j = g()) {};
void method(int k = g()) {};
};
int main(void) {
f(3);
f();
f(4);
f();
{
c my_c;
my_c.method();
}
return 0;
}

View File

@@ -0,0 +1,10 @@
class C {
public:
void (C::*g)();
};
void f() {
C *c, *d;
(c->*(d->g))();
;
}

View File

@@ -0,0 +1,30 @@
struct PM {
int x1;
int x2;
void f1();
void f2();
PM clone();
};
int PM::* getDataMemberPointer(bool);
typedef void (PM::*pmVoidVoid)();
pmVoidVoid getFunctionMemberPointer(bool);
int usePM(int PM::* pm) {
int acc;
PM obj;
// Needs fix for extractor bug CPP-313
//acc += obj.clone() .* getDataMemberPointer(true);
//acc += (&obj) ->* getDataMemberPointer(true);
(obj.clone() .* getFunctionMemberPointer(false))();
((&obj) ->* getFunctionMemberPointer(true))();
acc += obj .* pm;
acc += obj.clone() .* pm;
return acc;
}

View File

@@ -0,0 +1,198 @@
typedef unsigned char uint8_t;
void f_0(void) {
if (0) {
return; // prune
} else {
;
}
}
void f_1(void) {
if (1) {
return;
} else {
; // prune
}
}
void f_256(void) {
if (256) {
return;
} else {
; // prune
}
}
void f_uint8_t_0(void) {
if ((uint8_t)0) {
return; // prune
} else {
;
}
}
void f_uint8_t_1(void) {
if ((uint8_t)1) {
return;
} else {
; // prune
}
}
void f_uint8_t_256(void) {
if ((uint8_t)256) {
return; // prune
} else {
;
}
}
void f_uint8_t_257(void) {
if ((uint8_t)257) {
return;
} else {
; // prune
}
}
void f_uint8_t_minus1(void) {
if (255 == (uint8_t)-1) {
return;
} else {
; // prune
}
}
void f_v_int_0(void) {
int i = 0;
if (i) {
return; // prune
} else {
;
}
}
void f_v_int_1(void) {
int i = 1;
if (i) {
return;
} else {
; // prune
}
}
void f_v_int_256(void) {
int i = 256;
if (i) {
return;
} else {
; // prune
}
}
void f_v_uint8_t_0(void) {
uint8_t i = 0;
if (i) {
return; // prune
} else {
;
}
}
void f_v_uint8_t_1(void) {
uint8_t i = 1;
if (i) {
return;
} else {
; // prune
}
}
void f_v_uint8_t_256(void) {
uint8_t i = 256;
if (i) {
return; // prune
} else {
;
}
}
void f_v_uint8_t_257(void) {
uint8_t i = 257;
if (i) {
return;
} else {
; // prune
}
}
void f_v_uint8_t_minus1(void) {
uint8_t i = -1;
if (255 == i) {
return;
} else {
; // prune
}
}
void switch_f_0(void) {
switch(255) {
case 0: break; // prune
}
}
void switch_f_255(void) {
switch(255) {
case 255: break;
}
}
void switch_f_uint8_t_minus1(void) {
switch(255) {
case (uint8_t)-1: break;
}
}
void switch_f_uint8_t_256(void) {
switch(256) {
case (uint8_t)256: break; // prune
}
}
void switch_f_v_0(void) {
int i = 255;
switch(i) {
case 0: break; // prune
}
}
void switch_f_v_255(void) {
int i = 255;
switch(i) {
case 255: break;
}
}
void switch_f_v_uint8_t_minus1(void) {
int i = 255;
switch(i) {
case (uint8_t)-1: break;
}
}
void switch_f_v_uint8_t_256(void) {
int i = 256;
switch(i) {
case (uint8_t)256: break; // prune
}
}
void switch_asm(void) {
int faulted = 0;
asm volatile ("" : "=r"(faulted) : "0" (faulted));
switch (faulted) {
case 1: break;
}
}

View File

@@ -0,0 +1,4 @@
void f() {
int a, b, c, d, x;
x = a == b ? c + b : d - b;
}

View File

@@ -0,0 +1,400 @@
struct List {
struct List* next;
};
int test1(struct List* p) {
int count = 0;
for (; p; p = p->next) {
count = count+1;
}
return count;
}
int test2(struct List* p) {
int count = 0;
for (; p; p = p->next) {
count = (count+1) % 10;
}
return count;
}
int test3(struct List* p) {
int count = 0;
for (; p; p = p->next) {
count++;
count = count % 10;
}
return count;
}
int test4() {
int i = 0;
int total = 0;
for (i = 0; i < 2; i = i+1) {
total += i;
}
return total + i;
}
int test5() {
int i = 0;
int total = 0;
for (i = 0; i < 2; i++) {
total += i;
}
return total + i;
}
int test6() {
int i = 0;
int total = 0;
for (i = 0; i+2 < 4; i = i+1) {
total += i;
}
return total + i;
}
int test7(int i) {
if (i < 4) {
if (i < 5) {
return i;
}
}
return 1;
}
int test8(int x, int y) {
if (-1000 < y && y < 10) {
if (x < y-2) {
return x;
}
}
return y;
}
int test9(int x, int y) {
if (y == 0) {
if (x < 4) {
return 0;
}
} else {
if (x < 4) {
return 1;
}
}
return x;
}
int test10(int x, int y) {
if (y > 7) {
if (x < y) {
return 0;
}
return x;
}
return 1;
}
int test11(char *p) {
char c;
c = *p;
if (c != '\0')
*p++ = '\0';
if (c == ':') {
c = *p;
if (c != '\0')
*p++ = '\0';
if (c != ',')
return 1;
}
return 0;
}
typedef unsigned long long size_type;
size_type test12_helper() {
static size_type n = 0;
return n++;
}
int test12() {
size_type Start = 0;
while (Start <= test12_helper()-1)
{
const size_type Length = test12_helper();
Start += Length + 1;
}
return 1;
}
// Tests for overflow conditions.
int test13(char c, int i) {
unsigned char uc = c;
unsigned int x = 0;
unsigned int y = x-1;
int z = i+1;
return (double)(c + i + uc + x + y + z);
}
// Regression test for ODASA-6013.
int test14(int x) {
int x0 = (int)(char)x;
int x1 = (int)(unsigned char)x;
int x2 = (int)(unsigned short)x;
int x3 = (int)(unsigned int)x;
char c0 = x;
unsigned short s0 = x;
return x0 + x1 + x2 + x3 + c0 + s0;
}
long long test15(long long x) {
return (x > 0 && x == (int)x) ? x : -1;
}
// Tests for unary operators.
int test_unary(int a) {
int total = 0;
if (3 <= a && a <= 11) {
int b = +a;
int c = -a;
total += b+c;
}
if (0 <= a && a <= 11) {
int b = +a;
int c = -a;
total += b+c;
}
if (-7 <= a && a <= 11) {
int b = +a;
int c = -a;
total += b+c;
}
if (-7 <= a && a <= 1) {
int b = +a;
int c = -a;
total += b+c;
}
if (-7 <= a && a <= 0) {
int b = +a;
int c = -a;
total += b+c;
}
if (-7 <= a && a <= -2) {
int b = +a;
int c = -a;
total += b+c;
}
return total;
}
// Tests for multiplication.
int test_mult01(int a, int b) {
int total = 0;
if (3 <= a && a <= 11 && 5 <= b && b <= 23) {
int r = a*b; // 15 .. 253
total += r;
}
if (3 <= a && a <= 11 && 0 <= b && b <= 23) {
int r = a*b; // 0 .. 253
total += r;
}
if (3 <= a && a <= 11 && -13 <= b && b <= 23) {
int r = a*b; // -143 .. 253
total += r;
}
if (3 <= a && a <= 11 && -13 <= b && b <= 0) {
int r = a*b; // -143 .. 0
total += r;
}
if (3 <= a && a <= 11 && -13 <= b && b <= -7) {
int r = a*b; // -143 .. -21
total += r;
}
return total;
}
// Tests for multiplication.
int test_mult02(int a, int b) {
int total = 0;
if (0 <= a && a <= 11 && 5 <= b && b <= 23) {
int r = a*b; // 0 .. 253
total += r;
}
if (0 <= a && a <= 11 && 0 <= b && b <= 23) {
int r = a*b; // 0 .. 253
total += r;
}
if (0 <= a && a <= 11 && -13 <= b && b <= 23) {
int r = a*b; // -143 .. 253
total += r;
}
if (0 <= a && a <= 11 && -13 <= b && b <= 0) {
int r = a*b; // -143 .. 0
total += r;
}
if (0 <= a && a <= 11 && -13 <= b && b <= -7) {
int r = a*b; // -143 .. 0
total += r;
}
return total;
}
// Tests for multiplication.
int test_mult03(int a, int b) {
int total = 0;
if (-17 <= a && a <= 11 && 5 <= b && b <= 23) {
int r = a*b; // -391 .. 253
total += r;
}
if (-17 <= a && a <= 11 && 0 <= b && b <= 23) {
int r = a*b; // -391 .. 253
total += r;
}
if (-17 <= a && a <= 11 && -13 <= b && b <= 23) {
int r = a*b; // -391 .. 253
total += r;
}
if (-17 <= a && a <= 11 && -13 <= b && b <= 0) {
int r = a*b; // -143 .. 221
total += r;
}
if (-17 <= a && a <= 11 && -13 <= b && b <= -7) {
int r = a*b; // -143 .. 221
total += r;
}
return total;
}
// Tests for multiplication.
int test_mult04(int a, int b) {
int total = 0;
if (-17 <= a && a <= 0 && 5 <= b && b <= 23) {
int r = a*b; // -391 .. 0
total += r;
}
if (-17 <= a && a <= 0 && 0 <= b && b <= 23) {
int r = a*b; // -391 .. 0
total += r;
}
if (-17 <= a && a <= 0 && -13 <= b && b <= 23) {
int r = a*b; // -391 .. 221
total += r;
}
if (-17 <= a && a <= 0 && -13 <= b && b <= 0) {
int r = a*b; // 0 .. 221
total += r;
}
if (-17 <= a && a <= 0 && -13 <= b && b <= -7) {
int r = a*b; // 0 .. 221
total += r;
}
return total;
}
// Tests for multiplication.
int test_mult05(int a, int b) {
int total = 0;
if (-17 <= a && a <= -2 && 5 <= b && b <= 23) {
int r = a*b; // -391 .. -10
total += r;
}
if (-17 <= a && a <= -2 && 0 <= b && b <= 23) {
int r = a*b; // -391 .. 0
total += r;
}
if (-17 <= a && a <= -2 && -13 <= b && b <= 23) {
int r = a*b; // -391 .. 221
total += r;
}
if (-17 <= a && a <= -2 && -13 <= b && b <= 0) {
int r = a*b; // 0 .. 221
total += r;
}
if (-17 <= a && a <= -2 && -13 <= b && b <= -7) {
int r = a*b; // 14 .. 221
total += r;
}
return total;
}
int test16(int x) {
int d, i = 0;
if (x < 0) {
return -1;
}
while (i < 3) {
i++;
}
d = i;
if (x < 0) { // Comparison is always false.
if (d > -x) { // Unreachable code.
return 1;
}
}
return 0;
}
// Test ternary expression upper bounds.
unsigned int test_ternary01(unsigned int x) {
unsigned int y1, y2, y3, y4, y5, y6, y7, y8;
y1 = x < 100 ? x : 10; // y1 < 100
y2 = x >= 100 ? 10 : x; // y2 < 100
y3 = 0;
y4 = 0;
y5 = 0;
y6 = 0;
y7 = 0;
y8 = 0;
if (x < 300) {
y3 = x ?: 5; // y3 < 300
y4 = x ?: 500; // y4 <= 500
y5 = (x+1) ?: 500; // y5 <= 300
y6 = ((unsigned char)(x+1)) ?: 5; // y6 < 256
y7 = ((unsigned char)(x+1)) ?: 500; // y7 <= 500
y8 = ((unsigned short)(x+1)) ?: 500; // y8 <= 300
}
return y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8;
}
// Test ternary expression lower bounds.
unsigned int test_ternary02(unsigned int x) {
unsigned int y1, y2, y3, y4, y5;
y1 = x > 100 ? x : 110; // y1 > 100
y2 = x <= 100 ? 110 : x; // y2 > 100
y3 = 1000;
y4 = 1000;
y5 = 1000;
if (x >= 300) {
y3 = (x-300) ?: 5; // y3 >= 0
y4 = (x-200) ?: 5; // y4 >= 100
y5 = ((unsigned char)(x-200)) ?: 5; // y6 >= 0
}
return y1 + y2 + y3 + y4 + y5;
}
// Test the comma expression.
unsigned int test_comma01(unsigned int x) {
unsigned int y = x < 100 ? x : 100;
unsigned int y1;
unsigned int y2;
y1 = (++y, y);
y2 = (y++, y += 3, y);
return y1 + y2;
}

View File

@@ -0,0 +1,23 @@
class Error {
public:
Error () {}
virtual ~Error() {}
};
template <typename T>
int fun2() {
try {
}
catch (Error&) {
throw;
}
catch (...) {
return 1;
}
return 0;
}
void run_fun2(void) {
fun2<int>();
}

View File

@@ -0,0 +1,10 @@
void return_void() {
return;
;
}
int return_int() {
return 1;
;
}

View File

@@ -0,0 +1,5 @@
void g() {
double x[5];
int i, a, b;
i = (a + b)[x];
}

View File

@@ -0,0 +1,38 @@
void always_false() {
for(;0;) {
l1:;
}
l2:;
}
void always_true_1() {
for(;1;) {
l1:;
break;
}
l2:;
}
void always_true_2() {
for(;1;) {
l1:;
if(0) break;
if(1) break;
l2:;
}
l3:;
}
void always_true_3() {
for(;1;) {
l1:;
}
l2:;
}
void normal(int x, int y) {
for(;x < y;) {
x = y;
}
l:;
}

View File

@@ -0,0 +1,57 @@
#include "statements.h"
void simple() {
NonTrivial nt;
}
void simple2() {
NonTrivial one;
NonTrivial two;
}
void early_return(int x) {
NonTrivial before;
if(x) {
NonTrivial inner;
return;
}
NonTrivial after;
}
void early_throw(int x) {
NonTrivial before;
if(x) {
NonTrivial inner;
throw;
}
NonTrivial after;
}
void for_loop_scope(int x) {
NonTrivial outer_scope;
for(NonTrivial for_scope; x < 10; ++x)
{
NonTrivial inner_scope;
}
}
void never_destructs() {
NonTrivial nt;
loop: goto loop;
}
void gotos(int x) {
NonTrivial nt1;
if(x)
goto one; // this goto jumps into a block
{
static int y = ++x;
one:
NonTrivial nt2;
if(y)
goto two; // this goto jumps out of a block
NonTrivial nt3;
}
two:
--x;
}

View File

@@ -0,0 +1,4 @@
struct NonTrivial {
~NonTrivial() {
}
};

View File

@@ -0,0 +1,252 @@
void write_ref(int &ref) {
ref = 1;
}
class MyClass {
public:
MyClass();
~MyClass();
private:
int val;
};
MyClass :: MyClass()
{
int a, b, c, d, e; // BAD: 'e' is unused
int &f = d;
write_ref(a);
val = b + f;
throw c;
}
MyClass :: ~MyClass()
{
}
void test()
{
MyClass mc; // GOOD: constructor and destructor may have side-effects
MyClass *mc_ptr; // BAD: 'mc_ptr' is unused
MyClass &mc_ref = mc; // BAD: 'mc_ref' is unused
}
// ---
template<class T> class container {
public:
T t;
};
// static int variable in non-instantiated template function
template<typename T> void *templateFunction()
{
static int my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static template parameter variable in non-instantiated template function
template<typename T> void *templateFunction2()
{
static T my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static template derived variable in non-instantiated template function
template<typename T> void *templateFunction3()
{
static container<T *> *my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static unused int variable in non-instantiated template function
template<typename T> void *templateFunction4()
{
static int my_static; // BAD
static void* my_ptr = 0;
return my_ptr;
}
// static int variable in twice instantiated template function
template<typename T> void *instantiatedTemplateFunction()
{
static int my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static template parameter variable in twice instantiated template function
template<typename T> void *instantiatedTemplateFunction2()
{
static T my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static template derived variable in twice instantiated template function
template<typename T> void *instantiatedTemplateFunction3()
{
static container<T *> *my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// static unused int variable in twice instantiated template function
template<typename T> void *instantiatedTemplateFunction4()
{
static int my_static; // BAD
static void* my_ptr = 0;
return my_ptr;
}
void caller()
{
instantiatedTemplateFunction<int>();
instantiatedTemplateFunction<float>();
instantiatedTemplateFunction2<int>();
instantiatedTemplateFunction2<float>();
instantiatedTemplateFunction3<int>();
instantiatedTemplateFunction3<float>();
instantiatedTemplateFunction4<int>();
instantiatedTemplateFunction4<float>();
}
// This is a non-template version of the above.
void *nonTemplateFunction()
{
static int *my_static; // GOOD
static void* my_ptr = &my_static;
return my_ptr;
}
// This is a non-template version of the above.
void *nonTemplateFunction2()
{
static int *my_static; // BAD
static void* my_ptr = 0;
return my_ptr;
}
// non-static int variable in non-instantiated template function
template<typename T> void *templateFunction5()
{
int my_local; // GOOD
void* my_ptr = &my_local;
return my_ptr;
}
// non-static template parameter variable in non-instantiated template function
template<typename T> void *templateFunction6()
{
T my_local; // GOOD
void* my_ptr = &my_local;
return my_ptr;
}
// non-static template derived variable in non-instantiated template function
template<typename T> void *templateFunction7()
{
container<T *> *my_local; // GOOD
void* my_ptr = &my_local;
return my_ptr;
}
// non-static unused int variable in non-instantiated template function
template<typename T> void *templateFunction8()
{
int my_local; // BAD
void* my_ptr = 0;
return my_ptr;
}
template<typename T> class templateClass
{
public:
// static int variable in class template method
void *templateClassMethod()
{
static int my_static; // GOOD
void* my_ptr = &my_static;
return my_ptr;
}
// static template parameter variable in class template method
void *templateClassMethod2()
{
static T my_static; // GOOD
void* my_ptr = &my_static;
return my_ptr;
}
// static template derived variable in class template method
void *templateClassMethod3()
{
static container<T *> *my_static; // GOOD
void* my_ptr = &my_static;
return my_ptr;
}
// static unused int variable in class template method
void *templateClassMethod4()
{
static int my_static; // BAD
void* my_ptr = 0;
return my_ptr;
}
};
templateClass<int> tc_i;
template<typename T> class MyTemplateClass2
{
public:
void method()
{
static T *a; // BAD
static T b; // GOOD - T could have a constructor / destructor
static container<T> *c; // BAD
static container<T *> d; // BAD [NOT DETECTED - due to type container<T *> depending on type container<T>, which *could* have a constructor, though as used here it can't]
static container<T> e; // GOOD - T could have a constructor / destructor
}
};
// ---
int myGlobal;
class MyMethodClass
{
public:
void MyMethod() {myGlobal++;} // side-effect
};
class MyConstructorClass
{
public:
MyConstructorClass() {myGlobal++;} // side-effect
};
class MyDerivedClass : public MyConstructorClass
{
};
class MyContainingClass
{
private:
MyConstructorClass mcc;
};
void testFunction()
{
MyMethodClass mmc; // BAD: unused
MyConstructorClass mcc; // GOOD
MyDerivedClass mdc; // GOOD
MyContainingClass mcc2; // GOOD
}

View File

@@ -0,0 +1,32 @@
namespace staticlocals {
int g() {
return 1;
}
int h() {
return 1;
}
void f() {
static int i = g(), j = h();
static int k = g();
;
}
constexpr int addOne(int x) {
return x + 1;
}
struct C {
constexpr C() { }
};
void f2() {
constexpr int two = 2;
static int i = addOne(two);
static int j = addOne(2);
static C c{};
}
}

View File

@@ -0,0 +1,10 @@
class C {
public:
static void g();
};
void f() {
C c;
c.g();
;
}

View File

@@ -0,0 +1,11 @@
class C {
public:
C* d;
static void g(int x, int y);
};
void f() {
int i, j, k, l;
C c;
c.d->g(i + j, k - l);
}

View File

@@ -0,0 +1,34 @@
namespace stmtexpr {
class C {
public:
C(int x);
~C();
};
void f(int b) {
int i;
if (({
C c(1);
b;
}))
2;
else
;
}
void g(int b) {
void *ptr;
int i;
lab:
ptr = &&lab;
goto *({
C c(3);
ptr;
});
}
}

View File

@@ -0,0 +1,7 @@
void cpp_fun() {
typeof(({ int twisty(); twisty(); })) twisty();
decltype( ({using namespace std; using t = int; 1; }) ) i;
}

View File

@@ -0,0 +1,21 @@
template <typename T>
struct vector
{
T* begin() { return nullptr; }
T* end() { return nullptr; }
};
template <typename T>
void stream_it(vector<T>& t)
{
for(T& itr : t)
{
}
}
int main()
{
vector<int> xs;
stream_it(xs);
return 0;
}

View File

@@ -0,0 +1,5 @@
void f() {
double x[5];
int i, a, b;
i = x[a + b];
}

View File

@@ -0,0 +1,35 @@
// In a standard switch statement, each exit node of the conditional expression
// has an edge to the block statement of the body, and this block statement
// has an edge to each switch case.
int switch_block(int i) {
switch (i < 0 ? -i : i) {
case 0:
return 1;
default:
return i;
}
}
// If the body of a switch is not a compound statement then a block statement
// is synthesized by the extractor.
int switch_single(int i) {
switch (i < 0 ? -i : i)
case 0:
case 1:
return i;
return 2;
}
// If the body of a switch statement is a compound statement OTHER than a block
// then the CFG looks very different. Each exit node of the conditional
// expression has an edge directly to each switch case, and the body of the
// switch is unreachable. Hopefully nobody writes code like this.
int switch_notblock(int i) {
switch (i < 0 ? -i : i)
if (1) {
case 0:
return 1;
default:
return i;
}
}

View File

@@ -0,0 +1,8 @@
void f(int x) {
switch (x) {
case 1:
case 2:
default:
}
;
}

View File

@@ -0,0 +1,8 @@
| ms_try_mix__ms_empty_finally_at_end | ms_try_mix.cpp:53:13:54:3 | { ... } | ms_try_mix.cpp:47:6:47:28 | ms_empty_finally_at_end | Standard edge, only from QL |
| ms_try_mix__ms_empty_finally_at_end | ms_try_mix.cpp:53:13:54:3 | { ... } | ms_try_mix.cpp:55:1:55:1 | c201 | Standard edge, only from extractor |
| ms_try_mix__ms_empty_finally_at_end | ms_try_mix.cpp:55:1:55:1 | call to c201.~C | ms_try_mix.cpp:47:6:47:28 | ms_empty_finally_at_end | Standard edge, only from extractor |
| ms_try_mix__ms_finally_mix | ms_try_mix.cpp:39:5:39:5 | call to c108.~C | ms_try_mix.cpp:27:6:27:19 | ms_finally_mix | Standard edge, only from QL |
| ms_try_mix__ms_finally_mix | ms_try_mix.cpp:39:5:39:5 | call to c108.~C | ms_try_mix.cpp:42:1:42:1 | c101 | Standard edge, only from extractor |
| staticlocals__staticlocals_f2 | file://:0:0:0:0 | call to C | staticlocals.cpp:30:1:30:1 | return ... | Standard edge, only from QL |
| staticlocals__staticlocals_f2 | file://:0:0:0:0 | initializer for c | file://:0:0:0:0 | call to C | Standard edge, only from QL |
| staticlocals__staticlocals_f2 | staticlocals.cpp:29:5:29:17 | declaration | file://:0:0:0:0 | initializer for c | Standard edge, only from QL |

View File

@@ -0,0 +1,8 @@
import Compare
from
ControlFlowNode n1, ControlFlowNode n2, string msg
where
differentEdge(n1, n2, msg)
select
getScopeName(n1), n1, n2, msg

View File

@@ -0,0 +1,235 @@
void f_if_1(int i) {
if (i) {
;
} else {
;
}
}
void f_if_2(void) {
if (1) {
;
} else {
;
}
}
void f_if_3(void) {
if (0) {
;
} else {
;
}
}
void f_for_1(void) {
int i;
for(i = 0; i < 10; i++) {
;
}
return;
}
void f_for_2(void) {
int i;
for(i = 0; 1; i++) {
;
}
return;
}
void f_for_3(void) {
int i;
for(i = 0; 0; i++) {
;
}
return;
}
void f_while_1(int i) {
while(i) {
i--;
}
return;
}
void f_while_2(void) {
while(1) {
;
}
return;
}
void f_while_3(void) {
while(0) {
;
}
return;
}
void f_do_1(int i) {
do {
i--;
} while (i);
return;
}
void f_do_2(void) {
do {
;
} while (1);
return;
}
void f_do_3(void) {
do {
;
} while (0);
return;
}
void f_cond_1(int i) {
int j = i ? 3 : 4;
return;
}
void f_cond_2(void) {
int j = 1 ? 3 : 4;
return;
}
void f_cond_3(void) {
int j = 0 ? 3 : 4;
return;
}
void f_switch_1(int i) {
switch(i) {
case 0:
return;
case 1:
return;
case 2:
case 3:
;
case 4:
return;
default:
return;
}
return;
}
void f_switch_2(int i) {
switch(i) {
case 0:
return;
case 1:
return;
case 2:
case 3:
;
case 4:
return;
}
return;
}
void f_switch_3(void) {
switch(1) {
case 0:
return;
case 1:
return;
case 2:
case 3:
;
case 4:
return;
default:
return;
}
return;
}
void f_switch_4(void) {
switch(1) {
case 0:
return;
case 1:
return;
case 2:
case 3:
;
case 4:
return;
}
return;
}
void f_switch_5(void) {
switch(9) {
case 0:
return;
case 1:
return;
case 2:
case 3:
;
case 4:
return;
default:
return;
}
return;
}
void f_switch_6(void) {
switch(9) {
case 0:
return;
case 1:
return;
case 2:
case 3:
;
case 4:
return;
}
return;
}
void f_switch_7(int i) {
switch(i ? 1 : 3) {
case 0:
return;
case 1:
return;
case 2:
case 3:
;
case 4:
return;
}
return;
}
int f_and_1(int x, int y) {
if (x && !y) {
return x;
}
return y;
}
int f_and_2(int x, int y) {
if (!(x && y)) {
return x;
}
return y;
}
void f_if_ternary_1(int b, int x, int y) {
if (b ? x : y) {
}
}

View File

@@ -0,0 +1,5 @@
void f() {
for (;;) {
;
}
}

View File

@@ -0,0 +1,25 @@
namespace std {
struct exception {
virtual ~exception();
};
}
struct exn1 : std::exception { };
struct exn2 : std::exception { };
void bypass_catch() {
try {
throw exn1();
} catch (const exn2 &e) {
return;
}
}
void throw_from_nonstmt(int select) {
if (select) {
int x = (throw 1, 2);
} else {
({ throw 3; });
}
}

View File

@@ -0,0 +1,14 @@
void f() {
int i;
&i;
-i;
//+i
~i;
!i;
i++;
i--;
++i;
--i;
}

View File

@@ -0,0 +1,11 @@
struct HasDestructor {
~HasDestructor();
};
template<typename T>
void callDestructor(T *x) {
x->~T();
}
template void callDestructor<int>(int *x);
template void callDestructor<HasDestructor>(HasDestructor *x);

View File

@@ -0,0 +1,15 @@
int atoi(const char*);
int main(int argc, char** argv)
{
char* matrix[argc][atoi(argv[1])];
return 0;
}
int getInt(void);
void vla_typedef(void) {
typedef char myType[10 * 4][3 + getInt()][3][90 * getInt()];
myType var;
char c1, c2 = 'x', buf[10 * 4][2 + getInt()][3][80 * getInt()], buf2[getInt()], *ptr = buf;
}

Some files were not shown because too many files have changed in this diff Show More