blob: 6d21f9907a5d4900f990c910acc216419815dae7 [file]
// Part of the Crubit project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "nullability/inference/resolve_constraints.h"
#include <memory>
#include "nullability/inference/inference.proto.h"
#include "nullability/pointer_nullability.h"
#include "nullability/proto_matchers.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
#include "llvm/ADT/DenseSet.h"
#include "third_party/llvm/llvm-project/third-party/unittest/googlemock/include/gmock/gmock.h"
#include "third_party/llvm/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h"
namespace clang::tidy::nullability {
namespace {
class ResolveConstraintsTest : public testing::Test {
public:
ResolveConstraintsTest()
: StorageLocation(clang::dataflow::StorageLocation::Kind::Scalar,
clang::QualType()),
Pointer(StorageLocation),
DataflowAnalysisContext(
std::make_unique<clang::dataflow::WatchedLiteralsSolver>()),
Environment(DataflowAnalysisContext) {
initUnknownPointer(Pointer, Environment);
}
clang::dataflow::StorageLocation StorageLocation;
clang::dataflow::PointerValue Pointer;
clang::dataflow::DataflowAnalysisContext DataflowAnalysisContext;
clang::dataflow::Environment Environment;
};
TEST_F(ResolveConstraintsTest, EmptyConstraintsDoNotImplyNonNull) {
const llvm::DenseSet<clang::dataflow::BoolValue *> Constraints;
EXPECT_FALSE(resolveConstraints(Constraints, Pointer).must_be_nonnull());
}
TEST_F(ResolveConstraintsTest, ArbitraryBooleanConstraintsDoNotImplyNonNull) {
auto &A = Environment.arena();
auto &Atom1 = A.makeAtomValue();
auto &Atom2 = A.makeAtomValue();
const llvm::DenseSet<clang::dataflow::BoolValue *> Constraints = {&Atom1,
&Atom2};
EXPECT_FALSE(resolveConstraints(Constraints, Pointer).must_be_nonnull());
}
TEST_F(ResolveConstraintsTest, UnsatisfiableConstraintsProducesDefaultValues) {
auto &A = Environment.arena();
auto &Atom1 = A.makeAtomValue();
auto &NotAtom1 = A.makeBoolValue(A.makeNot(Atom1.formula()));
const llvm::DenseSet<clang::dataflow::BoolValue *> Constraints = {&Atom1,
&NotAtom1};
EXPECT_THAT(resolveConstraints(Constraints, Pointer), EqualsProto(""));
}
TEST_F(ResolveConstraintsTest, NotIsNullConstraintImpliesNonNull) {
auto &A = Environment.arena();
auto &is_null = getPointerNullState(Pointer).second;
auto &not_is_null = A.makeBoolValue(A.makeNot(is_null.formula()));
const llvm::DenseSet<clang::dataflow::BoolValue *> Constraints = {
&not_is_null};
EXPECT_TRUE(resolveConstraints(Constraints, Pointer).must_be_nonnull());
}
} // namespace
} // namespace clang::tidy::nullability