Skip to content

Commit 80f0dc3

Browse files
committed
[clang][dataflow] Unsoundly treat "Unknown" as "Equivalent" in widening.
This change makes widening act the same as equivalence checking. When the analysis does not provide an answer regarding the equivalence of two distinct values, the framework treats them as equivalent. This is an unsound choice that enables convergence. Differential Revision: https://reviews.llvm.org/D159355
1 parent 9ff0a44 commit 80f0dc3

File tree

2 files changed

+21
-24
lines changed

2 files changed

+21
-24
lines changed

clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,8 @@
2222
#include "llvm/ADT/DenseSet.h"
2323
#include "llvm/ADT/MapVector.h"
2424
#include "llvm/ADT/STLExtras.h"
25-
#include "llvm/Support/Casting.h"
2625
#include "llvm/Support/ErrorHandling.h"
2726
#include <cassert>
28-
#include <memory>
2927
#include <utility>
3028

3129
namespace clang {
@@ -50,6 +48,23 @@ llvm::DenseMap<K, V> intersectDenseMaps(const llvm::DenseMap<K, V> &Map1,
5048
return Result;
5149
}
5250

51+
// Whether to consider equivalent two values with an unknown relation.
52+
//
53+
// FIXME: this function is a hack enabling unsoundness to support
54+
// convergence. Once we have widening support for the reference/pointer and
55+
// struct built-in models, this should be unconditionally `false` (and inlined
56+
// as such at its call sites).
57+
static bool equateUnknownValues(Value::Kind K) {
58+
switch (K) {
59+
case Value::Kind::Integer:
60+
case Value::Kind::Pointer:
61+
case Value::Kind::Record:
62+
return true;
63+
default:
64+
return false;
65+
}
66+
}
67+
5368
static bool compareDistinctValues(QualType Type, Value &Val1,
5469
const Environment &Env1, Value &Val2,
5570
const Environment &Env2,
@@ -66,18 +81,7 @@ static bool compareDistinctValues(QualType Type, Value &Val1,
6681
case ComparisonResult::Different:
6782
return false;
6883
case ComparisonResult::Unknown:
69-
switch (Val1.getKind()) {
70-
case Value::Kind::Integer:
71-
case Value::Kind::Pointer:
72-
case Value::Kind::Record:
73-
// FIXME: this choice intentionally introduces unsoundness to allow
74-
// for convergence. Once we have widening support for the
75-
// reference/pointer and struct built-in models, this should be
76-
// `false`.
77-
return true;
78-
default:
79-
return false;
80-
}
84+
return equateUnknownValues(Val1.getKind());
8185
}
8286
llvm_unreachable("All cases covered in switch");
8387
}
@@ -167,8 +171,7 @@ static Value &widenDistinctValues(QualType Type, Value &Prev,
167171
if (auto *W = Model.widen(Type, Prev, PrevEnv, Current, CurrentEnv))
168172
return *W;
169173

170-
// Default of widening is a no-op: leave the current value unchanged.
171-
return Current;
174+
return equateUnknownValues(Prev.getKind()) ? Prev : Current;
172175
}
173176

174177
// Returns whether the values in `Map1` and `Map2` compare equal for those

clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3964,10 +3964,7 @@ TEST(TransferTest, LoopDereferencingChangingPointerConverges) {
39643964
}
39653965
}
39663966
)cc";
3967-
// FIXME: Implement pointer value widening to make analysis converge.
3968-
ASSERT_THAT_ERROR(
3969-
checkDataflowWithNoopAnalysis(Code),
3970-
llvm::FailedWithMessage("maximum number of iterations reached"));
3967+
ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
39713968
}
39723969

39733970
TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
@@ -3989,10 +3986,7 @@ TEST(TransferTest, LoopDereferencingChangingRecordPointerConverges) {
39893986
}
39903987
}
39913988
)cc";
3992-
// FIXME: Implement pointer value widening to make analysis converge.
3993-
ASSERT_THAT_ERROR(
3994-
checkDataflowWithNoopAnalysis(Code),
3995-
llvm::FailedWithMessage("maximum number of iterations reached"));
3989+
ASSERT_THAT_ERROR(checkDataflowWithNoopAnalysis(Code), llvm::Succeeded());
39963990
}
39973991

39983992
TEST(TransferTest, DoesNotCrashOnUnionThisExpr) {

0 commit comments

Comments
 (0)