@@ -21,6 +21,35 @@ using namespace ento;
21
21
22
22
namespace {
23
23
class SimpleSValBuilder : public SValBuilder {
24
+
25
+ // With one `simplifySValOnce` call, a compound symbols might collapse to
26
+ // simpler symbol tree that is still possible to further simplify. Thus, we
27
+ // do the simplification on a new symbol tree until we reach the simplest
28
+ // form, i.e. the fixpoint.
29
+ // Consider the following symbol `(b * b) * b * b` which has this tree:
30
+ // *
31
+ // / \
32
+ // * b
33
+ // / \
34
+ // / b
35
+ // (b * b)
36
+ // Now, if the `b * b == 1` new constraint is added then during the first
37
+ // iteration we have the following transformations:
38
+ // * *
39
+ // / \ / \
40
+ // * b --> b b
41
+ // / \
42
+ // / b
43
+ // 1
44
+ // We need another iteration to reach the final result `1`.
45
+ SVal simplifyUntilFixpoint (ProgramStateRef State, SVal Val);
46
+
47
+ // Recursively descends into symbolic expressions and replaces symbols
48
+ // with their known values (in the sense of the getKnownValue() method).
49
+ // We traverse the symbol tree and query the constraint values for the
50
+ // sub-trees and if a value is a constant we do the constant folding.
51
+ SVal simplifySValOnce (ProgramStateRef State, SVal V);
52
+
24
53
public:
25
54
SimpleSValBuilder (llvm::BumpPtrAllocator &alloc, ASTContext &context,
26
55
ProgramStateManager &stateMgr)
@@ -40,8 +69,6 @@ class SimpleSValBuilder : public SValBuilder {
40
69
// / (integer) value, that value is returned. Otherwise, returns NULL.
41
70
const llvm::APSInt *getKnownValue (ProgramStateRef state, SVal V) override ;
42
71
43
- // / Recursively descends into symbolic expressions and replaces symbols
44
- // / with their known values (in the sense of the getKnownValue() method).
45
72
SVal simplifySVal (ProgramStateRef State, SVal V) override ;
46
73
47
74
SVal MakeSymIntVal (const SymExpr *LHS, BinaryOperator::Opcode op,
@@ -1105,7 +1132,20 @@ const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
1105
1132
return nullptr ;
1106
1133
}
1107
1134
1135
+ SVal SimpleSValBuilder::simplifyUntilFixpoint (ProgramStateRef State, SVal Val) {
1136
+ SVal SimplifiedVal = simplifySValOnce (State, Val);
1137
+ while (SimplifiedVal != Val) {
1138
+ Val = SimplifiedVal;
1139
+ SimplifiedVal = simplifySValOnce (State, Val);
1140
+ }
1141
+ return SimplifiedVal;
1142
+ }
1143
+
1108
1144
SVal SimpleSValBuilder::simplifySVal (ProgramStateRef State, SVal V) {
1145
+ return simplifyUntilFixpoint (State, V);
1146
+ }
1147
+
1148
+ SVal SimpleSValBuilder::simplifySValOnce (ProgramStateRef State, SVal V) {
1109
1149
// For now, this function tries to constant-fold symbols inside a
1110
1150
// nonloc::SymbolVal, and does nothing else. More simplifications should
1111
1151
// be possible, such as constant-folding an index in an ElementRegion.
0 commit comments