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