aboutsummaryrefslogtreecommitdiff
path: root/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp')
-rw-r--r--clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp43
1 files changed, 43 insertions, 0 deletions
diff --git a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
index 465a8e2..cc20623 100644
--- a/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp
@@ -24,6 +24,7 @@ namespace {
using namespace clang;
using namespace dataflow;
+using ::clang::dataflow::test::findValueDecl;
using ::clang::dataflow::test::getFieldValue;
using ::testing::Contains;
using ::testing::IsNull;
@@ -199,6 +200,48 @@ TEST_F(EnvironmentTest, JoinRecords) {
}
}
+TEST_F(EnvironmentTest, DifferentReferenceLocInJoin) {
+ // This tests the case where the storage location for a reference-type
+ // variable is different 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
+
+ using namespace ast_matchers;
+
+ std::string Code = R"cc(
+ void f(int &ref) {}
+ )cc";
+
+ auto Unit =
+ tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++11"});
+ auto &Context = Unit->getASTContext();
+
+ ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U);
+
+ const ValueDecl *Ref = findValueDecl(Context, "ref");
+
+ Environment Env1(DAContext);
+ StorageLocation &Loc1 = Env1.createStorageLocation(Context.IntTy);
+ Env1.setStorageLocation(*Ref, Loc1);
+
+ Environment Env2(DAContext);
+ StorageLocation &Loc2 = Env2.createStorageLocation(Context.IntTy);
+ Env2.setStorageLocation(*Ref, Loc2);
+
+ EXPECT_NE(&Loc1, &Loc2);
+
+ Environment::ValueModel Model;
+ Environment EnvJoined =
+ Environment::join(Env1, Env2, Model, Environment::DiscardExprState);
+
+ // Joining environments with different storage locations for the same
+ // declaration results in the declaration being removed from the joined
+ // environment.
+ EXPECT_EQ(EnvJoined.getStorageLocation(*Ref), nullptr);
+}
+
TEST_F(EnvironmentTest, InitGlobalVarsFun) {
using namespace ast_matchers;