Skip to content

Commit 688f540

Browse files
authored
Merge pull request github#3582 from MathiasVP/qldoc-for-controlflow
C++: QLDoc for BasicBlock, ControlFlowGraph and Dataflow
2 parents 725a8f5 + 52da575 commit 688f540

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

cpp/ql/src/semmle/code/cpp/controlflow/BasicBlocks.qll

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Provides a library for reasoning about control flow at the granularity of basic blocks.
3+
* This is usually much more efficient than reasoning directly at the level of `ControlFlowNode`s.
4+
*/
5+
16
import cpp
27
private import internal.PrimitiveBasicBlocks
38
private import internal.ConstantExprs
@@ -148,22 +153,37 @@ predicate bb_successor = bb_successor_cached/2;
148153
class BasicBlock extends ControlFlowNodeBase {
149154
BasicBlock() { basic_block_entry_node(this) }
150155

156+
/** Holds if this basic block contains `node`. */
151157
predicate contains(ControlFlowNode node) { basic_block_member(node, this, _) }
152158

159+
/** Gets the `ControlFlowNode` at position `pos` in this basic block. */
153160
ControlFlowNode getNode(int pos) { basic_block_member(result, this, pos) }
154161

162+
/** Gets a `ControlFlowNode` in this basic block. */
155163
ControlFlowNode getANode() { basic_block_member(result, this, _) }
156164

165+
/** Gets a `BasicBlock` that is a direct successor of this basic block. */
157166
BasicBlock getASuccessor() { bb_successor(this, result) }
158167

168+
/** Gets a `BasicBlock` that is a direct predecessor of this basic block. */
159169
BasicBlock getAPredecessor() { bb_successor(result, this) }
160170

171+
/**
172+
* Gets a `BasicBlock` such that the control-flow edge `(this, result)` may be taken
173+
* when the outgoing edge of this basic block is an expression that is true.
174+
*/
161175
BasicBlock getATrueSuccessor() { result.getStart() = this.getEnd().getATrueSuccessor() }
162176

177+
/**
178+
* Gets a `BasicBlock` such that the control-flow edge `(this, result)` may be taken
179+
* when the outgoing edge of this basic block is an expression that is false.
180+
*/
163181
BasicBlock getAFalseSuccessor() { result.getStart() = this.getEnd().getAFalseSuccessor() }
164182

183+
/** Gets the final `ControlFlowNode` of this basic block. */
165184
ControlFlowNode getEnd() { basic_block_member(result, this, bb_length(this) - 1) }
166185

186+
/** Gets the first `ControlFlowNode` of this basic block. */
167187
ControlFlowNode getStart() { result = this }
168188

169189
/** Gets the number of `ControlFlowNode`s in this basic block. */
@@ -192,6 +212,7 @@ class BasicBlock extends ControlFlowNodeBase {
192212
this.getEnd().getLocation().hasLocationInfo(endf, _, _, endl, endc)
193213
}
194214

215+
/** Gets the function containing this basic block. */
195216
Function getEnclosingFunction() { result = this.getStart().getControlFlowScope() }
196217

197218
/**

cpp/ql/src/semmle/code/cpp/controlflow/ControlFlowGraph.qll

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
/**
2+
* Provides a library for reasoning about control flow at the granularity of
3+
* individual nodes in the control-flow graph.
4+
*/
5+
16
import cpp
27
import BasicBlocks
38
private import semmle.code.cpp.controlflow.internal.ConstantExprs
@@ -29,8 +34,10 @@ private import semmle.code.cpp.controlflow.internal.CFG
2934
* `Handler`. There are no edges from function calls to `Handler`s.
3035
*/
3136
class ControlFlowNode extends Locatable, ControlFlowNodeBase {
37+
/** Gets a direct successor of this control-flow node, if any. */
3238
ControlFlowNode getASuccessor() { successors_adapted(this, result) }
3339

40+
/** Gets a direct predecessor of this control-flow node, if any. */
3441
ControlFlowNode getAPredecessor() { this = result.getASuccessor() }
3542

3643
/** Gets the function containing this control-flow node. */
@@ -71,6 +78,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
7178
result = getASuccessor()
7279
}
7380

81+
/** Gets the `BasicBlock` containing this control-flow node. */
7482
BasicBlock getBasicBlock() { result.getANode() = this }
7583
}
7684

@@ -86,10 +94,18 @@ import ControlFlowGraphPublic
8694
*/
8795
class ControlFlowNodeBase extends ElementBase, @cfgnode { }
8896

97+
/**
98+
* Holds when `n2` is a control-flow node such that the control-flow
99+
* edge `(n1, n2)` may be taken when `n1` is an expression that is true.
100+
*/
89101
predicate truecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
90102
qlCFGTrueSuccessor(n1, n2)
91103
}
92104

105+
/**
106+
* Holds when `n2` is a control-flow node such that the control-flow
107+
* edge `(n1, n2)` may be taken when `n1` is an expression that is false.
108+
*/
93109
predicate falsecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
94110
qlCFGFalseSuccessor(n1, n2)
95111
}

cpp/ql/src/semmle/code/cpp/controlflow/Dataflow.qll

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,25 @@ import Dereferenced
1515
abstract class DataflowAnnotation extends string {
1616
DataflowAnnotation() { this = "pointer-null" or this = "pointer-valid" }
1717

18+
/** Holds if this annotation is the default annotation. */
1819
abstract predicate isDefault();
1920

21+
/** Holds if this annotation is generated when analyzing expression `e`. */
2022
abstract predicate generatedOn(Expr e);
2123

24+
/**
25+
* Holds if this annotation is generated for the variable `v` when
26+
* the control-flow edge `(src, dest)` is taken.
27+
*/
2228
abstract predicate generatedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest);
2329

30+
/**
31+
* Holds if this annotation is removed for the variable `v` when
32+
* the control-flow edge `(src, dest)` is taken.
33+
*/
2434
abstract predicate killedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest);
2535

36+
/** Holds if expression `e` is given this annotation. */
2637
predicate marks(Expr e) {
2738
this.generatedOn(e) and reachable(e)
2839
or
@@ -31,6 +42,7 @@ abstract class DataflowAnnotation extends string {
3142
exists(LocalScopeVariable v | this.marks(v, e) and e = v.getAnAccess())
3243
}
3344

45+
/** Holds if the variable `v` accessed in control-flow node `n` is given this annotation. */
3446
predicate marks(LocalScopeVariable v, ControlFlowNode n) {
3547
v.getAnAccess().getEnclosingFunction().getBlock() = n and
3648
this.isDefault()
@@ -57,13 +69,21 @@ abstract class DataflowAnnotation extends string {
5769
)
5870
}
5971

72+
/**
73+
* Holds if the variable `v` preserves this annotation when the control-flow
74+
* edge `(src, dest)` is taken.
75+
*/
6076
predicate preservedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest) {
6177
this.marks(v, src) and
6278
src.getASuccessor() = dest and
6379
not v.getInitializer() = dest and
6480
not v.getAnAssignment() = src
6581
}
6682

83+
/**
84+
* Holds if the variable `v` is assigned this annotation when `src` is an assignment
85+
* expression that assigns to `v` and the control-flow edge `(src, dest)` is taken.
86+
*/
6787
predicate assignedBy(LocalScopeVariable v, ControlFlowNode src, ControlFlowNode dest) {
6888
this.marks(src.(AssignExpr).getRValue()) and
6989
src = v.getAnAssignment() and

0 commit comments

Comments
 (0)