summaryrefslogtreecommitdiff
path: root/clang/lib/Analysis
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-02-05 18:04:23 +0000
committerDimitry Andric <dim@FreeBSD.org>2022-02-05 18:05:05 +0000
commitecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (patch)
tree3a4038f3b7bafaeade9fd6146ea8021237616657 /clang/lib/Analysis
parent6f8fc217eaa12bf657be1c6468ed9938d10168b3 (diff)
Vendor import of llvm-project main llvmorg-14-init-18294-gdb01b123d012,vendor/llvm-project/llvmorg-14-init-18294-gdb01b123d012
the last commit before the upstream release/14.x branch was created.
Diffstat (limited to 'clang/lib/Analysis')
-rw-r--r--clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp73
-rw-r--r--clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp11
2 files changed, 65 insertions, 19 deletions
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 938f7338b640..eca58b313761 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -41,6 +41,21 @@ llvm::DenseMap<K, V> intersectDenseMaps(const llvm::DenseMap<K, V> &Map1,
return Result;
}
+/// Returns true if and only if `Val1` is equivalent to `Val2`.
+static bool equivalentValues(QualType Type, Value *Val1, Value *Val2,
+ Environment::ValueModel &Model) {
+ if (Val1 == Val2)
+ return true;
+
+ if (auto *IndVal1 = dyn_cast<IndirectionValue>(Val1)) {
+ auto *IndVal2 = cast<IndirectionValue>(Val2);
+ assert(IndVal1->getKind() == IndVal2->getKind());
+ return &IndVal1->getPointeeLoc() == &IndVal2->getPointeeLoc();
+ }
+
+ return Model.compareEquivalent(Type, *Val1, *Val2);
+}
+
Environment::Environment(DataflowAnalysisContext &DACtx,
const DeclContext &DeclCtx)
: Environment(DACtx) {
@@ -68,13 +83,40 @@ Environment::Environment(DataflowAnalysisContext &DACtx,
}
}
-bool Environment::operator==(const Environment &Other) const {
+bool Environment::equivalentTo(const Environment &Other,
+ Environment::ValueModel &Model) const {
assert(DACtx == Other.DACtx);
- return DeclToLoc == Other.DeclToLoc && LocToVal == Other.LocToVal;
+
+ if (DeclToLoc != Other.DeclToLoc)
+ return false;
+
+ if (ExprToLoc != Other.ExprToLoc)
+ return false;
+
+ if (LocToVal.size() != Other.LocToVal.size())
+ return false;
+
+ for (auto &Entry : LocToVal) {
+ const StorageLocation *Loc = Entry.first;
+ assert(Loc != nullptr);
+
+ Value *Val = Entry.second;
+ assert(Val != nullptr);
+
+ auto It = Other.LocToVal.find(Loc);
+ if (It == Other.LocToVal.end())
+ return false;
+ assert(It->second != nullptr);
+
+ if (!equivalentValues(Loc->getType(), Val, It->second, Model))
+ return false;
+ }
+
+ return true;
}
LatticeJoinEffect Environment::join(const Environment &Other,
- Environment::Merger &Merger) {
+ Environment::ValueModel &Model) {
assert(DACtx == Other.DACtx);
auto Effect = LatticeJoinEffect::Unchanged;
@@ -89,8 +131,12 @@ LatticeJoinEffect Environment::join(const Environment &Other,
if (ExprToLocSizeBefore != ExprToLoc.size())
Effect = LatticeJoinEffect::Changed;
- llvm::DenseMap<const StorageLocation *, Value *> MergedLocToVal;
- for (auto &Entry : LocToVal) {
+ // Move `LocToVal` so that `Environment::ValueModel::merge` can safely assign
+ // values to storage locations while this code iterates over the current
+ // assignments.
+ llvm::DenseMap<const StorageLocation *, Value *> OldLocToVal =
+ std::move(LocToVal);
+ for (auto &Entry : OldLocToVal) {
const StorageLocation *Loc = Entry.first;
assert(Loc != nullptr);
@@ -102,20 +148,19 @@ LatticeJoinEffect Environment::join(const Environment &Other,
continue;
assert(It->second != nullptr);
- if (It->second == Val) {
- MergedLocToVal.insert({Loc, Val});
+ if (equivalentValues(Loc->getType(), Val, It->second, Model)) {
+ LocToVal.insert({Loc, Val});
continue;
}
- // FIXME: Consider destroying `MergedValue` immediately if `Merger::merge`
- // returns false to avoid storing unneeded values in `DACtx`.
+ // FIXME: Consider destroying `MergedValue` immediately if
+ // `ValueModel::merge` returns false to avoid storing unneeded values in
+ // `DACtx`.
if (Value *MergedVal = createValue(Loc->getType()))
- if (Merger.merge(Loc->getType(), *Val, *It->second, *MergedVal, *this))
- MergedLocToVal.insert({Loc, MergedVal});
+ if (Model.merge(Loc->getType(), *Val, *It->second, *MergedVal, *this))
+ LocToVal.insert({Loc, MergedVal});
}
- const unsigned LocToValSizeBefore = LocToVal.size();
- LocToVal = std::move(MergedLocToVal);
- if (LocToValSizeBefore != LocToVal.size())
+ if (OldLocToVal.size() != LocToVal.size())
Effect = LatticeJoinEffect::Changed;
return Effect;
diff --git a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
index aaf6a834f5b3..6b14b5ceaf69 100644
--- a/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
+++ b/clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include <memory>
+#include <system_error>
#include <utility>
#include <vector>
@@ -26,7 +27,7 @@
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Error.h"
namespace clang {
namespace dataflow {
@@ -190,7 +191,7 @@ TypeErasedDataflowAnalysisState transferBlock(
return State;
}
-std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>>
+llvm::Expected<std::vector<llvm::Optional<TypeErasedDataflowAnalysisState>>>
runTypeErasedDataflowAnalysis(const ControlFlowContext &CFCtx,
TypeErasedDataflowAnalysis &Analysis,
const Environment &InitEnv) {
@@ -216,8 +217,8 @@ runTypeErasedDataflowAnalysis(const ControlFlowContext &CFCtx,
static constexpr uint32_t MaxIterations = 1 << 16;
while (const CFGBlock *Block = Worklist.dequeue()) {
if (++Iterations > MaxIterations) {
- llvm::errs() << "Maximum number of iterations reached, giving up.\n";
- break;
+ return llvm::createStringError(std::errc::timed_out,
+ "maximum number of iterations reached");
}
const llvm::Optional<TypeErasedDataflowAnalysisState> &OldBlockState =
@@ -228,7 +229,7 @@ runTypeErasedDataflowAnalysis(const ControlFlowContext &CFCtx,
if (OldBlockState.hasValue() &&
Analysis.isEqualTypeErased(OldBlockState.getValue().Lattice,
NewBlockState.Lattice) &&
- OldBlockState->Env == NewBlockState.Env) {
+ OldBlockState->Env.equivalentTo(NewBlockState.Env, Analysis)) {
// The state of `Block` didn't change after transfer so there's no need to
// revisit its successors.
continue;