mirror of
https://github.com/github/codeql.git
synced 2026-05-02 04:05:14 +02:00
@@ -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) {
|
||||
|
||||
@@ -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) }
|
||||
|
||||
1386
cpp/ql/src/semmle/code/cpp/controlflow/internal/CFG.qll
Normal file
1386
cpp/ql/src/semmle/code/cpp/controlflow/internal/CFG.qll
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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)
|
||||
)
|
||||
}
|
||||
@@ -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)) }
|
||||
|
||||
|
||||
@@ -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&`).
|
||||
* 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).
|
||||
*/
|
||||
|
||||
@@ -2691,6 +2691,6 @@ class TranslatedConditionDeclExpr extends TranslatedNonConstantExpr {
|
||||
}
|
||||
|
||||
private TranslatedExpr getConditionExpr() {
|
||||
result = getTranslatedExpr(condDeclExpr.getExpr().getFullyConverted())
|
||||
result = getTranslatedExpr(condDeclExpr.getVariableAccess().getFullyConverted())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
12
cpp/ql/test/library-tests/qlcfg/CPP-309.cpp
Normal file
12
cpp/ql/test/library-tests/qlcfg/CPP-309.cpp
Normal 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);
|
||||
}
|
||||
146
cpp/ql/test/library-tests/qlcfg/Compare.qll
Normal file
146
cpp/ql/test/library-tests/qlcfg/Compare.qll
Normal 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)
|
||||
}
|
||||
}
|
||||
16
cpp/ql/test/library-tests/qlcfg/FunctionTryStmt.cpp
Normal file
16
cpp/ql/test/library-tests/qlcfg/FunctionTryStmt.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
int foo() try {
|
||||
return 0;
|
||||
}
|
||||
catch(...) {
|
||||
throw;
|
||||
}
|
||||
|
||||
class Bar
|
||||
{
|
||||
Bar() try {
|
||||
return;
|
||||
}
|
||||
catch(...) {
|
||||
throw;
|
||||
}
|
||||
};
|
||||
11
cpp/ql/test/library-tests/qlcfg/VacuousDestructorCall.cpp
Normal file
11
cpp/ql/test/library-tests/qlcfg/VacuousDestructorCall.cpp
Normal 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);
|
||||
}
|
||||
50
cpp/ql/test/library-tests/qlcfg/abortingfunctions.cpp
Normal file
50
cpp/ql/test/library-tests/qlcfg/abortingfunctions.cpp
Normal 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;
|
||||
}
|
||||
4
cpp/ql/test/library-tests/qlcfg/aggregateinitializer.c
Normal file
4
cpp/ql/test/library-tests/qlcfg/aggregateinitializer.c
Normal file
@@ -0,0 +1,4 @@
|
||||
void f() {
|
||||
int a, b, c, d;
|
||||
int x[] = { a + b, c - d };
|
||||
}
|
||||
20
cpp/ql/test/library-tests/qlcfg/allocators.cpp
Normal file
20
cpp/ql/test/library-tests/qlcfg/allocators.cpp
Normal 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
|
||||
7
cpp/ql/test/library-tests/qlcfg/array_delete.cpp
Normal file
7
cpp/ql/test/library-tests/qlcfg/array_delete.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
struct Foo {
|
||||
~Foo();
|
||||
};
|
||||
|
||||
void f() {
|
||||
delete[] (Foo*)nullptr;
|
||||
}
|
||||
11
cpp/ql/test/library-tests/qlcfg/assignexpr.cpp
Normal file
11
cpp/ql/test/library-tests/qlcfg/assignexpr.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
class C {
|
||||
public:
|
||||
int i;
|
||||
};
|
||||
|
||||
void f() {
|
||||
C c;
|
||||
int a, b;
|
||||
c.i = a + b;
|
||||
;
|
||||
}
|
||||
20
cpp/ql/test/library-tests/qlcfg/assume0.cpp
Normal file
20
cpp/ql/test/library-tests/qlcfg/assume0.cpp
Normal 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
|
||||
}
|
||||
29
cpp/ql/test/library-tests/qlcfg/bad_asts.cpp
Normal file
29
cpp/ql/test/library-tests/qlcfg/bad_asts.cpp
Normal 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.
|
||||
}
|
||||
}
|
||||
30
cpp/ql/test/library-tests/qlcfg/break_labels.c
Normal file
30
cpp/ql/test/library-tests/qlcfg/break_labels.c
Normal 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++;
|
||||
}
|
||||
}
|
||||
|
||||
57
cpp/ql/test/library-tests/qlcfg/builtin.c
Normal file
57
cpp/ql/test/library-tests/qlcfg/builtin.c
Normal 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;
|
||||
}
|
||||
16
cpp/ql/test/library-tests/qlcfg/builtin.cpp
Normal file
16
cpp/ql/test/library-tests/qlcfg/builtin.cpp
Normal 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);
|
||||
}
|
||||
16578
cpp/ql/test/library-tests/qlcfg/cfg.expected
Normal file
16578
cpp/ql/test/library-tests/qlcfg/cfg.expected
Normal file
File diff suppressed because it is too large
Load Diff
35
cpp/ql/test/library-tests/qlcfg/cfg.ql
Normal file
35
cpp/ql/test/library-tests/qlcfg/cfg.ql
Normal 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
|
||||
|
||||
5
cpp/ql/test/library-tests/qlcfg/condition_decl_int.cpp
Normal file
5
cpp/ql/test/library-tests/qlcfg/condition_decl_int.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
void ConditionDecl() {
|
||||
int j = 0;
|
||||
while(int k = j < 5) {
|
||||
}
|
||||
}
|
||||
52
cpp/ql/test/library-tests/qlcfg/condition_decls.cpp
Normal file
52
cpp/ql/test/library-tests/qlcfg/condition_decls.cpp
Normal 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;
|
||||
}
|
||||
46
cpp/ql/test/library-tests/qlcfg/conditional_destructors.cpp
Normal file
46
cpp/ql/test/library-tests/qlcfg/conditional_destructors.cpp
Normal 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)) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
10
cpp/ql/test/library-tests/qlcfg/constmemberaccess.cpp
Normal file
10
cpp/ql/test/library-tests/qlcfg/constmemberaccess.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
class C {
|
||||
public:
|
||||
int x;
|
||||
};
|
||||
|
||||
void f() {
|
||||
C *c;
|
||||
int i;
|
||||
i = c->x;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
169
cpp/ql/test/library-tests/qlcfg/cpp11.cpp
Normal file
169
cpp/ql/test/library-tests/qlcfg/cpp11.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
21
cpp/ql/test/library-tests/qlcfg/cpp17.cpp
Normal file
21
cpp/ql/test/library-tests/qlcfg/cpp17.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
class C { };
|
||||
|
||||
void f() {
|
||||
new C;
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
class C { };
|
||||
|
||||
void f() {
|
||||
C* c = new C();
|
||||
delete c;
|
||||
}
|
||||
9
cpp/ql/test/library-tests/qlcfg/deleteexpr.cpp
Normal file
9
cpp/ql/test/library-tests/qlcfg/deleteexpr.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
public:
|
||||
~C();
|
||||
};
|
||||
|
||||
void f() {
|
||||
C* c = new C();
|
||||
delete c;
|
||||
}
|
||||
38
cpp/ql/test/library-tests/qlcfg/destructors.cpp
Normal file
38
cpp/ql/test/library-tests/qlcfg/destructors.cpp
Normal 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 };
|
||||
}
|
||||
}
|
||||
38
cpp/ql/test/library-tests/qlcfg/dostmt.c
Normal file
38
cpp/ql/test/library-tests/qlcfg/dostmt.c
Normal 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:;
|
||||
}
|
||||
310
cpp/ql/test/library-tests/qlcfg/drawDifferent.expected
Normal file
310
cpp/ql/test/library-tests/qlcfg/drawDifferent.expected
Normal 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 | |
|
||||
11
cpp/ql/test/library-tests/qlcfg/drawDifferent.ql
Normal file
11
cpp/ql/test/library-tests/qlcfg/drawDifferent.ql
Normal 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
|
||||
16
cpp/ql/test/library-tests/qlcfg/duff.c
Normal file
16
cpp/ql/test/library-tests/qlcfg/duff.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
||||
23
cpp/ql/test/library-tests/qlcfg/duff2.c
Normal file
23
cpp/ql/test/library-tests/qlcfg/duff2.c
Normal 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);
|
||||
}
|
||||
|
||||
4
cpp/ql/test/library-tests/qlcfg/dummyblock.c
Normal file
4
cpp/ql/test/library-tests/qlcfg/dummyblock.c
Normal file
@@ -0,0 +1,4 @@
|
||||
void f() {
|
||||
if (1)
|
||||
;
|
||||
}
|
||||
20
cpp/ql/test/library-tests/qlcfg/ellipsisexceptionhandler.cpp
Normal file
20
cpp/ql/test/library-tests/qlcfg/ellipsisexceptionhandler.cpp
Normal 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 (...) {
|
||||
}
|
||||
}
|
||||
}
|
||||
5
cpp/ql/test/library-tests/qlcfg/emptyblock.c
Normal file
5
cpp/ql/test/library-tests/qlcfg/emptyblock.c
Normal file
@@ -0,0 +1,5 @@
|
||||
void f() {
|
||||
{
|
||||
}
|
||||
;
|
||||
}
|
||||
7
cpp/ql/test/library-tests/qlcfg/enum.c
Normal file
7
cpp/ql/test/library-tests/qlcfg/enum.c
Normal file
@@ -0,0 +1,7 @@
|
||||
enum {
|
||||
a = 1 + 1
|
||||
};
|
||||
|
||||
int f() {
|
||||
return a;
|
||||
}
|
||||
25
cpp/ql/test/library-tests/qlcfg/exceptionhandler.cpp
Normal file
25
cpp/ql/test/library-tests/qlcfg/exceptionhandler.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
4
cpp/ql/test/library-tests/qlcfg/exprstmt.c
Normal file
4
cpp/ql/test/library-tests/qlcfg/exprstmt.c
Normal file
@@ -0,0 +1,4 @@
|
||||
void f() {
|
||||
1;
|
||||
;
|
||||
}
|
||||
10
cpp/ql/test/library-tests/qlcfg/fieldaccess.cpp
Normal file
10
cpp/ql/test/library-tests/qlcfg/fieldaccess.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
class C {
|
||||
public:
|
||||
int x;
|
||||
};
|
||||
|
||||
void f() {
|
||||
C *c;
|
||||
int i;
|
||||
i = c->x;
|
||||
}
|
||||
21
cpp/ql/test/library-tests/qlcfg/forstmt.cpp
Normal file
21
cpp/ql/test/library-tests/qlcfg/forstmt.cpp
Normal 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
|
||||
}
|
||||
}
|
||||
5
cpp/ql/test/library-tests/qlcfg/gotostmt.c
Normal file
5
cpp/ql/test/library-tests/qlcfg/gotostmt.c
Normal file
@@ -0,0 +1,5 @@
|
||||
void v() {
|
||||
goto label;
|
||||
;
|
||||
label:
|
||||
}
|
||||
45
cpp/ql/test/library-tests/qlcfg/ifelsestmt.c
Normal file
45
cpp/ql/test/library-tests/qlcfg/ifelsestmt.c
Normal 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:;
|
||||
}
|
||||
32
cpp/ql/test/library-tests/qlcfg/ifstmt.c
Normal file
32
cpp/ql/test/library-tests/qlcfg/ifstmt.c
Normal 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:;
|
||||
}
|
||||
4
cpp/ql/test/library-tests/qlcfg/initializer.c
Normal file
4
cpp/ql/test/library-tests/qlcfg/initializer.c
Normal file
@@ -0,0 +1,4 @@
|
||||
void f() {
|
||||
int a, b;
|
||||
int i = a + b;
|
||||
}
|
||||
984
cpp/ql/test/library-tests/qlcfg/ir.cpp
Normal file
984
cpp/ql/test/library-tests/qlcfg/ir.cpp
Normal 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
|
||||
6
cpp/ql/test/library-tests/qlcfg/landexpr.c
Normal file
6
cpp/ql/test/library-tests/qlcfg/landexpr.c
Normal file
@@ -0,0 +1,6 @@
|
||||
void f() {
|
||||
int a, b;
|
||||
if (a && b) {
|
||||
}
|
||||
;
|
||||
}
|
||||
6
cpp/ql/test/library-tests/qlcfg/lorexpr.c
Normal file
6
cpp/ql/test/library-tests/qlcfg/lorexpr.c
Normal file
@@ -0,0 +1,6 @@
|
||||
void f() {
|
||||
int a, b;
|
||||
if (a || b) {
|
||||
}
|
||||
;
|
||||
}
|
||||
43
cpp/ql/test/library-tests/qlcfg/ltrbinopexpr.c
Normal file
43
cpp/ql/test/library-tests/qlcfg/ltrbinopexpr.c
Normal 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;
|
||||
}
|
||||
10
cpp/ql/test/library-tests/qlcfg/membercallexpr.cpp
Normal file
10
cpp/ql/test/library-tests/qlcfg/membercallexpr.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
class C {
|
||||
public:
|
||||
void g();
|
||||
};
|
||||
|
||||
void f() {
|
||||
C *c;
|
||||
c->g();
|
||||
;
|
||||
}
|
||||
11
cpp/ql/test/library-tests/qlcfg/membercallexpr_args.cpp
Normal file
11
cpp/ql/test/library-tests/qlcfg/membercallexpr_args.cpp
Normal 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);
|
||||
}
|
||||
232
cpp/ql/test/library-tests/qlcfg/misc.c
Normal file
232
cpp/ql/test/library-tests/qlcfg/misc.c
Normal 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);
|
||||
}
|
||||
34
cpp/ql/test/library-tests/qlcfg/ms_assume.cpp
Normal file
34
cpp/ql/test/library-tests/qlcfg/ms_assume.cpp
Normal 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();
|
||||
}
|
||||
24
cpp/ql/test/library-tests/qlcfg/ms_try_except.cpp
Normal file
24
cpp/ql/test/library-tests/qlcfg/ms_try_except.cpp
Normal 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;
|
||||
}
|
||||
;
|
||||
}
|
||||
|
||||
55
cpp/ql/test/library-tests/qlcfg/ms_try_mix.cpp
Normal file
55
cpp/ql/test/library-tests/qlcfg/ms_try_mix.cpp
Normal 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 {
|
||||
}
|
||||
}
|
||||
9
cpp/ql/test/library-tests/qlcfg/newexpr.cpp
Normal file
9
cpp/ql/test/library-tests/qlcfg/newexpr.cpp
Normal 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);
|
||||
}
|
||||
12
cpp/ql/test/library-tests/qlcfg/no_dynamic_init.cpp
Normal file
12
cpp/ql/test/library-tests/qlcfg/no_dynamic_init.cpp
Normal 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;
|
||||
}
|
||||
7
cpp/ql/test/library-tests/qlcfg/nodefaultswitchstmt.c
Normal file
7
cpp/ql/test/library-tests/qlcfg/nodefaultswitchstmt.c
Normal file
@@ -0,0 +1,7 @@
|
||||
void f(int x) {
|
||||
switch (x) {
|
||||
case 1:
|
||||
case 2:
|
||||
}
|
||||
;
|
||||
}
|
||||
6
cpp/ql/test/library-tests/qlcfg/nonmembercallexpr.c
Normal file
6
cpp/ql/test/library-tests/qlcfg/nonmembercallexpr.c
Normal file
@@ -0,0 +1,6 @@
|
||||
void g() { }
|
||||
|
||||
void f() {
|
||||
g();
|
||||
;
|
||||
}
|
||||
6
cpp/ql/test/library-tests/qlcfg/nonmemberfp2callexpr.c
Normal file
6
cpp/ql/test/library-tests/qlcfg/nonmemberfp2callexpr.c
Normal file
@@ -0,0 +1,6 @@
|
||||
void (*g())();
|
||||
|
||||
void f() {
|
||||
g()();
|
||||
;
|
||||
}
|
||||
5
cpp/ql/test/library-tests/qlcfg/nonmemberfpcallexpr.c
Normal file
5
cpp/ql/test/library-tests/qlcfg/nonmemberfpcallexpr.c
Normal file
@@ -0,0 +1,5 @@
|
||||
void f() {
|
||||
int (*g)();
|
||||
g();
|
||||
;
|
||||
}
|
||||
28
cpp/ql/test/library-tests/qlcfg/ops.cpp
Normal file
28
cpp/ql/test/library-tests/qlcfg/ops.cpp
Normal 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;
|
||||
}
|
||||
31
cpp/ql/test/library-tests/qlcfg/parameterinitializer.cpp
Normal file
31
cpp/ql/test/library-tests/qlcfg/parameterinitializer.cpp
Normal 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;
|
||||
}
|
||||
10
cpp/ql/test/library-tests/qlcfg/pmcallexpr.cpp
Normal file
10
cpp/ql/test/library-tests/qlcfg/pmcallexpr.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
class C {
|
||||
public:
|
||||
void (C::*g)();
|
||||
};
|
||||
|
||||
void f() {
|
||||
C *c, *d;
|
||||
(c->*(d->g))();
|
||||
;
|
||||
}
|
||||
30
cpp/ql/test/library-tests/qlcfg/pointer_to_member.cpp
Normal file
30
cpp/ql/test/library-tests/qlcfg/pointer_to_member.cpp
Normal 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;
|
||||
}
|
||||
198
cpp/ql/test/library-tests/qlcfg/pruning.c
Normal file
198
cpp/ql/test/library-tests/qlcfg/pruning.c
Normal 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;
|
||||
}
|
||||
}
|
||||
4
cpp/ql/test/library-tests/qlcfg/questionexpr.c
Normal file
4
cpp/ql/test/library-tests/qlcfg/questionexpr.c
Normal file
@@ -0,0 +1,4 @@
|
||||
void f() {
|
||||
int a, b, c, d, x;
|
||||
x = a == b ? c + b : d - b;
|
||||
}
|
||||
400
cpp/ql/test/library-tests/qlcfg/range_analysis.c
Normal file
400
cpp/ql/test/library-tests/qlcfg/range_analysis.c
Normal 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;
|
||||
}
|
||||
23
cpp/ql/test/library-tests/qlcfg/rethrow_error.cpp
Normal file
23
cpp/ql/test/library-tests/qlcfg/rethrow_error.cpp
Normal 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>();
|
||||
}
|
||||
|
||||
10
cpp/ql/test/library-tests/qlcfg/returnstmt.c
Normal file
10
cpp/ql/test/library-tests/qlcfg/returnstmt.c
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
void return_void() {
|
||||
return;
|
||||
;
|
||||
}
|
||||
|
||||
int return_int() {
|
||||
return 1;
|
||||
;
|
||||
}
|
||||
5
cpp/ql/test/library-tests/qlcfg/revsubscriptexpr.c
Normal file
5
cpp/ql/test/library-tests/qlcfg/revsubscriptexpr.c
Normal file
@@ -0,0 +1,5 @@
|
||||
void g() {
|
||||
double x[5];
|
||||
int i, a, b;
|
||||
i = (a + b)[x];
|
||||
}
|
||||
38
cpp/ql/test/library-tests/qlcfg/shortforstmt.cpp
Normal file
38
cpp/ql/test/library-tests/qlcfg/shortforstmt.cpp
Normal 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:;
|
||||
}
|
||||
57
cpp/ql/test/library-tests/qlcfg/statements.cpp
Normal file
57
cpp/ql/test/library-tests/qlcfg/statements.cpp
Normal 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;
|
||||
}
|
||||
4
cpp/ql/test/library-tests/qlcfg/statements.h
Normal file
4
cpp/ql/test/library-tests/qlcfg/statements.h
Normal file
@@ -0,0 +1,4 @@
|
||||
struct NonTrivial {
|
||||
~NonTrivial() {
|
||||
}
|
||||
};
|
||||
252
cpp/ql/test/library-tests/qlcfg/static_init_templates.cpp
Normal file
252
cpp/ql/test/library-tests/qlcfg/static_init_templates.cpp
Normal 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
|
||||
}
|
||||
32
cpp/ql/test/library-tests/qlcfg/staticlocals.cpp
Normal file
32
cpp/ql/test/library-tests/qlcfg/staticlocals.cpp
Normal 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{};
|
||||
}
|
||||
|
||||
}
|
||||
10
cpp/ql/test/library-tests/qlcfg/staticmembercallexpr.cpp
Normal file
10
cpp/ql/test/library-tests/qlcfg/staticmembercallexpr.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
class C {
|
||||
public:
|
||||
static void g();
|
||||
};
|
||||
|
||||
void f() {
|
||||
C c;
|
||||
c.g();
|
||||
;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
34
cpp/ql/test/library-tests/qlcfg/stmt_expr.cpp
Normal file
34
cpp/ql/test/library-tests/qlcfg/stmt_expr.cpp
Normal 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;
|
||||
});
|
||||
}
|
||||
}
|
||||
7
cpp/ql/test/library-tests/qlcfg/stmt_in_type.cpp
Normal file
7
cpp/ql/test/library-tests/qlcfg/stmt_in_type.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
void cpp_fun() {
|
||||
typeof(({ int twisty(); twisty(); })) twisty();
|
||||
|
||||
decltype( ({using namespace std; using t = int; 1; }) ) i;
|
||||
}
|
||||
|
||||
21
cpp/ql/test/library-tests/qlcfg/stream_it.cpp
Normal file
21
cpp/ql/test/library-tests/qlcfg/stream_it.cpp
Normal 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;
|
||||
}
|
||||
5
cpp/ql/test/library-tests/qlcfg/subscriptexpr.c
Normal file
5
cpp/ql/test/library-tests/qlcfg/subscriptexpr.c
Normal file
@@ -0,0 +1,5 @@
|
||||
void f() {
|
||||
double x[5];
|
||||
int i, a, b;
|
||||
i = x[a + b];
|
||||
}
|
||||
35
cpp/ql/test/library-tests/qlcfg/switchbody.c
Normal file
35
cpp/ql/test/library-tests/qlcfg/switchbody.c
Normal 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;
|
||||
}
|
||||
}
|
||||
8
cpp/ql/test/library-tests/qlcfg/switchstmt.c
Normal file
8
cpp/ql/test/library-tests/qlcfg/switchstmt.c
Normal file
@@ -0,0 +1,8 @@
|
||||
void f(int x) {
|
||||
switch (x) {
|
||||
case 1:
|
||||
case 2:
|
||||
default:
|
||||
}
|
||||
;
|
||||
}
|
||||
8
cpp/ql/test/library-tests/qlcfg/tellDifferent.expected
Normal file
8
cpp/ql/test/library-tests/qlcfg/tellDifferent.expected
Normal 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 |
|
||||
8
cpp/ql/test/library-tests/qlcfg/tellDifferent.ql
Normal file
8
cpp/ql/test/library-tests/qlcfg/tellDifferent.ql
Normal 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
|
||||
235
cpp/ql/test/library-tests/qlcfg/test.c
Normal file
235
cpp/ql/test/library-tests/qlcfg/test.c
Normal 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) {
|
||||
}
|
||||
}
|
||||
5
cpp/ql/test/library-tests/qlcfg/tinyforstmt.c
Normal file
5
cpp/ql/test/library-tests/qlcfg/tinyforstmt.c
Normal file
@@ -0,0 +1,5 @@
|
||||
void f() {
|
||||
for (;;) {
|
||||
;
|
||||
}
|
||||
}
|
||||
25
cpp/ql/test/library-tests/qlcfg/try_catch.cpp
Normal file
25
cpp/ql/test/library-tests/qlcfg/try_catch.cpp
Normal 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; });
|
||||
}
|
||||
}
|
||||
14
cpp/ql/test/library-tests/qlcfg/unaryopexpr.c
Normal file
14
cpp/ql/test/library-tests/qlcfg/unaryopexpr.c
Normal file
@@ -0,0 +1,14 @@
|
||||
void f() {
|
||||
int i;
|
||||
&i;
|
||||
|
||||
-i;
|
||||
//+i
|
||||
~i;
|
||||
!i;
|
||||
|
||||
i++;
|
||||
i--;
|
||||
++i;
|
||||
--i;
|
||||
}
|
||||
11
cpp/ql/test/library-tests/qlcfg/vacuous_dtor_call.cpp
Normal file
11
cpp/ql/test/library-tests/qlcfg/vacuous_dtor_call.cpp
Normal 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);
|
||||
15
cpp/ql/test/library-tests/qlcfg/vla.c
Normal file
15
cpp/ql/test/library-tests/qlcfg/vla.c
Normal 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
Reference in New Issue
Block a user