aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp')
-rw-r--r--clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp28
1 files changed, 24 insertions, 4 deletions
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index fd7b06e..62332a1 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -48,6 +48,24 @@ static llvm::DenseMap<const ValueDecl *, StorageLocation *> intersectDeclToLoc(
return Result;
}
+// Performs a join on either `ExprToLoc` or `ExprToVal`.
+// The maps must be consistent in the sense that any entries for the same
+// expression must map to the same location / value. This is the case if we are
+// performing a join for control flow within a full-expression (which is the
+// only case when this function should be used).
+template <typename MapT> MapT joinExprMaps(const MapT &Map1, const MapT &Map2) {
+ MapT Result = Map1;
+
+ for (const auto &Entry : Map2) {
+ [[maybe_unused]] auto [It, Inserted] = Result.insert(Entry);
+ // If there was an existing entry, its value should be the same as for the
+ // entry we were trying to insert.
+ assert(It->second == Entry.second);
+ }
+
+ return Result;
+}
+
// Whether to consider equivalent two values with an unknown relation.
//
// FIXME: this function is a hack enabling unsoundness to support
@@ -627,7 +645,8 @@ LatticeJoinEffect Environment::widen(const Environment &PrevEnv,
}
Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
- Environment::ValueModel &Model) {
+ Environment::ValueModel &Model,
+ ExprJoinBehavior ExprBehavior) {
assert(EnvA.DACtx == EnvB.DACtx);
assert(EnvA.ThisPointeeLoc == EnvB.ThisPointeeLoc);
assert(EnvA.CallStack == EnvB.CallStack);
@@ -675,9 +694,10 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
JoinedEnv.LocToVal =
joinLocToVal(EnvA.LocToVal, EnvB.LocToVal, EnvA, EnvB, JoinedEnv, Model);
- // We intentionally leave `JoinedEnv.ExprToLoc` and `JoinedEnv.ExprToVal`
- // empty, as we never need to access entries in these maps outside of the
- // basic block that sets them.
+ if (ExprBehavior == KeepExprState) {
+ JoinedEnv.ExprToVal = joinExprMaps(EnvA.ExprToVal, EnvB.ExprToVal);
+ JoinedEnv.ExprToLoc = joinExprMaps(EnvA.ExprToLoc, EnvB.ExprToLoc);
+ }
return JoinedEnv;
}