Annotate pointers in crubit/nullability Abseil nullability annotations.
PiperOrigin-RevId: 589849354
Change-Id: I741ec99392ad9e35870032df6f1d36e3986a7b23
diff --git a/nullability/BUILD b/nullability/BUILD
index 5c4e7af..e5f3721 100644
--- a/nullability/BUILD
+++ b/nullability/BUILD
@@ -12,6 +12,7 @@
],
deps = [
":type_nullability",
+ "@absl//absl/base:nullability",
"@absl//absl/container:flat_hash_map",
"@absl//absl/log:check",
"@llvm-project//clang:analysis",
@@ -62,6 +63,7 @@
":pointer_nullability_lattice",
":pointer_nullability_matchers",
":type_nullability",
+ "@absl//absl/base:nullability",
"@absl//absl/log:check",
"@llvm-project//clang:analysis",
"@llvm-project//clang:ast",
@@ -77,13 +79,12 @@
deps = [
":pointer_nullability",
":pointer_nullability_analysis",
- ":pointer_nullability_lattice",
+ "@absl//absl/base:nullability",
"@llvm-project//clang:analysis",
"@llvm-project//clang:ast",
"@llvm-project//clang:basic",
"@llvm-project//clang:testing",
"@llvm-project//llvm:Support",
- "@llvm-project//third-party/unittest:gmock",
"@llvm-project//third-party/unittest:gtest",
"@llvm-project//third-party/unittest:gtest_main",
],
@@ -99,6 +100,7 @@
":pointer_nullability_lattice",
":pointer_nullability_matchers",
":type_nullability",
+ "@absl//absl/base:nullability",
"@absl//absl/log:check",
"@llvm-project//clang:analysis",
"@llvm-project//clang:ast",
@@ -150,6 +152,7 @@
"//nullability/test:__pkg__",
],
deps = [
+ "@absl//absl/base:nullability",
"@absl//absl/log:check",
"@llvm-project//clang:analysis",
"@llvm-project//clang:ast",
@@ -182,6 +185,7 @@
visibility = [":__subpackages__"],
deps = [
"//third_party/protobuf",
+ "@absl//absl/base:nullability",
"@llvm-project//llvm:Support",
"@llvm-project//third-party/unittest:gmock",
],
@@ -195,6 +199,7 @@
":pointer_nullability_analysis",
":pointer_nullability_diagnosis",
"//third_party/benchmark",
+ "@absl//absl/base:nullability",
"@absl//absl/log:check",
"@absl//absl/strings",
"@absl//absl/strings:string_view",
diff --git a/nullability/inference/BUILD b/nullability/inference/BUILD
index f249345..452feea 100644
--- a/nullability/inference/BUILD
+++ b/nullability/inference/BUILD
@@ -16,6 +16,7 @@
"//nullability:pointer_nullability_analysis",
"//nullability:pointer_nullability_lattice",
"//nullability:type_nullability",
+ "@absl//absl/base:nullability",
"@absl//absl/container:flat_hash_map",
"@absl//absl/log:check",
"@llvm-project//clang:analysis",
@@ -191,6 +192,7 @@
deps = [
":infer_tu",
":inference_cc_proto",
+ "@absl//absl/base:nullability",
"@absl//absl/log:check",
"@llvm-project//clang:ast",
"@llvm-project//clang:basic",
diff --git a/nullability/inference/collect_evidence.cc b/nullability/inference/collect_evidence.cc
index 7c55917..212b1b2 100644
--- a/nullability/inference/collect_evidence.cc
+++ b/nullability/inference/collect_evidence.cc
@@ -11,6 +11,7 @@
#include <utility>
#include <vector>
+#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/log/check.h"
#include "nullability/inference/inferable.h"
@@ -242,7 +243,8 @@
}
auto getNullabilityAnnotationsFromTypeAndOverrides(
- QualType Type, const Decl *D, const PointerNullabilityLattice &Lattice) {
+ QualType Type, absl::Nonnull<const Decl *> D,
+ const PointerNullabilityLattice &Lattice) {
auto N = getNullabilityAnnotationsFromType(Type);
if (N.empty()) {
// We expect this not to be the case, but not to a crash-worthy level, so
@@ -788,7 +790,7 @@
// We do want to see concrete code, including function instantiations.
bool shouldVisitTemplateInstantiations() const { return true; }
- bool VisitFunctionDecl(const FunctionDecl *FD) {
+ bool VisitFunctionDecl(absl::Nonnull<const FunctionDecl *> FD) {
if (isInferenceTarget(*FD)) Out.Declarations.push_back(FD);
// Visiting template instantiations is fine, these are valid functions!
diff --git a/nullability/inference/infer_tu_main.cc b/nullability/inference/infer_tu_main.cc
index 656d125..67c5ac2 100644
--- a/nullability/inference/infer_tu_main.cc
+++ b/nullability/inference/infer_tu_main.cc
@@ -14,6 +14,7 @@
#include <string>
#include <utility>
+#include "absl/base/nullability.h"
#include "absl/log/check.h"
#include "nullability/inference/infer_tu.h"
#include "nullability/inference/inference.proto.h"
@@ -84,7 +85,8 @@
// Walks the AST looking for declarations of symbols we inferred.
// When it finds them, prints the inference as diagnostics.
class DiagnosticPrinter : public RecursiveASTVisitor<DiagnosticPrinter> {
- llvm::DenseMap<llvm::StringRef, const Inference *> InferenceByUSR;
+ llvm::DenseMap<llvm::StringRef, absl::Nonnull<const Inference *>>
+ InferenceByUSR;
DiagnosticsEngine &Diags;
unsigned DiagInferHere;
unsigned DiagSample;
@@ -130,7 +132,7 @@
DiagSample = Diags.getCustomDiagID(DiagnosticsEngine::Note, "%0 here");
}
- bool VisitDecl(const Decl *FD) {
+ bool VisitDecl(absl::Nonnull<const Decl *> FD) {
llvm::SmallString<128> USR;
if (!index::generateUSRForDecl(FD, USR))
if (auto *I = InferenceByUSR.lookup(USR)) render(*I, FD->getLocation());
@@ -185,8 +187,8 @@
};
class Action : public SyntaxOnlyAction {
- std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &,
- llvm::StringRef) override {
+ absl::Nonnull<std::unique_ptr<ASTConsumer>> CreateASTConsumer(
+ CompilerInstance &, llvm::StringRef) override {
class Consumer : public ASTConsumer {
void HandleTranslationUnit(ASTContext &Ctx) override {
llvm::errs() << "Running inference...\n";
@@ -212,7 +214,7 @@
} // namespace
} // namespace clang::tidy::nullability
-int main(int argc, const char **argv) {
+int main(int argc, absl::Nonnull<const char **> argv) {
using namespace clang::tooling;
auto Exec = createExecutorFromCommandLineArgs(argc, argv, Opts);
QCHECK(Exec) << toString(Exec.takeError());
diff --git a/nullability/pointer_nullability.cc b/nullability/pointer_nullability.cc
index 93cac80..15ea94c 100644
--- a/nullability/pointer_nullability.cc
+++ b/nullability/pointer_nullability.cc
@@ -7,6 +7,7 @@
#include <cassert>
#include <optional>
+#include "absl/base/nullability.h"
#include "nullability/type_nullability.h"
#include "clang/AST/Type.h"
#include "clang/Analysis/FlowSensitive/DataflowAnalysisContext.h"
@@ -40,8 +41,8 @@
return Type->getNullability().value_or(NullabilityKind::Unspecified);
}
-PointerValue *getPointerValueFromExpr(const Expr *PointerExpr,
- const Environment &Env) {
+absl::Nullable<PointerValue *> getPointerValueFromExpr(
+ absl::Nonnull<const Expr *> PointerExpr, const Environment &Env) {
return cast_or_null<PointerValue>(Env.getValue(*PointerExpr));
}
@@ -88,10 +89,10 @@
};
}
-static bool tryCreatePointerNullState(PointerValue &PointerVal,
- dataflow::Arena &A,
- const Formula *FromNullable = nullptr,
- const Formula *IsNull = nullptr) {
+static bool tryCreatePointerNullState(
+ PointerValue &PointerVal, dataflow::Arena &A,
+ absl::Nullable<const Formula *> FromNullable = nullptr,
+ absl::Nullable<const Formula *> IsNull = nullptr) {
if (hasPointerNullState(PointerVal)) return false;
if (!FromNullable) FromNullable = &A.makeAtomRef(A.makeAtom());
if (!IsNull) IsNull = &A.makeAtomRef(A.makeAtom());
@@ -140,8 +141,9 @@
return PointerVal;
}
-bool isNullable(const PointerValue &PointerVal, const Environment &Env,
- const dataflow::Formula *AdditionalConstraints) {
+bool isNullable(
+ const PointerValue &PointerVal, const Environment &Env,
+ absl::Nullable<const dataflow::Formula *> AdditionalConstraints) {
auto &A = Env.getDataflowAnalysisContext().arena();
auto [FromNullable, Null] = getPointerNullState(PointerVal);
@@ -159,9 +161,9 @@
return Env.allows(*ForseeablyNull);
}
-NullabilityKind getNullability(const dataflow::PointerValue &PointerVal,
- const dataflow::Environment &Env,
- const dataflow::Formula *AdditionalConstraints) {
+NullabilityKind getNullability(
+ const dataflow::PointerValue &PointerVal, const dataflow::Environment &Env,
+ absl::Nullable<const dataflow::Formula *> AdditionalConstraints) {
auto &A = Env.getDataflowAnalysisContext().arena();
if (auto *Null = getPointerNullState(PointerVal).IsNull) {
if (AdditionalConstraints) Null = &A.makeAnd(*AdditionalConstraints, *Null);
diff --git a/nullability/pointer_nullability.h b/nullability/pointer_nullability.h
index f1c12ef..4032549 100644
--- a/nullability/pointer_nullability.h
+++ b/nullability/pointer_nullability.h
@@ -36,8 +36,8 @@
/// Returns the `PointerValue` allocated to `PointerExpr` if available.
/// Otherwise, returns nullptr.
-dataflow::PointerValue *getPointerValueFromExpr(
- const Expr *PointerExpr, const dataflow::Environment &Env);
+absl::Nullable<dataflow::PointerValue *> getPointerValueFromExpr(
+ absl::Nonnull<const Expr *> PointerExpr, const dataflow::Environment &Env);
/// Returns the `PointerValue` underlying a smart pointer, or null if no
/// `PointerValue` is assigned to the smart pointer in the environment.
@@ -133,9 +133,9 @@
dataflow::Environment &Env);
/// Returns true if there is evidence that `PointerVal` may hold a nullptr.
-bool isNullable(const dataflow::PointerValue &PointerVal,
- const dataflow::Environment &Env,
- const dataflow::Formula *AdditionalConstraints = nullptr);
+bool isNullable(
+ const dataflow::PointerValue &PointerVal, const dataflow::Environment &Env,
+ absl::Nullable<const dataflow::Formula *> AdditionalConstraints = nullptr);
/// Returns the strongest provable assertion we can make about `PointerVal`.
/// If PointerVal may not be null, returns Nonnull.
@@ -143,13 +143,13 @@
/// Otherwise, returns Unspecified.
clang::NullabilityKind getNullability(
const dataflow::PointerValue &PointerVal, const dataflow::Environment &Env,
- const dataflow::Formula *AdditionalConstraints = nullptr);
+ absl::Nullable<const dataflow::Formula *> AdditionalConstraints = nullptr);
/// Returns the strongest provable assertion we can make about the value of
/// `E` in `Env`.
clang::NullabilityKind getNullability(
- const Expr *E, const dataflow::Environment &Env,
- const dataflow::Formula *AdditionalConstraints = nullptr);
+ absl::Nonnull<const Expr *> E, const dataflow::Environment &Env,
+ absl::Nullable<const dataflow::Formula *> AdditionalConstraints = nullptr);
// Work around the lack of Expr.dump() etc with an ostream but no ASTContext.
template <typename T>
diff --git a/nullability/pointer_nullability_analysis.cc b/nullability/pointer_nullability_analysis.cc
index 85212c0..31bdedf 100644
--- a/nullability/pointer_nullability_analysis.cc
+++ b/nullability/pointer_nullability_analysis.cc
@@ -9,6 +9,7 @@
#include <optional>
#include <vector>
+#include "absl/base/nullability.h"
#include "absl/log/check.h"
#include "nullability/pointer_nullability.h"
#include "nullability/pointer_nullability_lattice.h"
@@ -63,7 +64,7 @@
return Result;
}
-void computeNullability(const Expr *E,
+void computeNullability(absl::Nonnull<const Expr *> E,
TransferState<PointerNullabilityLattice> &State,
std::function<TypeNullability()> Compute) {
(void)State.Lattice.insertExprNullabilityIfAbsent(E, [&] {
@@ -96,7 +97,8 @@
// Returns the computed nullability for a subexpr of the current expression.
// This is always available as we compute bottom-up.
const TypeNullability &getNullabilityForChild(
- const Expr *E, TransferState<PointerNullabilityLattice> &State) {
+ absl::Nonnull<const Expr *> E,
+ TransferState<PointerNullabilityLattice> &State) {
return State.Lattice.insertExprNullabilityIfAbsent(E, [&] {
// Since we process child nodes before parents, we should already have
// computed the child nullability. However, this is not true in all test
@@ -214,7 +216,7 @@
/// the given type after applying substitutions, which in this case is
/// [_Nullable, _Nonnull].
TypeNullability substituteNullabilityAnnotationsInFunctionTemplate(
- QualType T, const CallExpr *CE) {
+ QualType T, absl::Nonnull<const CallExpr *> CE) {
return getNullabilityAnnotationsFromType(
T,
[&](const SubstTemplateTypeParmType *ST)
@@ -254,7 +256,7 @@
}
PointerTypeNullability getPointerTypeNullability(
- const Expr *E, PointerNullabilityAnalysis::Lattice &L) {
+ absl::Nonnull<const Expr *> E, PointerNullabilityAnalysis::Lattice &L) {
// TODO: handle this in non-flow-sensitive transfer instead
if (auto FromClang = E->getType()->getNullability();
FromClang && *FromClang != NullabilityKind::Unspecified)
@@ -270,7 +272,7 @@
}
void initPointerFromTypeNullability(
- PointerValue &PointerVal, const Expr *E,
+ PointerValue &PointerVal, absl::Nonnull<const Expr *> E,
TransferState<PointerNullabilityLattice> &State) {
initPointerNullState(PointerVal, State.Env.getDataflowAnalysisContext(),
getPointerTypeNullability(E, State.Lattice));
@@ -282,7 +284,8 @@
/// TODO(mboehme): When we add support for smart pointers, this function will
/// also need to be called when accessing the `PointerValue` that underlies the
/// smart pointer.
-PointerValue *unpackPointerValue(PointerValue &PointerVal, Environment &Env) {
+absl::Nullable<PointerValue *> unpackPointerValue(PointerValue &PointerVal,
+ Environment &Env) {
auto [FromNullable, Null] = getPointerNullState(PointerVal);
if (FromNullable && Null) return nullptr;
@@ -309,7 +312,7 @@
}
void transferValue_NullPointer(
- const Expr *NullPointer, const MatchFinder::MatchResult &,
+ absl::Nonnull<const Expr *> NullPointer, const MatchFinder::MatchResult &,
TransferState<PointerNullabilityLattice> &State) {
if (auto *PointerVal = getPointerValueFromExpr(NullPointer, State.Env)) {
initNullPointer(*PointerVal, State.Env.getDataflowAnalysisContext());
@@ -317,7 +320,8 @@
}
void transferValue_NotNullPointer(
- const Expr *NotNullPointer, const MatchFinder::MatchResult &,
+ absl::Nonnull<const Expr *> NotNullPointer,
+ const MatchFinder::MatchResult &,
TransferState<PointerNullabilityLattice> &State) {
if (auto *PointerVal = getPointerValueFromExpr(NotNullPointer, State.Env)) {
initPointerNullState(*PointerVal, State.Env.getDataflowAnalysisContext(),
@@ -527,7 +531,7 @@
initPointerFromTypeNullability(*Val, PointerExpr, State);
}
-void transferValue_Pointer(const Expr *PointerExpr,
+void transferValue_Pointer(absl::Nonnull<const Expr *> PointerExpr,
const MatchFinder::MatchResult &Result,
TransferState<PointerNullabilityLattice> &State) {
auto *PointerVal = getPointerValueFromExpr(PointerExpr, State.Env);
@@ -550,7 +554,8 @@
// unknown pointers when there is evidence that it is nullable, for example
// when the pointer is compared to nullptr, or casted to boolean.
void transferValue_NullCheckComparison(
- const BinaryOperator *BinaryOp, const MatchFinder::MatchResult &result,
+ absl::Nonnull<const BinaryOperator *> BinaryOp,
+ const MatchFinder::MatchResult &result,
TransferState<PointerNullabilityLattice> &State) {
auto &A = State.Env.arena();
@@ -613,7 +618,7 @@
}
void transferValue_NullCheckImplicitCastPtrToBool(
- const Expr *CastExpr, const MatchFinder::MatchResult &,
+ absl::Nonnull<const Expr *> CastExpr, const MatchFinder::MatchResult &,
TransferState<PointerNullabilityLattice> &State) {
auto &A = State.Env.arena();
auto *PointerVal =
@@ -628,8 +633,8 @@
State.Env.setValue(*CastExpr, A.makeTopValue());
}
-void initializeOutputParameter(const Expr *Arg, dataflow::Environment &Env,
- QualType ParamTy) {
+void initializeOutputParameter(absl::Nonnull<const Expr *> Arg,
+ dataflow::Environment &Env, QualType ParamTy) {
// When a function has an "output parameter" - a non-const pointer or
// reference to a pointer of unknown nullability - assume that the function
// may set the pointer to non-null.
@@ -672,7 +677,7 @@
Env.setValue(*Loc, *InnerPointer);
}
-void transferValue_CallExpr(const CallExpr *CallExpr,
+void transferValue_CallExpr(absl::Nonnull<const CallExpr *> CallExpr,
const MatchFinder::MatchResult &Result,
TransferState<PointerNullabilityLattice> &State) {
// The dataflow framework itself does not create values for `CallExpr`s.
@@ -727,7 +732,8 @@
}
void transferValue_AccessorCall(
- const CXXMemberCallExpr *MCE, const MatchFinder::MatchResult &Result,
+ absl::Nonnull<const CXXMemberCallExpr *> MCE,
+ const MatchFinder::MatchResult &Result,
TransferState<PointerNullabilityLattice> &State) {
auto *member = Result.Nodes.getNodeAs<clang::ValueDecl>("member-decl");
PointerValue *PointerVal = nullptr;
@@ -748,7 +754,8 @@
}
void transferValue_ConstMemberCall(
- const CXXMemberCallExpr *MCE, const MatchFinder::MatchResult &Result,
+ absl::Nonnull<const CXXMemberCallExpr *> MCE,
+ const MatchFinder::MatchResult &Result,
TransferState<PointerNullabilityLattice> &State) {
if (!isSupportedRawPointerType(MCE->getType()) || !MCE->isPRValue()) {
// We can't handle it as a special case, but still need to handle it.
@@ -771,7 +778,8 @@
}
void transferValue_NonConstMemberCall(
- const CXXMemberCallExpr *MCE, const MatchFinder::MatchResult &Result,
+ absl::Nonnull<const CXXMemberCallExpr *> MCE,
+ const MatchFinder::MatchResult &Result,
TransferState<PointerNullabilityLattice> &State) {
// When a non-const member function is called, reset all pointer-type fields
// of the implicit object.
@@ -788,7 +796,7 @@
transferValue_CallExpr(MCE, Result, State);
}
-void transferType_DeclRefExpr(const DeclRefExpr *DRE,
+void transferType_DeclRefExpr(absl::Nonnull<const DeclRefExpr *> DRE,
const MatchFinder::MatchResult &MR,
TransferState<PointerNullabilityLattice> &State) {
computeNullability(DRE, State, [&] {
@@ -798,7 +806,7 @@
});
}
-void transferType_MemberExpr(const MemberExpr *ME,
+void transferType_MemberExpr(absl::Nonnull<const MemberExpr *> ME,
const MatchFinder::MatchResult &MR,
TransferState<PointerNullabilityLattice> &State) {
computeNullability(ME, State, [&]() {
@@ -822,7 +830,8 @@
}
void transferType_MemberCallExpr(
- const CXXMemberCallExpr *MCE, const MatchFinder::MatchResult &MR,
+ absl::Nonnull<const CXXMemberCallExpr *> MCE,
+ const MatchFinder::MatchResult &MR,
TransferState<PointerNullabilityLattice> &State) {
computeNullability(MCE, State, [&]() {
return ArrayRef(getNullabilityForChild(MCE->getCallee(), State))
@@ -831,7 +840,7 @@
});
}
-void transferType_CastExpr(const CastExpr *CE,
+void transferType_CastExpr(absl::Nonnull<const CastExpr *> CE,
const MatchFinder::MatchResult &MR,
TransferState<PointerNullabilityLattice> &State) {
computeNullability(CE, State, [&]() -> TypeNullability {
@@ -972,7 +981,8 @@
}
void transferType_MaterializeTemporaryExpr(
- const MaterializeTemporaryExpr *MTE, const MatchFinder::MatchResult &MR,
+ absl::Nonnull<const MaterializeTemporaryExpr *> MTE,
+ const MatchFinder::MatchResult &MR,
TransferState<PointerNullabilityLattice> &State) {
computeNullability(MTE, State, [&]() {
return getNullabilityForChild(MTE->getSubExpr(), State);
@@ -987,7 +997,7 @@
});
}
-void transferType_CallExpr(const CallExpr *CE,
+void transferType_CallExpr(absl::Nonnull<const CallExpr *> CE,
const MatchFinder::MatchResult &MR,
TransferState<PointerNullabilityLattice> &State) {
// TODO: Check CallExpr arguments in the diagnoser against the nullability of
@@ -1007,7 +1017,7 @@
}
void transferType_UnaryOperator(
- const UnaryOperator *UO, const MatchFinder::MatchResult &MR,
+ absl::Nonnull<const UnaryOperator *> UO, const MatchFinder::MatchResult &MR,
TransferState<PointerNullabilityLattice> &State) {
computeNullability(UO, State, [&]() -> TypeNullability {
switch (UO->getOpcode()) {
@@ -1039,7 +1049,7 @@
});
}
-void transferType_NewExpr(const CXXNewExpr *NE,
+void transferType_NewExpr(absl::Nonnull<const CXXNewExpr *> NE,
const MatchFinder::MatchResult &MR,
TransferState<PointerNullabilityLattice> &State) {
computeNullability(NE, State, [&]() {
@@ -1051,7 +1061,8 @@
}
void transferType_ArraySubscriptExpr(
- const ArraySubscriptExpr *ASE, const MatchFinder::MatchResult &MR,
+ absl::Nonnull<const ArraySubscriptExpr *> ASE,
+ const MatchFinder::MatchResult &MR,
TransferState<PointerNullabilityLattice> &State) {
computeNullability(ASE, State, [&]() {
auto &BaseNullability = getNullabilityForChild(ASE->getBase(), State);
@@ -1063,7 +1074,7 @@
});
}
-void transferType_ThisExpr(const CXXThisExpr *TE,
+void transferType_ThisExpr(absl::Nonnull<const CXXThisExpr *> TE,
const MatchFinder::MatchResult &MR,
TransferState<PointerNullabilityLattice> &State) {
computeNullability(TE, State, [&]() {
@@ -1184,7 +1195,7 @@
}
PointerTypeNullability PointerNullabilityAnalysis::assignNullabilityVariable(
- const ValueDecl *D, dataflow::Arena &A) {
+ absl::Nonnull<const ValueDecl *> D, dataflow::Arena &A) {
auto [It, Inserted] = NFS.DeclTopLevelNullability.try_emplace(D);
if (Inserted) It->second = PointerTypeNullability::createSymbolic(A);
return It->second;
@@ -1200,11 +1211,10 @@
ValueTransferer(Elt, getASTContext(), State);
}
-static const Formula *mergeFormulas(const Formula *Bool1,
- const Environment &Env1,
- const Formula *Bool2,
- const Environment &Env2,
- Environment &MergedEnv) {
+static absl::Nullable<const Formula *> mergeFormulas(
+ absl::Nullable<const Formula *> Bool1, const Environment &Env1,
+ absl::Nullable<const Formula *> Bool2, const Environment &Env2,
+ Environment &MergedEnv) {
if (Bool1 == Bool2) {
return Bool1;
}
@@ -1321,10 +1331,9 @@
// returns `Cur`, as this is the formula that is appropriate to use in the
// current environment (where we will produce the widened pointer). Otherwise,
// returns null, to indicate that the property should be widened to "top".
-static const Formula *widenNullabilityProperty(const Formula *Prev,
- const Environment &PrevEnv,
- const Formula *Cur,
- Environment &CurEnv) {
+static absl::Nullable<const Formula *> widenNullabilityProperty(
+ absl::Nullable<const Formula *> Prev, const Environment &PrevEnv,
+ absl::Nullable<const Formula *> Cur, Environment &CurEnv) {
if (Prev == Cur) return Cur;
if (Prev == nullptr || Cur == nullptr) return nullptr;
@@ -1340,10 +1349,9 @@
return nullptr;
}
-Value *PointerNullabilityAnalysis::widen(QualType Type, Value &Prev,
- const Environment &PrevEnv,
- Value &Current,
- Environment &CurrentEnv) {
+absl::Nullable<Value *> PointerNullabilityAnalysis::widen(
+ QualType Type, Value &Prev, const Environment &PrevEnv, Value &Current,
+ Environment &CurrentEnv) {
// Widen pointers to a pointer with a "top" storage location.
if (auto *PrevPtr = dyn_cast<PointerValue>(&Prev)) {
auto &CurPtr = cast<PointerValue>(Current);
diff --git a/nullability/pointer_nullability_analysis.h b/nullability/pointer_nullability_analysis.h
index bdf9358..9275397 100644
--- a/nullability/pointer_nullability_analysis.h
+++ b/nullability/pointer_nullability_analysis.h
@@ -8,6 +8,7 @@
#include <optional>
#include <utility>
+#include "absl/base/nullability.h"
#include "nullability/pointer_nullability_lattice.h"
#include "nullability/type_nullability.h"
#include "clang/AST/ASTContext.h"
@@ -67,8 +68,8 @@
// variables are only associated with direct reads of pointer values from D.
//
// The returned nullability is guaranteed to be symbolic.
- PointerTypeNullability assignNullabilityVariable(const ValueDecl *D,
- dataflow::Arena &);
+ PointerTypeNullability assignNullabilityVariable(
+ absl::Nonnull<const ValueDecl *> D, dataflow::Arena &);
void assignNullabilityOverride(
llvm::unique_function<
@@ -90,10 +91,10 @@
const dataflow::Environment &Env1, const dataflow::Value &Val2,
const dataflow::Environment &Env2) override;
- dataflow::Value *widen(QualType Type, dataflow::Value &Prev,
- const dataflow::Environment &PrevEnv,
- dataflow::Value &Current,
- dataflow::Environment &CurrentEnv) override;
+ absl::Nullable<dataflow::Value *> widen(
+ QualType Type, dataflow::Value &Prev,
+ const dataflow::Environment &PrevEnv, dataflow::Value &Current,
+ dataflow::Environment &CurrentEnv) override;
private:
// Returns a storage location representing "top", i.e. a storage location of
diff --git a/nullability/pointer_nullability_analysis_benchmark.cc b/nullability/pointer_nullability_analysis_benchmark.cc
index eba9461..7e1de00 100644
--- a/nullability/pointer_nullability_analysis_benchmark.cc
+++ b/nullability/pointer_nullability_analysis_benchmark.cc
@@ -4,6 +4,7 @@
#include <cstdint>
+#include "absl/base/nullability.h"
#include "absl/log/check.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
@@ -20,7 +21,8 @@
namespace clang::tidy::nullability {
namespace {
-NamedDecl *lookup(absl::string_view Name, const DeclContext &DC) {
+absl::Nonnull<NamedDecl *> lookup(absl::string_view Name,
+ const DeclContext &DC) {
auto Result = DC.lookup(&DC.getParentASTContext().Idents.get(Name));
CHECK(Result.isSingleResult()) << Name;
return Result.front();
@@ -222,7 +224,7 @@
} // namespace
} // namespace clang::tidy::nullability
-int main(int argc, char **argv) {
+int main(int argc, absl::Nonnull<char **> argv) {
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
return 0;
diff --git a/nullability/pointer_nullability_analysis_test.cc b/nullability/pointer_nullability_analysis_test.cc
index 9c3d846..fa0011f 100644
--- a/nullability/pointer_nullability_analysis_test.cc
+++ b/nullability/pointer_nullability_analysis_test.cc
@@ -8,6 +8,7 @@
#include <optional>
#include <utility>
+#include "absl/base/nullability.h"
#include "nullability/pointer_nullability.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
@@ -26,7 +27,7 @@
namespace clang::tidy::nullability {
namespace {
-NamedDecl *lookup(StringRef Name, const DeclContext &DC) {
+absl::Nonnull<NamedDecl *> lookup(StringRef Name, const DeclContext &DC) {
auto Result = DC.lookup(&DC.getParentASTContext().Idents.get(Name));
EXPECT_TRUE(Result.isSingleResult()) << Name;
return Result.front();
diff --git a/nullability/pointer_nullability_diagnosis.cc b/nullability/pointer_nullability_diagnosis.cc
index c9b6b2e..b089f05 100644
--- a/nullability/pointer_nullability_diagnosis.cc
+++ b/nullability/pointer_nullability_diagnosis.cc
@@ -6,6 +6,7 @@
#include <optional>
+#include "absl/base/nullability.h"
#include "absl/log/check.h"
#include "nullability/pointer_nullability.h"
#include "nullability/pointer_nullability_matchers.h"
@@ -40,7 +41,7 @@
// Diagnoses whether `E` violates the expectation that it is nonnull.
SmallVector<PointerNullabilityDiagnostic> diagnoseNonnullExpected(
- const Expr *E, const Environment &Env,
+ absl::Nonnull<const Expr *> E, const Environment &Env,
PointerNullabilityDiagnostic::Context DiagCtx,
std::optional<std::string> ParamName = std::nullopt) {
if (auto *ActualVal = getPointerValueFromExpr(E, Env)) {
@@ -66,8 +67,9 @@
// Diagnoses whether the nullability of `E` is incompatible with the expectation
// set by `DeclaredType`.
SmallVector<PointerNullabilityDiagnostic> diagnoseTypeExprCompatibility(
- QualType DeclaredType, const Expr *E, const Environment &Env,
- ASTContext &Ctx, PointerNullabilityDiagnostic::Context DiagCtx,
+ QualType DeclaredType, absl::Nonnull<const Expr *> E,
+ const Environment &Env, ASTContext &Ctx,
+ PointerNullabilityDiagnostic::Context DiagCtx,
std::optional<std::string> ParamName = std::nullopt) {
CHECK(isSupportedRawPointerType(DeclaredType));
return getNullabilityKind(DeclaredType, Ctx) == NullabilityKind::NonNull
@@ -76,7 +78,8 @@
}
SmallVector<PointerNullabilityDiagnostic> diagnoseDereference(
- const UnaryOperator *UnaryOp, const MatchFinder::MatchResult &,
+ absl::Nonnull<const UnaryOperator *> UnaryOp,
+ const MatchFinder::MatchResult &,
const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
return diagnoseNonnullExpected(
UnaryOp->getSubExpr(), State.Env,
@@ -84,7 +87,8 @@
}
SmallVector<PointerNullabilityDiagnostic> diagnoseArrow(
- const MemberExpr *MemberExpr, const MatchFinder::MatchResult &Result,
+ absl::Nonnull<const MemberExpr *> MemberExpr,
+ const MatchFinder::MatchResult &Result,
const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
return diagnoseNonnullExpected(
MemberExpr->getBase(), State.Env,
@@ -161,7 +165,7 @@
/// }
/// \endcode
SmallVector<PointerNullabilityDiagnostic> diagnoseAssertNullabilityCall(
- const CallExpr *CE,
+ absl::Nonnull<const CallExpr *> CE,
const TransferStateForDiagnostics<PointerNullabilityLattice> &State,
ASTContext &Ctx) {
auto *DRE = cast<DeclRefExpr>(CE->getCallee()->IgnoreImpCasts());
@@ -207,7 +211,7 @@
}
SmallVector<PointerNullabilityDiagnostic> diagnoseCallExpr(
- const CallExpr *CE, const MatchFinder::MatchResult &Result,
+ absl::Nonnull<const CallExpr *> CE, const MatchFinder::MatchResult &Result,
const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
// Check whether the callee is null.
// - Skip direct callees to avoid handling builtin functions, which don't
@@ -270,7 +274,8 @@
}
SmallVector<PointerNullabilityDiagnostic> diagnoseConstructExpr(
- const CXXConstructExpr *CE, const MatchFinder::MatchResult &Result,
+ absl::Nonnull<const CXXConstructExpr *> CE,
+ const MatchFinder::MatchResult &Result,
const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
auto *CalleeFPT = CE->getConstructor()->getType()->getAs<FunctionProtoType>();
if (!CalleeFPT) return {};
@@ -283,7 +288,8 @@
}
SmallVector<PointerNullabilityDiagnostic> diagnoseReturn(
- const ReturnStmt *RS, const MatchFinder::MatchResult &Result,
+ absl::Nonnull<const ReturnStmt *> RS,
+ const MatchFinder::MatchResult &Result,
const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
auto ReturnType = cast<FunctionDecl>(State.Env.getDeclCtx())->getReturnType();
@@ -301,7 +307,8 @@
}
SmallVector<PointerNullabilityDiagnostic> diagnoseMemberInitializer(
- const CXXCtorInitializer *CI, const MatchFinder::MatchResult &Result,
+ absl::Nonnull<const CXXCtorInitializer *> CI,
+ const MatchFinder::MatchResult &Result,
const TransferStateForDiagnostics<PointerNullabilityLattice> &State) {
CHECK(CI->isAnyMemberInitializer());
auto MemberType = CI->getAnyMember()->getType();
diff --git a/nullability/pointer_nullability_lattice.cc b/nullability/pointer_nullability_lattice.cc
index abab6ab..e2d0c03 100644
--- a/nullability/pointer_nullability_lattice.cc
+++ b/nullability/pointer_nullability_lattice.cc
@@ -6,6 +6,7 @@
#include <optional>
+#include "absl/base/nullability.h"
#include "absl/log/check.h"
#include "nullability/type_nullability.h"
#include "clang/AST/Decl.h"
@@ -17,8 +18,8 @@
// Returns overridden nullability information associated with a declaration.
// For now we only track top-level decl nullability symbolically and check for
// concrete nullability override results.
-const PointerTypeNullability *getDeclNullability(
- const Decl *D,
+absl::Nullable<const PointerTypeNullability *> getDeclNullability(
+ absl::Nullable<const Decl *> D,
const PointerNullabilityLattice::NonFlowSensitiveState &NFS) {
if (!D) return nullptr;
if (const auto *VD = dyn_cast_or_null<ValueDecl>(D)) {
@@ -33,7 +34,7 @@
} // namespace
void PointerNullabilityLattice::overrideNullabilityFromDecl(
- const Decl *D, TypeNullability &N) const {
+ absl::Nullable<const Decl *> D, TypeNullability &N) const {
// For now, overrides are always for pointer values only, and override only
// the top-level nullability.
if (auto *PN = getDeclNullability(D, NFS)) {
diff --git a/nullability/pointer_nullability_lattice.h b/nullability/pointer_nullability_lattice.h
index 6457ca5..898e55f 100644
--- a/nullability/pointer_nullability_lattice.h
+++ b/nullability/pointer_nullability_lattice.h
@@ -9,6 +9,7 @@
#include <optional>
#include <ostream>
+#include "absl/base/nullability.h"
#include "absl/container/flat_hash_map.h"
#include "absl/log/check.h"
#include "nullability/type_nullability.h"
@@ -31,7 +32,8 @@
// These are set by PointerNullabilityAnalysis::assignNullabilityVariable,
// and take precedence over the declared type and over any result from
// ConcreteNullabilityOverride.
- absl::flat_hash_map<const ValueDecl *, PointerTypeNullability>
+ absl::flat_hash_map<absl::Nonnull<const ValueDecl *>,
+ PointerTypeNullability>
DeclTopLevelNullability;
// Returns overriding concrete nullability for decls. This is set by
// PointerNullabilityAnalysis::assignNullabilityOverride, and the result, if
@@ -43,7 +45,8 @@
PointerNullabilityLattice(NonFlowSensitiveState &NFS) : NFS(NFS) {}
- const TypeNullability *getExprNullability(const Expr *E) const {
+ absl::Nullable<const TypeNullability *> getExprNullability(
+ absl::Nonnull<const Expr *> E) const {
auto I = NFS.ExprToNullability.find(&dataflow::ignoreCFGOmittedNodes(*E));
return I == NFS.ExprToNullability.end() ? nullptr : &I->second;
}
@@ -53,7 +56,8 @@
// the provided GetNullability.
// Returns the (cached or computed) nullability.
const TypeNullability &insertExprNullabilityIfAbsent(
- const Expr *E, const std::function<TypeNullability()> &GetNullability) {
+ absl::Nonnull<const Expr *> E,
+ const std::function<TypeNullability()> &GetNullability) {
E = &dataflow::ignoreCFGOmittedNodes(*E);
if (auto It = NFS.ExprToNullability.find(E);
It != NFS.ExprToNullability.end())
@@ -69,9 +73,10 @@
// Gets the PointerValue associated with the RecordStorageLocation and
// MethodDecl of the CallExpr, creating one if it doesn't yet exist. Requires
// the CXXMemberCallExpr to have a supported pointer type.
- dataflow::PointerValue *getConstMethodReturnValue(
+ absl::Nonnull<dataflow::PointerValue *> getConstMethodReturnValue(
const dataflow::RecordStorageLocation &RecordLoc,
- const CXXMemberCallExpr *MCE, dataflow::Environment &Env) {
+ absl::Nonnull<const CXXMemberCallExpr *> MCE,
+ dataflow::Environment &Env) {
auto &ObjMap = ConstMethodReturnValues[&RecordLoc];
auto it = ObjMap.find(MCE->getMethodDecl());
if (it != ObjMap.end()) return it->second;
@@ -87,7 +92,8 @@
// If nullability for the decl D has been overridden, patch N to reflect it.
// (N is the nullability of an access to D).
- void overrideNullabilityFromDecl(const Decl *D, TypeNullability &N) const;
+ void overrideNullabilityFromDecl(absl::Nullable<const Decl *> D,
+ TypeNullability &N) const;
bool operator==(const PointerNullabilityLattice &Other) const { return true; }
diff --git a/nullability/proto_matchers.cc b/nullability/proto_matchers.cc
index 87f02fd..5059958 100644
--- a/nullability/proto_matchers.cc
+++ b/nullability/proto_matchers.cc
@@ -8,6 +8,7 @@
#include <ostream>
#include <string>
+#include "absl/base/nullability.h"
#include "llvm/ADT/StringRef.h"
#include "third_party/llvm/llvm-project/third-party/unittest/googlemock/include/gmock/gmock.h"
#include "third_party/protobuf/message.h"
@@ -23,8 +24,9 @@
public:
EqualsProtoMatcher(llvm::StringRef Expected) : Expected(Expected) {}
- bool MatchAndExplain(const proto2::Message &M,
- testing::MatchResultListener *Listener) const override {
+ bool MatchAndExplain(
+ const proto2::Message &M,
+ absl::Nonnull<testing::MatchResultListener *> Listener) const override {
std::unique_ptr<proto2::Message> Parsed(M.New());
if (!proto2::TextFormat::ParseFromString(Expected, Parsed.get())) {
*Listener << "where <<<\n"
@@ -45,7 +47,7 @@
Listener);
}
- void DescribeTo(std::ostream *OS) const override {
+ void DescribeTo(absl::Nonnull<std::ostream *> OS) const override {
*OS << "equals proto <<<\n" << Expected << "\n>>>";
}
};
diff --git a/nullability/type_nullability.cc b/nullability/type_nullability.cc
index 0d6447a..132ddc7 100644
--- a/nullability/type_nullability.cc
+++ b/nullability/type_nullability.cc
@@ -9,6 +9,7 @@
#include <utility>
#include <vector>
+#include "absl/base/nullability.h"
#include "absl/log/check.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTFwd.h"
@@ -299,7 +300,7 @@
if (TA.getKind() == TemplateArgument::Pack)
for (const auto &PackElt : TA.getPackAsArray()) Visit(PackElt);
}
- void Visit(const DeclContext *DC) {
+ void Visit(absl::Nonnull<const DeclContext *> DC) {
// For now, only consider enclosing classes.
// TODO: The nullability of template functions can affect local classes too,
// this can be relevant e.g. when instantiating templates with such types.
@@ -307,7 +308,7 @@
Visit(DC->getParentASTContext().getRecordType(CRD));
}
- void VisitType(const Type *T) {
+ void VisitType(absl::Nonnull<const Type *> T) {
// For sugar not explicitly handled below, desugar and continue.
// (We need to walk the full structure of the canonical type.)
if (auto *Desugar =
@@ -321,13 +322,14 @@
Base::VisitType(T);
}
- void VisitFunctionProtoType(const FunctionProtoType *FPT) {
+ void VisitFunctionProtoType(absl::Nonnull<const FunctionProtoType *> FPT) {
ignoreUnexpectedNullability();
Visit(FPT->getReturnType());
for (auto ParamType : FPT->getParamTypes()) Visit(ParamType);
}
- void VisitTemplateSpecializationType(const TemplateSpecializationType *TST) {
+ void VisitTemplateSpecializationType(
+ absl::Nonnull<const TemplateSpecializationType *> TST) {
if (TST->isTypeAlias()) {
if (auto NK = getAliasNullability(TST->getTemplateName()))
sawNullability(*NK);
@@ -372,7 +374,8 @@
}
}
- void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
+ void VisitSubstTemplateTypeParmType(
+ absl::Nonnull<const SubstTemplateTypeParmType *> T) {
// The underlying type of T in the AST has no sugar, as the template has
// only one body instantiated per canonical args.
// Instead, try to find the (sugared) template argument that T is bound to.
@@ -410,7 +413,7 @@
}
// If we see foo<args>::ty then we may need sugar from args to resugar ty.
- void VisitElaboratedType(const ElaboratedType *ET) {
+ void VisitElaboratedType(absl::Nonnull<const ElaboratedType *> ET) {
std::vector<TemplateContext> BoundTemplateArgs;
// Iterate over qualifiers right-to-left, looking for template args.
for (auto *NNS = ET->getQualifier(); NNS; NNS = NNS->getPrefix()) {
@@ -445,7 +448,7 @@
Visit(ET->getNamedType());
}
- void VisitRecordType(const RecordType *RT) {
+ void VisitRecordType(absl::Nonnull<const RecordType *> RT) {
if (isSupportedSmartPointerType(QualType(RT, 0))) {
derived().report(
RT, PendingNullability.value_or(NullabilityKind::Unspecified));
@@ -461,7 +464,7 @@
}
}
- void VisitAttributedType(const AttributedType *AT) {
+ void VisitAttributedType(absl::Nonnull<const AttributedType *> AT) {
if (auto NK = AT->getImmediateNullability()) sawNullability(*NK);
Visit(AT->getModifiedType());
CHECK(!PendingNullability.has_value())
@@ -469,50 +472,55 @@
<< AT->getModifiedType().getAsString();
}
- void VisitPointerType(const PointerType *PT) {
+ void VisitPointerType(absl::Nonnull<const PointerType *> PT) {
derived().report(PT,
PendingNullability.value_or(NullabilityKind::Unspecified));
PendingNullability.reset();
Visit(PT->getPointeeType());
}
- void VisitReferenceType(const ReferenceType *RT) {
+ void VisitReferenceType(absl::Nonnull<const ReferenceType *> RT) {
ignoreUnexpectedNullability();
Visit(RT->getPointeeTypeAsWritten());
}
- void VisitArrayType(const ArrayType *AT) {
+ void VisitArrayType(absl::Nonnull<const ArrayType *> AT) {
ignoreUnexpectedNullability();
Visit(AT->getElementType());
}
};
-template <typename T>
-unsigned countPointers(const T &Object) {
- struct Walker : public NullabilityWalker<Walker> {
- unsigned Count = 0;
- void report(const Type *, NullabilityKind) { ++Count; }
- } PointerCountWalker;
- PointerCountWalker.Visit(Object);
+struct CountWalker : public NullabilityWalker<CountWalker> {
+ unsigned Count = 0;
+ void report(absl::Nonnull<const Type *>, NullabilityKind) { ++Count; }
+};
+} // namespace
+
+unsigned countPointersInType(QualType T) {
+ CountWalker PointerCountWalker;
+ PointerCountWalker.Visit(T);
return PointerCountWalker.Count;
}
-} // namespace
-
-unsigned countPointersInType(QualType T) { return countPointers(T); }
-
-unsigned countPointersInType(const DeclContext *DC) {
- return countPointers(DC);
+unsigned countPointersInType(absl::Nonnull<const DeclContext *> DC) {
+ CountWalker PointerCountWalker;
+ PointerCountWalker.Visit(DC);
+ return PointerCountWalker.Count;
}
-unsigned countPointersInType(TemplateArgument TA) { return countPointers(TA); }
-QualType exprType(const Expr *E) {
+unsigned countPointersInType(const TemplateArgument &TA) {
+ CountWalker PointerCountWalker;
+ PointerCountWalker.Visit(TA);
+ return PointerCountWalker.Count;
+}
+
+QualType exprType(absl::Nonnull<const Expr *> E) {
if (E->hasPlaceholderType(BuiltinType::BoundMember))
return Expr::findBoundMemberType(E);
return E->getType();
}
-unsigned countPointersInType(const Expr *E) {
+unsigned countPointersInType(absl::Nonnull<const Expr *> E) {
return countPointersInType(exprType(E));
}
@@ -520,13 +528,17 @@
QualType T,
llvm::function_ref<GetTypeParamNullability> SubstituteTypeParam) {
CHECK(!T->isDependentType()) << T.getAsString();
+
struct Walker : NullabilityWalker<Walker> {
std::vector<PointerTypeNullability> Annotations;
llvm::function_ref<GetTypeParamNullability> SubstituteTypeParam;
- void report(const Type *, NullabilityKind NK) { Annotations.push_back(NK); }
+ void report(absl::Nonnull<const Type *>, NullabilityKind NK) {
+ Annotations.push_back(NK);
+ }
- void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *ST) {
+ void VisitSubstTemplateTypeParmType(
+ absl::Nonnull<const SubstTemplateTypeParmType *> ST) {
if (SubstituteTypeParam) {
if (auto Subst = SubstituteTypeParam(ST)) {
DCHECK_EQ(Subst->size(),
@@ -540,12 +552,13 @@
NullabilityWalker::VisitSubstTemplateTypeParmType(ST);
}
} AnnotationVisitor;
+
AnnotationVisitor.SubstituteTypeParam = SubstituteTypeParam;
AnnotationVisitor.Visit(T);
return std::move(AnnotationVisitor.Annotations);
}
-TypeNullability unspecifiedNullability(const Expr *E) {
+TypeNullability unspecifiedNullability(absl::Nonnull<const Expr *> E) {
return TypeNullability(countPointersInType(E), NullabilityKind::Unspecified);
}
@@ -582,9 +595,9 @@
}
// Default behavior for unhandled types: do not transform.
- QualType VisitType(const Type *T) { return QualType(T, 0); }
+ QualType VisitType(absl::Nonnull<const Type *> T) { return QualType(T, 0); }
- QualType VisitPointerType(const PointerType *PT) {
+ QualType VisitPointerType(absl::Nonnull<const PointerType *> PT) {
CHECK(!Nullability.empty())
<< "Nullability vector too short at " << QualType(PT, 0).getAsString();
NullabilityKind NK = Nullability.front().concrete();
@@ -596,7 +609,7 @@
Rebuilt, Rebuilt);
}
- QualType VisitRecordType(const RecordType *RT) {
+ QualType VisitRecordType(absl::Nonnull<const RecordType *> RT) {
if (const auto *CTSD =
dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl())) {
std::vector<TemplateArgument> TransformedArgs;
@@ -609,31 +622,34 @@
return QualType(RT, 0);
}
- QualType VisitFunctionProtoType(const FunctionProtoType *T) {
+ QualType VisitFunctionProtoType(absl::Nonnull<const FunctionProtoType *> T) {
QualType Ret = Visit(T->getReturnType());
std::vector<QualType> Params;
for (const auto &Param : T->getParamTypes()) Params.push_back(Visit(Param));
return Ctx.getFunctionType(Ret, Params, T->getExtProtoInfo());
}
- QualType VisitLValueReferenceType(const LValueReferenceType *T) {
+ QualType VisitLValueReferenceType(
+ absl::Nonnull<const LValueReferenceType *> T) {
return Ctx.getLValueReferenceType(Visit(T->getPointeeType()));
}
- QualType VisitRValueReferenceType(const RValueReferenceType *T) {
+ QualType VisitRValueReferenceType(
+ absl::Nonnull<const RValueReferenceType *> T) {
return Ctx.getRValueReferenceType(Visit(T->getPointeeType()));
}
- QualType VisitConstantArrayType(const ConstantArrayType *AT) {
+ QualType VisitConstantArrayType(absl::Nonnull<const ConstantArrayType *> AT) {
return Ctx.getConstantArrayType(Visit(AT->getElementType()), AT->getSize(),
AT->getSizeExpr(), AT->getSizeModifier(),
AT->getIndexTypeCVRQualifiers());
}
- QualType VisitIncompleteArrayType(const IncompleteArrayType *AT) {
+ QualType VisitIncompleteArrayType(
+ absl::Nonnull<const IncompleteArrayType *> AT) {
return Ctx.getIncompleteArrayType(Visit(AT->getElementType()),
AT->getSizeModifier(),
AT->getIndexTypeCVRQualifiers());
}
- QualType VisitVariableArrayType(const VariableArrayType *AT) {
+ QualType VisitVariableArrayType(absl::Nonnull<const VariableArrayType *> AT) {
return Ctx.getVariableArrayType(
Visit(AT->getElementType()), AT->getSizeExpr(), AT->getSizeModifier(),
AT->getIndexTypeCVRQualifiers(), AT->getBracketsRange());
diff --git a/nullability/type_nullability.h b/nullability/type_nullability.h
index bbd8421..3eac9e7 100644
--- a/nullability/type_nullability.h
+++ b/nullability/type_nullability.h
@@ -30,6 +30,7 @@
#include <tuple>
#include <vector>
+#include "absl/base/nullability.h"
#include "absl/log/check.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
@@ -191,15 +192,15 @@
/// Each of these could conceptually be nullable, so this is the length of
/// the nullability vector computed by getNullabilityAnnotationsFromType().
unsigned countPointersInType(QualType T);
-unsigned countPointersInType(const Expr *E);
-unsigned countPointersInType(TemplateArgument TA);
-unsigned countPointersInType(const DeclContext *DC);
+unsigned countPointersInType(absl::Nonnull<const Expr *> E);
+unsigned countPointersInType(const TemplateArgument &TA);
+unsigned countPointersInType(absl::Nonnull<const DeclContext *> DC);
/// Returns the type of an expression for the purposes of nullability.
/// This handles wrinkles in the type system like BoundMember.
-QualType exprType(const Expr *E);
+QualType exprType(absl::Nonnull<const Expr *> E);
-TypeNullability unspecifiedNullability(const Expr *E);
+TypeNullability unspecifiedNullability(absl::Nonnull<const Expr *> E);
} // namespace clang::tidy::nullability