forked from google/crubit
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpointer_nullability_lattice_test.cc
More file actions
95 lines (78 loc) · 3.01 KB
/
pointer_nullability_lattice_test.cc
File metadata and controls
95 lines (78 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// 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/pointer_nullability_lattice.h"
#include <cassert>
#include <memory>
#include "absl/base/nullability.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Type.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
#include "clang/Analysis/FlowSensitive/DataflowLattice.h"
#include "clang/Analysis/FlowSensitive/StorageLocation.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "clang/Analysis/FlowSensitive/WatchedLiteralsSolver.h"
#include "clang/Basic/LLVM.h"
#include "clang/Testing/TestAST.h"
#include "external/llvm-project/third-party/unittest/googletest/include/gtest/gtest.h"
namespace clang::tidy::nullability {
namespace {
using ast_matchers::callee;
using ast_matchers::cxxMemberCallExpr;
using ast_matchers::functionDecl;
using ast_matchers::hasName;
using ast_matchers::match;
using ast_matchers::selectFirst;
using dataflow::DataflowAnalysisContext;
using dataflow::Environment;
using dataflow::LatticeJoinEffect;
using dataflow::RecordStorageLocation;
using dataflow::Value;
using dataflow::WatchedLiteralsSolver;
NamedDecl *absl_nonnull lookup(StringRef Name, const DeclContext &DC) {
auto Result = DC.lookup(&DC.getParentASTContext().Idents.get(Name));
EXPECT_TRUE(Result.isSingleResult()) << Name;
return Result.front();
}
class PointerNullabilityLatticeTest : public ::testing::Test {
protected:
DataflowAnalysisContext DACtx{std::make_unique<WatchedLiteralsSolver>()};
Environment Env{DACtx};
PointerNullabilityLattice::NonFlowSensitiveState NFS;
};
TEST_F(PointerNullabilityLatticeTest, ConstMethodProducesNewValueAfterJoin) {
TestAST AST(R"cpp(
struct S {
int *property() const;
};
void target() {
S s;
s.property();
}
)cpp");
auto *SDecl =
cast<CXXRecordDecl>(lookup("S", *AST.context().getTranslationUnitDecl()));
QualType SType = AST.context().getRecordType(SDecl);
auto *CE = selectFirst<CallExpr>(
"call", match(cxxMemberCallExpr(callee(functionDecl(hasName("property"))))
.bind("call"),
AST.context()));
assert(CE != nullptr);
RecordStorageLocation Loc(SType, RecordStorageLocation::FieldToLoc(), {});
PointerNullabilityLattice Lattice1(NFS);
Value *Val1 = Lattice1.getOrCreateConstMethodReturnValue(Loc, CE, Env);
PointerNullabilityLattice Lattice2(NFS);
Value *Val2 = Lattice2.getOrCreateConstMethodReturnValue(Loc, CE, Env);
EXPECT_EQ(Lattice1.join(Lattice2), LatticeJoinEffect::Changed);
Value *ValAfterJoin =
Lattice1.getOrCreateConstMethodReturnValue(Loc, CE, Env);
EXPECT_NE(ValAfterJoin, Val1);
EXPECT_NE(ValAfterJoin, Val2);
}
} // namespace
} // namespace clang::tidy::nullability