diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2022-02-05 18:04:23 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2022-02-05 18:05:05 +0000 |
| commit | ecbca9f5fb7d7613d2b94982c4825eb0d33d6842 (patch) | |
| tree | 3a4038f3b7bafaeade9fd6146ea8021237616657 /clang/lib/Analysis | |
| parent | 6f8fc217eaa12bf657be1c6468ed9938d10168b3 (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.cpp | 73 | ||||
| -rw-r--r-- | clang/lib/Analysis/FlowSensitive/TypeErasedDataflowAnalysis.cpp | 11 |
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; |
