//===- unittests/Analysis/FlowSensitive/DataflowEnvironmentTest.cpp -------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/Analysis/FlowSensitive/DataflowEnvironment.h" #include "TestingSupport.h" #include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h" #include "clang/Analysis/FlowSensitive/NoopAnalysis.h" #include "clang/Analysis/FlowSensitive/Value.h" #include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include namespace { using namespace clang; using namespace dataflow; using ::testing::ElementsAre; using ::testing::Pair; class EnvironmentTest : public ::testing::Test { DataflowAnalysisContext Context; protected: EnvironmentTest() : Context(std::make_unique()), Env(Context) {} Environment Env; }; TEST_F(EnvironmentTest, FlowCondition) { EXPECT_TRUE(Env.flowConditionImplies(Env.getBoolLiteralValue(true))); EXPECT_FALSE(Env.flowConditionImplies(Env.getBoolLiteralValue(false))); auto &X = Env.makeAtomicBoolValue(); EXPECT_FALSE(Env.flowConditionImplies(X)); Env.addToFlowCondition(X); EXPECT_TRUE(Env.flowConditionImplies(X)); auto &NotX = Env.makeNot(X); EXPECT_FALSE(Env.flowConditionImplies(NotX)); } TEST_F(EnvironmentTest, CreateValueRecursiveType) { using namespace ast_matchers; std::string Code = R"cc( struct Recursive { bool X; Recursive *R; }; )cc"; auto Unit = tooling::buildASTFromCodeWithArgs(Code, {"-fsyntax-only", "-std=c++11"}); auto &Context = Unit->getASTContext(); ASSERT_EQ(Context.getDiagnostics().getClient()->getNumErrors(), 0U); auto Results = match(qualType(hasDeclaration(recordDecl( hasName("Recursive"), has(fieldDecl(hasName("R")).bind("field-r"))))) .bind("target"), Context); const QualType *Ty = selectFirst("target", Results); const FieldDecl *R = selectFirst("field-r", Results); ASSERT_TRUE(Ty != nullptr && !Ty->isNull()); ASSERT_TRUE(R != nullptr); // Verify that the struct and the field (`R`) with first appearance of the // type is created successfully. Value *Val = Env.createValue(*Ty); ASSERT_NE(Val, nullptr); StructValue *SVal = clang::dyn_cast(Val); ASSERT_NE(SVal, nullptr); Val = SVal->getChild(*R); ASSERT_NE(Val, nullptr); PointerValue *PV = clang::dyn_cast(Val); EXPECT_NE(PV, nullptr); } } // namespace