Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8065bf1

Browse files
committed
C++: Per-variable overrides
Without these changes, there was no way to tell which variables were overridden by a given instance of `SimpleRangeAnalysisDefinition`. All four overrides are needed because they fit into different mutual recursions of the `SimpleRangeAnalysis` implementation.
1 parent 7dce4d0 commit 8065bf1

2 files changed

Lines changed: 47 additions & 13 deletions

File tree

cpp/ql/src/experimental/semmle/code/cpp/models/interfaces/SimpleRangeAnalysisDefinition.qll

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,54 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
1010
/**
1111
* EXPERIMENTAL: The API of this class may change without notice.
1212
*
13-
* An SSA definition for which a range can be deduced. Extend this class to add
14-
* functionality to the range analysis library.
13+
* An SSA definition for which a range can be deduced. As with
14+
* `RangeSsaDefinition` and `SsaDefinition`, instances of this class
15+
* correspond to points in the program where one or more variables are defined
16+
* or have their value constrained in some way.
17+
*
18+
* Extend this class to add functionality to the range analysis library.
1519
*/
1620
abstract class SimpleRangeAnalysisDefinition extends RangeSsaDefinition {
17-
/**
18-
* Gets the lower bound of the defomotopn.
21+
/**
22+
* Holds if this `SimpleRangeAnalysisDefinition` adds range information for
23+
* `v`. Because a `SimpleRangeAnalysisDefinition` is just a point in the
24+
* program, it's possible that more than one variable might be defined at
25+
* this point. This predicate clarifies which variable(s) should get range
26+
* information from `this`.
27+
*
28+
* This predicate **must be overridden** to hold for any `v` that can show
29+
* up in the other members of `SimpleRangeAnalysisDefinition`. Conversely,
30+
* the other members **must be accurate** for any `v` in this predicate.
31+
*/
32+
abstract predicate hasRangeInformationFor(StackVariable v);
33+
34+
/**
35+
* Holds if `(this, v)` depends on the range of the unconverted expression
36+
* `e`. This information is used to inform the range analysis about cyclic
37+
* dependencies. Without this information, range analysis might work for
38+
* simple cases but will go into infinite loops on complex code.
39+
*
40+
* For example, when modelling the definition by reference in a call to an
41+
* overloaded `operator=`, written as `v = e`, the definition of `(this, v)`
42+
* depends on `e`.
43+
*/
44+
abstract predicate dependsOnExpr(StackVariable v, Expr e);
45+
46+
/**
47+
* Gets the lower bound of the variable `v` defined by this definition.
1948
*
2049
* Implementations of this predicate should use
2150
* `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for
22-
* recursive calls to get the bounds of their children.
51+
* recursive calls to get the bounds of their dependencies.
2352
*/
24-
abstract float getLowerBounds();
53+
abstract float getLowerBounds(StackVariable v);
2554

2655
/**
27-
* Gets the upper bound of the definition.
56+
* Gets the upper bound of the variable `v` defined by this definition.
2857
*
2958
* Implementations of this predicate should use
3059
* `getFullyConvertedLowerBounds` and `getFullyConvertedUpperBounds` for
31-
* recursive calls to get the bounds of their children.
60+
* recursive calls to get the bounds of their dependencies.
3261
*/
33-
abstract float getUpperBounds();
34-
}
62+
abstract float getUpperBounds(StackVariable v);
63+
}

cpp/ql/src/semmle/code/cpp/rangeanalysis/SimpleRangeAnalysis.qll

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,11 @@ private predicate defDependsOnDef(
336336
or
337337
// Phi nodes.
338338
phiDependsOnDef(def, v, srcDef, srcVar)
339+
or
340+
// Extensions
341+
exists(Expr expr | def.(SimpleRangeAnalysisDefinition).dependsOnExpr(v, expr) |
342+
exprDependsOnDef(expr, srcDef, srcVar)
343+
)
339344
}
340345

341346
/**
@@ -495,7 +500,7 @@ private predicate analyzableDef(RangeSsaDefinition def, StackVariable v) {
495500
phiDependsOnDef(def, v, _, _)
496501
or
497502
// A modeled def for range analysis
498-
def.(SimpleRangeAnalysisDefinition).getAVariable() =v
503+
def.(SimpleRangeAnalysisDefinition).hasRangeInformationFor(v)
499504
}
500505

501506
/**
@@ -1220,7 +1225,7 @@ private float getDefLowerBoundsImpl(RangeSsaDefinition def, StackVariable v) {
12201225
result = getPhiLowerBounds(v, def)
12211226
or
12221227
// A modeled def for range analysis
1223-
result = def.(SimpleRangeAnalysisDefinition).getLowerBounds()
1228+
result = def.(SimpleRangeAnalysisDefinition).getLowerBounds(v)
12241229
or
12251230
// Unanalyzable definitions.
12261231
unanalyzableDefBounds(def, v, result, _)
@@ -1256,7 +1261,7 @@ private float getDefUpperBoundsImpl(RangeSsaDefinition def, StackVariable v) {
12561261
result = getPhiUpperBounds(v, def)
12571262
or
12581263
// A modeled def for range analysis
1259-
result = def.(SimpleRangeAnalysisDefinition).getUpperBounds()
1264+
result = def.(SimpleRangeAnalysisDefinition).getUpperBounds(v)
12601265
or
12611266
// Unanalyzable definitions.
12621267
unanalyzableDefBounds(def, v, _, result)

0 commit comments

Comments
 (0)