aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
diff options
context:
space:
mode:
authormartinboehme <mboehme@google.com>2024-04-23 08:10:55 +0200
committerGitHub <noreply@github.com>2024-04-23 08:10:55 +0200
commit9ba6961ce05b17a70c22354f0b54a963ed1ab49c (patch)
treeb8400f6ab5561851fb0da81bdeeffb062debfb49 /clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
parent4513050f526be8bc17883685efec91a15ae427f8 (diff)
downloadllvm-9ba6961ce05b17a70c22354f0b54a963ed1ab49c.zip
llvm-9ba6961ce05b17a70c22354f0b54a963ed1ab49c.tar.gz
llvm-9ba6961ce05b17a70c22354f0b54a963ed1ab49c.tar.bz2
Reapply "[clang][dataflow] Model conditional operator correctly." with fixes (#89596)
I reverted https://github.com/llvm/llvm-project/pull/89213 beause it was causing buildbots to fail with assertion failures. Embarrassingly, it turns out I had been running tests locally in `Release` mode, i.e. with `assert()` compiled away. This PR re-lands #89213 with fixes for the failing assertions.
Diffstat (limited to 'clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp')
-rw-r--r--clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp46
1 files changed, 24 insertions, 22 deletions
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 05395e07..3cb656a 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -237,13 +237,8 @@ joinLocToVal(const llvm::MapVector<const StorageLocation *, Value *> &LocToVal,
continue;
assert(It->second != nullptr);
- if (areEquivalentValues(*Val, *It->second)) {
- Result.insert({Loc, Val});
- continue;
- }
-
- if (Value *JoinedVal = joinDistinctValues(
- Loc->getType(), *Val, Env1, *It->second, Env2, JoinedEnv, Model)) {
+ if (Value *JoinedVal = Environment::joinValues(
+ Loc->getType(), Val, Env1, It->second, Env2, JoinedEnv, Model)) {
Result.insert({Loc, JoinedVal});
}
}
@@ -775,27 +770,16 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
JoinedEnv.LocForRecordReturnVal = EnvA.LocForRecordReturnVal;
JoinedEnv.ThisPointeeLoc = EnvA.ThisPointeeLoc;
- if (EnvA.ReturnVal == nullptr || EnvB.ReturnVal == nullptr) {
- // `ReturnVal` might not always get set -- for example if we have a return
- // statement of the form `return some_other_func()` and we decide not to
- // analyze `some_other_func()`.
- // In this case, we can't say anything about the joined return value -- we
- // don't simply want to propagate the return value that we do have, because
- // it might not be the correct one.
- // This occurs for example in the test `ContextSensitiveMutualRecursion`.
+ if (EnvA.CallStack.empty()) {
JoinedEnv.ReturnVal = nullptr;
- } else if (areEquivalentValues(*EnvA.ReturnVal, *EnvB.ReturnVal)) {
- JoinedEnv.ReturnVal = EnvA.ReturnVal;
} else {
- assert(!EnvA.CallStack.empty());
// FIXME: Make `CallStack` a vector of `FunctionDecl` so we don't need this
// cast.
auto *Func = dyn_cast<FunctionDecl>(EnvA.CallStack.back());
assert(Func != nullptr);
- if (Value *JoinedVal =
- joinDistinctValues(Func->getReturnType(), *EnvA.ReturnVal, EnvA,
- *EnvB.ReturnVal, EnvB, JoinedEnv, Model))
- JoinedEnv.ReturnVal = JoinedVal;
+ JoinedEnv.ReturnVal =
+ joinValues(Func->getReturnType(), EnvA.ReturnVal, EnvA, EnvB.ReturnVal,
+ EnvB, JoinedEnv, Model);
}
if (EnvA.ReturnLoc == EnvB.ReturnLoc)
@@ -821,6 +805,24 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
return JoinedEnv;
}
+Value *Environment::joinValues(QualType Ty, Value *Val1,
+ const Environment &Env1, Value *Val2,
+ const Environment &Env2, Environment &JoinedEnv,
+ Environment::ValueModel &Model) {
+ if (Val1 == nullptr || Val2 == nullptr)
+ // We can't say anything about the joined value -- even if one of the values
+ // is non-null, we don't want to simply propagate it, because it would be
+ // too specific: Because the other value is null, that means we have no
+ // information at all about the value (i.e. the value is unconstrained).
+ return nullptr;
+
+ if (areEquivalentValues(*Val1, *Val2))
+ // Arbitrarily return one of the two values.
+ return Val1;
+
+ return joinDistinctValues(Ty, *Val1, Env1, *Val2, Env2, JoinedEnv, Model);
+}
+
StorageLocation &Environment::createStorageLocation(QualType Type) {
return DACtx->createStorageLocation(Type);
}