1ae60884dSStanislav Gatev //===- unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp -------===//
2ae60884dSStanislav Gatev //
3ae60884dSStanislav Gatev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4ae60884dSStanislav Gatev // See https://llvm.org/LICENSE.txt for license information.
5ae60884dSStanislav Gatev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ae60884dSStanislav Gatev //
7ae60884dSStanislav Gatev //===----------------------------------------------------------------------===//
8ae60884dSStanislav Gatev 
9ae60884dSStanislav Gatev #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
103dd7877bSStanislav Gatev #include "TestingSupport.h"
11ae60884dSStanislav Gatev #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
12*32dcb759SSam Estep #include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
1318c84e2dSYitzhak Mandelbaum #include "clang/Analysis/FlowSensitive/Value.h"
14ae60884dSStanislav Gatev #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
15ae60884dSStanislav Gatev #include "gmock/gmock.h"
16ae60884dSStanislav Gatev #include "gtest/gtest.h"
17ae60884dSStanislav Gatev #include <memory>
18ae60884dSStanislav Gatev 
19ae60884dSStanislav Gatev namespace {
20ae60884dSStanislav Gatev 
21ae60884dSStanislav Gatev using namespace clang;
22ae60884dSStanislav Gatev using namespace dataflow;
2318c84e2dSYitzhak Mandelbaum using ::testing::ElementsAre;
2418c84e2dSYitzhak Mandelbaum using ::testing::Pair;
25ae60884dSStanislav Gatev 
26ae60884dSStanislav Gatev class EnvironmentTest : public ::testing::Test {
27ae60884dSStanislav Gatev   DataflowAnalysisContext Context;
28ae60884dSStanislav Gatev 
29ae60884dSStanislav Gatev protected:
EnvironmentTest()30ae60884dSStanislav Gatev   EnvironmentTest()
31ae60884dSStanislav Gatev       : Context(std::make_unique<WatchedLiteralsSolver>()), Env(Context) {}
32ae60884dSStanislav Gatev 
33ae60884dSStanislav Gatev   Environment Env;
34ae60884dSStanislav Gatev };
35ae60884dSStanislav Gatev 
TEST_F(EnvironmentTest,FlowCondition)36ae60884dSStanislav Gatev TEST_F(EnvironmentTest, FlowCondition) {
37ae60884dSStanislav Gatev   EXPECT_TRUE(Env.flowConditionImplies(Env.getBoolLiteralValue(true)));
38ae60884dSStanislav Gatev   EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false)));
39ae60884dSStanislav Gatev 
40ae60884dSStanislav Gatev   auto &X = Env.makeAtomicBoolValue();
41ae60884dSStanislav Gatev   EXPECT_FALSE(Env.flowConditionImplies(X));
42ae60884dSStanislav Gatev 
43ae60884dSStanislav Gatev   Env.addToFlowCondition(X);
44ae60884dSStanislav Gatev   EXPECT_TRUE(Env.flowConditionImplies(X));
45ae60884dSStanislav Gatev 
46ae60884dSStanislav Gatev   auto &NotX = Env.makeNot(X);
47ae60884dSStanislav Gatev   EXPECT_FALSE(Env.flowConditionImplies(NotX));
48ae60884dSStanislav Gatev }
49ae60884dSStanislav Gatev 
TEST_F(EnvironmentTest,CreateValueRecursiveType)5018c84e2dSYitzhak Mandelbaum TEST_F(EnvironmentTest, CreateValueRecursiveType) {
5118c84e2dSYitzhak Mandelbaum   using namespace ast_matchers;
5218c84e2dSYitzhak Mandelbaum 
5318c84e2dSYitzhak Mandelbaum   std::string Code = R"cc(
5418c84e2dSYitzhak Mandelbaum     struct Recursive {
5518c84e2dSYitzhak Mandelbaum       bool X;
5618c84e2dSYitzhak Mandelbaum       Recursive *R;
5718c84e2dSYitzhak Mandelbaum     };
5818c84e2dSYitzhak Mandelbaum   )cc";
5918c84e2dSYitzhak Mandelbaum 
6018c84e2dSYitzhak Mandelbaum   auto Unit =
6118c84e2dSYitzhak Mandelbaum       tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++11"});
6218c84e2dSYitzhak Mandelbaum   auto &Context = Unit->getASTContext();
6318c84e2dSYitzhak Mandelbaum 
6418c84e2dSYitzhak Mandelbaum   ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U);
6518c84e2dSYitzhak Mandelbaum 
6618c84e2dSYitzhak Mandelbaum   auto Results =
6718c84e2dSYitzhak Mandelbaum       match(qualType(hasDeclaration(recordDecl(
6818c84e2dSYitzhak Mandelbaum                          hasName("Recursive"),
6918c84e2dSYitzhak Mandelbaum                          has(fieldDecl(hasName("R")).bind("field-r")))))
7018c84e2dSYitzhak Mandelbaum                 .bind("target"),
7118c84e2dSYitzhak Mandelbaum             Context);
7218c84e2dSYitzhak Mandelbaum   const QualType *Ty = selectFirst<QualType>("target", Results);
7318c84e2dSYitzhak Mandelbaum   const FieldDecl *R = selectFirst<FieldDecl>("field-r", Results);
7418c84e2dSYitzhak Mandelbaum   ASSERT_TRUE(Ty != nullptr && !Ty->isNull());
7518c84e2dSYitzhak Mandelbaum   ASSERT_TRUE(R != nullptr);
7618c84e2dSYitzhak Mandelbaum 
7718c84e2dSYitzhak Mandelbaum   // Verify that the struct and the field (`R`) with first appearance of the
7818c84e2dSYitzhak Mandelbaum   // type is created successfully.
7918c84e2dSYitzhak Mandelbaum   Value *Val = Env.createValue(*Ty);
8018c84e2dSYitzhak Mandelbaum   ASSERT_NE(Val, nullptr);
8118c84e2dSYitzhak Mandelbaum   StructValue *SVal = clang::dyn_cast<StructValue>(Val);
8218c84e2dSYitzhak Mandelbaum   ASSERT_NE(SVal, nullptr);
8318c84e2dSYitzhak Mandelbaum   Val = SVal->getChild(*R);
8418c84e2dSYitzhak Mandelbaum   ASSERT_NE(Val, nullptr);
8518c84e2dSYitzhak Mandelbaum   PointerValue *PV = clang::dyn_cast<PointerValue>(Val);
8618c84e2dSYitzhak Mandelbaum   EXPECT_NE(PV, nullptr);
8718c84e2dSYitzhak Mandelbaum }
8818c84e2dSYitzhak Mandelbaum 
89ae60884dSStanislav Gatev } // namespace
90