Create pointer nullability lattice.
We hope to make use of the Clang Dataflow Analysis framework to propagate nullability annotations (for example, on assignment of template-instantiated values). For this, we will alter the lattice used in pointer nullability analysis to contain maps from expressions and variable declarations to nullability annotations. This change introduces a custom lattice to the pointer nullability analysis. This lattice is still undistinguishable from a NoopLattice (we will add more functionality on a subsequent change).
PiperOrigin-RevId: 491586319
diff --git a/nullability_verification/pointer_nullability_analysis.cc b/nullability_verification/pointer_nullability_analysis.cc
index 43015f4..a2416e3 100644
--- a/nullability_verification/pointer_nullability_analysis.cc
+++ b/nullability_verification/pointer_nullability_analysis.cc
@@ -8,6 +8,7 @@
#include "absl/log/check.h"
#include "nullability_verification/pointer_nullability.h"
+#include "nullability_verification/pointer_nullability_lattice.h"
#include "nullability_verification/pointer_nullability_matchers.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
@@ -18,7 +19,6 @@
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Analysis/FlowSensitive/CFGMatchSwitch.h"
#include "clang/Analysis/FlowSensitive/DataflowEnvironment.h"
-#include "clang/Analysis/FlowSensitive/NoopLattice.h"
#include "clang/Analysis/FlowSensitive/Value.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Specifiers.h"
@@ -31,7 +31,6 @@
using dataflow::BoolValue;
using dataflow::CFGMatchSwitchBuilder;
using dataflow::Environment;
-using dataflow::NoopLattice;
using dataflow::PointerValue;
using dataflow::SkipPast;
using dataflow::TransferState;
@@ -282,7 +281,7 @@
void transferNullPointer(const Expr* NullPointer,
const MatchFinder::MatchResult&,
- TransferState<NoopLattice>& State) {
+ TransferState<PointerNullabilityLattice>& State) {
if (auto* PointerVal = getPointerValueFromExpr(NullPointer, State.Env)) {
initNullPointer(*PointerVal, State.Env);
}
@@ -290,7 +289,7 @@
void transferNotNullPointer(const Expr* NotNullPointer,
const MatchFinder::MatchResult&,
- TransferState<NoopLattice>& State) {
+ TransferState<PointerNullabilityLattice>& State) {
if (auto* PointerVal = getPointerValueFromExpr(NotNullPointer, State.Env)) {
initNotNullPointer(*PointerVal, State.Env);
}
@@ -298,7 +297,7 @@
void transferPointer(const Expr* PointerExpr,
const MatchFinder::MatchResult& Result,
- TransferState<NoopLattice>& State) {
+ TransferState<PointerNullabilityLattice>& State) {
if (auto* PointerVal = getPointerValueFromExpr(PointerExpr, State.Env)) {
initPointerFromAnnotations(*PointerVal, PointerExpr, State.Env,
*Result.Context);
@@ -308,9 +307,9 @@
// TODO(b/233582219): Implement promotion of nullability knownness for initially
// unknown pointers when there is evidence that it is nullable, for example
// when the pointer is compared to nullptr, or casted to boolean.
-void transferNullCheckComparison(const BinaryOperator* BinaryOp,
- const MatchFinder::MatchResult& result,
- TransferState<NoopLattice>& State) {
+void transferNullCheckComparison(
+ const BinaryOperator* BinaryOp, const MatchFinder::MatchResult& result,
+ TransferState<PointerNullabilityLattice>& State) {
// Boolean representing the comparison between the two pointer values,
// automatically created by the dataflow framework.
auto& PointerComparison =
@@ -349,9 +348,9 @@
State.Env.makeAnd(LHSKnownNotNull, RHSKnownNull), PointerNE));
}
-void transferNullCheckImplicitCastPtrToBool(const Expr* CastExpr,
- const MatchFinder::MatchResult&,
- TransferState<NoopLattice>& State) {
+void transferNullCheckImplicitCastPtrToBool(
+ const Expr* CastExpr, const MatchFinder::MatchResult&,
+ TransferState<PointerNullabilityLattice>& State) {
auto* PointerVal =
getPointerValueFromExpr(CastExpr->IgnoreImplicit(), State.Env);
if (!PointerVal) return;
@@ -365,7 +364,7 @@
void transferCallExpr(const CallExpr* CallExpr,
const MatchFinder::MatchResult& Result,
- TransferState<NoopLattice>& State) {
+ TransferState<PointerNullabilityLattice>& State) {
auto ReturnType = CallExpr->getType();
if (!ReturnType->isAnyPointerType()) return;
@@ -380,7 +379,7 @@
}
auto buildTransferer() {
- return CFGMatchSwitchBuilder<TransferState<NoopLattice>>()
+ return CFGMatchSwitchBuilder<TransferState<PointerNullabilityLattice>>()
// Handles initialization of the null states of pointers.
.CaseOfCFGStmt<Expr>(isPointerVariableReference(), transferPointer)
.CaseOfCFGStmt<Expr>(isCXXThisExpr(), transferNotNullPointer)
@@ -399,13 +398,14 @@
} // namespace
PointerNullabilityAnalysis::PointerNullabilityAnalysis(ASTContext& Context)
- : DataflowAnalysis<PointerNullabilityAnalysis, NoopLattice>(Context),
+ : DataflowAnalysis<PointerNullabilityAnalysis, PointerNullabilityLattice>(
+ Context),
Transferer(buildTransferer()) {}
void PointerNullabilityAnalysis::transfer(const CFGElement* Elt,
- NoopLattice& Lattice,
+ PointerNullabilityLattice& Lattice,
Environment& Env) {
- TransferState<NoopLattice> State(Lattice, Env);
+ TransferState<PointerNullabilityLattice> State(Lattice, Env);
Transferer(*Elt, getASTContext(), State);
}