1 //===- unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
10 #include "TestingSupport.h"
11 #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
12 #include "clang/Analysis/FlowSensitive/NoopAnalysis.h"
13 #include "clang/Analysis/FlowSensitive/Value.h"
14 #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
15 #include "gmock/gmock.h"
16 #include "gtest/gtest.h"
17 #include <memory>
18
19 namespace {
20
21 using namespace clang;
22 using namespace dataflow;
23 using ::testing::ElementsAre;
24 using ::testing::Pair;
25
26 class EnvironmentTest : public ::testing::Test {
27 DataflowAnalysisContext Context;
28
29 protected:
EnvironmentTest()30 EnvironmentTest()
31 : Context(std::make_unique<WatchedLiteralsSolver>()), Env(Context) {}
32
33 Environment Env;
34 };
35
TEST_F(EnvironmentTest,FlowCondition)36 TEST_F(EnvironmentTest, FlowCondition) {
37 EXPECT_TRUE(Env.flowConditionImplies(Env.getBoolLiteralValue(true)));
38 EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false)));
39
40 auto &X = Env.makeAtomicBoolValue();
41 EXPECT_FALSE(Env.flowConditionImplies(X));
42
43 Env.addToFlowCondition(X);
44 EXPECT_TRUE(Env.flowConditionImplies(X));
45
46 auto &NotX = Env.makeNot(X);
47 EXPECT_FALSE(Env.flowConditionImplies(NotX));
48 }
49
TEST_F(EnvironmentTest,CreateValueRecursiveType)50 TEST_F(EnvironmentTest, CreateValueRecursiveType) {
51 using namespace ast_matchers;
52
53 std::string Code = R"cc(
54 struct Recursive {
55 bool X;
56 Recursive *R;
57 };
58 )cc";
59
60 auto Unit =
61 tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++11"});
62 auto &Context = Unit->getASTContext();
63
64 ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U);
65
66 auto Results =
67 match(qualType(hasDeclaration(recordDecl(
68 hasName("Recursive"),
69 has(fieldDecl(hasName("R")).bind("field-r")))))
70 .bind("target"),
71 Context);
72 const QualType *Ty = selectFirst<QualType>("target", Results);
73 const FieldDecl *R = selectFirst<FieldDecl>("field-r", Results);
74 ASSERT_TRUE(Ty != nullptr && !Ty->isNull());
75 ASSERT_TRUE(R != nullptr);
76
77 // Verify that the struct and the field (`R`) with first appearance of the
78 // type is created successfully.
79 Value *Val = Env.createValue(*Ty);
80 ASSERT_NE(Val, nullptr);
81 StructValue *SVal = clang::dyn_cast<StructValue>(Val);
82 ASSERT_NE(SVal, nullptr);
83 Val = SVal->getChild(*R);
84 ASSERT_NE(Val, nullptr);
85 PointerValue *PV = clang::dyn_cast<PointerValue>(Val);
86 EXPECT_NE(PV, nullptr);
87 }
88
89 } // namespace
90