[clang] 14b039c - [clang][dataflow] Remove `declToLocConsistent()` assertion. (#69819)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 23 23:42:35 PDT 2023
Author: martinboehme
Date: 2023-10-24T08:42:30+02:00
New Revision: 14b039c1dd1e20cf7527aa717bac05133273a7dd
URL: https://github.com/llvm/llvm-project/commit/14b039c1dd1e20cf7527aa717bac05133273a7dd
DIFF: https://github.com/llvm/llvm-project/commit/14b039c1dd1e20cf7527aa717bac05133273a7dd.diff
LOG: [clang][dataflow] Remove `declToLocConsistent()` assertion. (#69819)
As described [here](https://discourse.llvm.org/t/70086/6), there are
legitimate
non-bug scenarios where two `DeclToLoc` maps to be joined contain
different
storage locations for the same declaration. This patch also adds a test
containing an example of such a situation. (The test fails without the
other
changes in this patch.)
With the assertion removed, the existing logic in `intersectDenseMaps()`
will
remove the corresponding declaration from the joined DeclToLoc map.
We also remove `removeDecl()`'s precondition (that the declaration must
be
associated with a storage location) because this may no longer hold if
the
declaration was previously removed during a join, as described above.
Added:
Modified:
clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
index 9ac2cb90ccc4d4a..33e9f0fba02bc77 100644
--- a/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
+++ b/clang/include/clang/Analysis/FlowSensitive/DataflowEnvironment.h
@@ -260,11 +260,7 @@ class Environment {
/// if `D` isn't assigned a storage location in the environment.
StorageLocation *getStorageLocation(const ValueDecl &D) const;
- /// Removes the location assigned to `D` in the environment.
- ///
- /// Requirements:
- ///
- /// `D` must have a storage location assigned in the environment.
+ /// Removes the location assigned to `D` in the environment (if any).
void removeDecl(const ValueDecl &D);
/// Assigns `Loc` as the storage location of the glvalue `E` in the
diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 01c6cc69e2b9fac..00e56ce51c530b3 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -35,20 +35,6 @@ namespace dataflow {
static constexpr int MaxCompositeValueDepth = 3;
static constexpr int MaxCompositeValueSize = 1000;
-/// Returns whether all declarations that `DeclToLoc1` and `DeclToLoc2` have in
-/// common map to the same storage location in both maps.
-bool declToLocConsistent(
- const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc1,
- const llvm::DenseMap<const ValueDecl *, StorageLocation *> &DeclToLoc2) {
- for (auto &Entry : DeclToLoc1) {
- auto It = DeclToLoc2.find(Entry.first);
- if (It != DeclToLoc2.end() && Entry.second != It->second)
- return false;
- }
-
- return true;
-}
-
/// Returns a map consisting of key-value entries that are present in both maps.
template <typename K, typename V>
llvm::DenseMap<K, V> intersectDenseMaps(const llvm::DenseMap<K, V> &Map1,
@@ -662,7 +648,6 @@ Environment Environment::join(const Environment &EnvA, const Environment &EnvB,
else
JoinedEnv.ReturnLoc = nullptr;
- assert(declToLocConsistent(EnvA.DeclToLoc, EnvB.DeclToLoc));
JoinedEnv.DeclToLoc = intersectDenseMaps(EnvA.DeclToLoc, EnvB.DeclToLoc);
JoinedEnv.ExprToLoc = intersectDenseMaps(EnvA.ExprToLoc, EnvB.ExprToLoc);
@@ -714,10 +699,7 @@ StorageLocation *Environment::getStorageLocation(const ValueDecl &D) const {
return Loc;
}
-void Environment::removeDecl(const ValueDecl &D) {
- assert(DeclToLoc.contains(&D));
- DeclToLoc.erase(&D);
-}
+void Environment::removeDecl(const ValueDecl &D) { DeclToLoc.erase(&D); }
void Environment::setStorageLocation(const Expr &E, StorageLocation &Loc) {
// `DeclRefExpr`s to builtin function types aren't glvalues, for some reason,
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index f5d9c785b63976f..0c2106777560ee6 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -6236,4 +6236,48 @@ TEST(TransferTest, LambdaCaptureThis) {
});
}
+TEST(TransferTest, DifferentReferenceLocInJoin) {
+ // This test triggers a case where the storage location for a reference-type
+ // variable is
diff erent for two states being joined. We used to believe this
+ // could not happen and therefore had an assertion disallowing this; this test
+ // exists to demonstrate that we can handle this condition without a failing
+ // assertion. See also the discussion here:
+ // https://discourse.llvm.org/t/70086/6
+ std::string Code = R"(
+ namespace std {
+ template <class T> struct initializer_list {
+ const T* begin();
+ const T* end();
+ };
+ }
+
+ void target(char* p, char* end) {
+ while (p != end) {
+ if (*p == ' ') {
+ p++;
+ continue;
+ }
+
+ auto && range = {1, 2};
+ for (auto b = range.begin(), e = range.end(); b != e; ++b) {
+ }
+ (void)0;
+ // [[p]]
+ }
+ }
+ )";
+ runDataflow(
+ Code,
+ [](const llvm::StringMap<DataflowAnalysisState<NoopLattice>> &Results,
+ ASTContext &ASTCtx) {
+ const Environment &Env = getEnvironmentAtAnnotation(Results, "p");
+
+ // Joining environments with
diff erent storage locations for the same
+ // declaration results in the declaration being removed from the joined
+ // environment.
+ const ValueDecl *VD = findValueDecl(ASTCtx, "range");
+ ASSERT_EQ(Env.getStorageLocation(*VD), nullptr);
+ });
+}
+
} // namespace
More information about the cfe-commits
mailing list