90 lines
2.7 KiB
C++
90 lines
2.7 KiB
C++
//===- 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 <memory>
|
|
|
|
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<WatchedLiteralsSolver>()), 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<QualType>("target", Results);
|
|
const FieldDecl *R = selectFirst<FieldDecl>("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<StructValue>(Val);
|
|
ASSERT_NE(SVal, nullptr);
|
|
Val = SVal->getChild(*R);
|
|
ASSERT_NE(Val, nullptr);
|
|
PointerValue *PV = clang::dyn_cast<PointerValue>(Val);
|
|
EXPECT_NE(PV, nullptr);
|
|
}
|
|
|
|
} // namespace
|