[clang] [NFC][analyzer] Multipart checker refactor 2: NullabilityChecker (PR #132250)
DonĂ¡t Nagy via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 20 10:03:00 PDT 2025
https://github.com/NagyDonat updated https://github.com/llvm/llvm-project/pull/132250
>From d4878a62a69304dc2ae32902803f8c8efb1c69ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Thu, 20 Mar 2025 17:09:46 +0100
Subject: [PATCH 1/3] [NFC][analyzer] Multipart checker refactor 2:
NullabilityChecker
Simplify `NullabilityChecker.cpp` with new multipart checker framework
introduced in 27099982da2f5a6c2d282d6b385e79d080669546. This is part of
a commit series that will perform analogous changes in all checker
classes that implement multiple user-facing checker parts (with separate
names).
---
.../Checkers/NullabilityChecker.cpp | 157 +++++++++---------
1 file changed, 81 insertions(+), 76 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index 04472bb3895a7..8fe7d21ca7984 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -112,25 +112,38 @@ class NullabilityChecker
void printState(raw_ostream &Out, ProgramStateRef State, const char *NL,
const char *Sep) const override;
- enum CheckKind {
- CK_NullPassedToNonnull,
- CK_NullReturnedFromNonnull,
- CK_NullableDereferenced,
- CK_NullablePassedToNonnull,
- CK_NullableReturnedFromNonnull,
- CK_NumCheckKinds
+ // FIXME: This enumeration of checker parts is extremely similar to the
+ // ErrorKind enum. It would be nice to unify them to simplify the code.
+ // FIXME: The modeling checker NullabilityBase is a dummy "empty checker
+ // part" that registers this checker class without enabling any of the real
+ // checker parts. As far as I understand no other checker references it, so
+ // it should be removed.
+ enum : CheckerPartIdx {
+ NullabilityBase,
+ NullPassedToNonnullChecker,
+ NullReturnedFromNonnullChecker,
+ NullableDereferencedChecker,
+ NullablePassedToNonnullChecker,
+ NullableReturnedFromNonnullChecker,
+ NumCheckerParts
};
- bool ChecksEnabled[CK_NumCheckKinds] = {false};
- CheckerNameRef CheckNames[CK_NumCheckKinds];
- mutable std::unique_ptr<BugType> BTs[CK_NumCheckKinds];
-
- const std::unique_ptr<BugType> &getBugType(CheckKind Kind) const {
- if (!BTs[Kind])
- BTs[Kind].reset(new BugType(CheckNames[Kind], "Nullability",
- categories::MemoryError));
- return BTs[Kind];
- }
+ // FIXME: Currently the `Description` fields of these `BugType`s are all
+ // identical ("Nullability") -- they should be more descriptive than this.
+ // NOTE: NullabilityBase is a dummy checker part that does nothing, so its
+ // bug type is left empty.
+ BugType BugTypes[NumCheckerParts] = {
+ {this, NullabilityBase, "", ""},
+ {this, NullPassedToNonnullChecker, "Nullability",
+ categories::MemoryError},
+ {this, NullReturnedFromNonnullChecker, "Nullability",
+ categories::MemoryError},
+ {this, NullableDereferencedChecker, "Nullability",
+ categories::MemoryError},
+ {this, NullablePassedToNonnullChecker, "Nullability",
+ categories::MemoryError},
+ {this, NullableReturnedFromNonnullChecker, "Nullability",
+ categories::MemoryError}};
// When set to false no nullability information will be tracked in
// NullabilityMap. It is possible to catch errors like passing a null pointer
@@ -163,17 +176,16 @@ class NullabilityChecker
///
/// When \p SuppressPath is set to true, no more bugs will be reported on this
/// path by this checker.
- void reportBugIfInvariantHolds(StringRef Msg, ErrorKind Error, CheckKind CK,
- ExplodedNode *N, const MemRegion *Region,
- CheckerContext &C,
+ void reportBugIfInvariantHolds(StringRef Msg, ErrorKind Error,
+ CheckerPartIdx Idx, ExplodedNode *N,
+ const MemRegion *Region, CheckerContext &C,
const Stmt *ValueExpr = nullptr,
bool SuppressPath = false) const;
- void reportBug(StringRef Msg, ErrorKind Error, CheckKind CK, ExplodedNode *N,
- const MemRegion *Region, BugReporter &BR,
+ void reportBug(StringRef Msg, ErrorKind Error, CheckerPartIdx Idx,
+ ExplodedNode *N, const MemRegion *Region, BugReporter &BR,
const Stmt *ValueExpr = nullptr) const {
- const std::unique_ptr<BugType> &BT = getBugType(CK);
- auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
+ auto R = std::make_unique<PathSensitiveBugReport>(BugTypes[Idx], Msg, N);
if (Region) {
R->markInteresting(Region);
R->addVisitor<NullabilityBugVisitor>(Region);
@@ -479,7 +491,7 @@ static bool checkInvariantViolation(ProgramStateRef State, ExplodedNode *N,
}
void NullabilityChecker::reportBugIfInvariantHolds(
- StringRef Msg, ErrorKind Error, CheckKind CK, ExplodedNode *N,
+ StringRef Msg, ErrorKind Error, CheckerPartIdx Idx, ExplodedNode *N,
const MemRegion *Region, CheckerContext &C, const Stmt *ValueExpr,
bool SuppressPath) const {
ProgramStateRef OriginalState = N->getState();
@@ -491,7 +503,7 @@ void NullabilityChecker::reportBugIfInvariantHolds(
N = C.addTransition(OriginalState, N);
}
- reportBug(Msg, Error, CK, N, Region, C.getBugReporter(), ValueExpr);
+ reportBug(Msg, Error, Idx, N, Region, C.getBugReporter(), ValueExpr);
}
/// Cleaning up the program state.
@@ -545,19 +557,19 @@ void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const {
if (!TrackedNullability)
return;
- if (ChecksEnabled[CK_NullableDereferenced] &&
+ if (isPartEnabled(NullableDereferencedChecker) &&
TrackedNullability->getValue() == Nullability::Nullable) {
BugReporter &BR = *Event.BR;
// Do not suppress errors on defensive code paths, because dereferencing
// a nullable pointer is always an error.
if (Event.IsDirectDereference)
reportBug("Nullable pointer is dereferenced",
- ErrorKind::NullableDereferenced, CK_NullableDereferenced,
+ ErrorKind::NullableDereferenced, NullableDereferencedChecker,
Event.SinkNode, Region, BR);
else {
reportBug("Nullable pointer is passed to a callee that requires a "
"non-null",
- ErrorKind::NullablePassedToNonnull, CK_NullableDereferenced,
+ ErrorKind::NullablePassedToNonnull, NullableDereferencedChecker,
Event.SinkNode, Region, BR);
}
}
@@ -711,7 +723,8 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
bool NullReturnedFromNonNull = (RequiredNullability == Nullability::Nonnull &&
Nullness == NullConstraint::IsNull);
- if (ChecksEnabled[CK_NullReturnedFromNonnull] && NullReturnedFromNonNull &&
+ if (isPartEnabled(NullReturnedFromNonnullChecker) &&
+ NullReturnedFromNonNull &&
RetExprTypeLevelNullability != Nullability::Nonnull &&
!InSuppressedMethodFamily) {
static CheckerProgramPointTag Tag(this, "NullReturnedFromNonnull");
@@ -725,7 +738,7 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
OS << " returned from a " << C.getDeclDescription(D) <<
" that is expected to return a non-null value";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NilReturnedToNonnull,
- CK_NullReturnedFromNonnull, N, nullptr, C,
+ NullReturnedFromNonnullChecker, N, nullptr, C,
RetExpr);
return;
}
@@ -746,7 +759,7 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
State->get<NullabilityMap>(Region);
if (TrackedNullability) {
Nullability TrackedNullabValue = TrackedNullability->getValue();
- if (ChecksEnabled[CK_NullableReturnedFromNonnull] &&
+ if (isPartEnabled(NullableReturnedFromNonnullChecker) &&
Nullness != NullConstraint::IsNotNull &&
TrackedNullabValue == Nullability::Nullable &&
RequiredNullability == Nullability::Nonnull) {
@@ -759,7 +772,8 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
" that is expected to return a non-null value";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NullableReturnedToNonnull,
- CK_NullableReturnedFromNonnull, N, Region, C);
+ NullableReturnedFromNonnullChecker, N, Region,
+ C);
}
return;
}
@@ -810,7 +824,7 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
unsigned ParamIdx = Param->getFunctionScopeIndex() + 1;
- if (ChecksEnabled[CK_NullPassedToNonnull] &&
+ if (isPartEnabled(NullPassedToNonnullChecker) &&
Nullness == NullConstraint::IsNull &&
ArgExprTypeLevelNullability != Nullability::Nonnull &&
RequiredNullability == Nullability::Nonnull &&
@@ -825,7 +839,8 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
OS << " passed to a callee that requires a non-null " << ParamIdx
<< llvm::getOrdinalSuffix(ParamIdx) << " parameter";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull,
- CK_NullPassedToNonnull, N, nullptr, C, ArgExpr,
+ NullPassedToNonnullChecker, N, nullptr, C,
+ ArgExpr,
/*SuppressPath=*/false);
return;
}
@@ -842,7 +857,7 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
TrackedNullability->getValue() != Nullability::Nullable)
continue;
- if (ChecksEnabled[CK_NullablePassedToNonnull] &&
+ if (isPartEnabled(NullablePassedToNonnullChecker) &&
RequiredNullability == Nullability::Nonnull &&
isDiagnosableCall(Call)) {
ExplodedNode *N = C.addTransition(State);
@@ -851,16 +866,16 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
OS << "Nullable pointer is passed to a callee that requires a non-null "
<< ParamIdx << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NullablePassedToNonnull,
- CK_NullablePassedToNonnull, N, Region, C,
+ NullablePassedToNonnullChecker, N, Region, C,
ArgExpr, /*SuppressPath=*/true);
return;
}
- if (ChecksEnabled[CK_NullableDereferenced] &&
+ if (isPartEnabled(NullableDereferencedChecker) &&
Param->getType()->isReferenceType()) {
ExplodedNode *N = C.addTransition(State);
reportBugIfInvariantHolds("Nullable pointer is dereferenced",
ErrorKind::NullableDereferenced,
- CK_NullableDereferenced, N, Region, C,
+ NullableDereferencedChecker, N, Region, C,
ArgExpr, /*SuppressPath=*/true);
return;
}
@@ -1295,7 +1310,7 @@ void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
bool NullAssignedToNonNull = (LocNullability == Nullability::Nonnull &&
RhsNullness == NullConstraint::IsNull);
- if (ChecksEnabled[CK_NullPassedToNonnull] && NullAssignedToNonNull &&
+ if (isPartEnabled(NullPassedToNonnullChecker) && NullAssignedToNonNull &&
ValNullability != Nullability::Nonnull &&
ValueExprTypeLevelNullability != Nullability::Nonnull &&
!isARCNilInitializedLocal(C, S)) {
@@ -1314,7 +1329,8 @@ void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
OS << (LocType->isObjCObjectPointerType() ? "nil" : "Null");
OS << " assigned to a pointer which is expected to have non-null value";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NilAssignedToNonnull,
- CK_NullPassedToNonnull, N, nullptr, C, ValueStmt);
+ NullPassedToNonnullChecker, N, nullptr, C,
+ ValueStmt);
return;
}
@@ -1340,14 +1356,15 @@ void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
if (RhsNullness == NullConstraint::IsNotNull ||
TrackedNullability->getValue() != Nullability::Nullable)
return;
- if (ChecksEnabled[CK_NullablePassedToNonnull] &&
+ if (isPartEnabled(NullablePassedToNonnullChecker) &&
LocNullability == Nullability::Nonnull) {
static CheckerProgramPointTag Tag(this, "NullablePassedToNonnull");
ExplodedNode *N = C.addTransition(State, C.getPredecessor(), &Tag);
reportBugIfInvariantHolds("Nullable pointer is assigned to a pointer "
"which is expected to have non-null value",
ErrorKind::NullableAssignedToNonnull,
- CK_NullablePassedToNonnull, N, ValueRegion, C);
+ NullablePassedToNonnullChecker, N, ValueRegion,
+ C);
}
return;
}
@@ -1394,38 +1411,26 @@ void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
}
}
-void ento::registerNullabilityBase(CheckerManager &mgr) {
- mgr.registerChecker<NullabilityChecker>();
-}
-
-bool ento::shouldRegisterNullabilityBase(const CheckerManager &mgr) {
- return true;
-}
-
-#define REGISTER_CHECKER(name, trackingRequired) \
- void ento::register##name##Checker(CheckerManager &mgr) { \
- NullabilityChecker *checker = mgr.getChecker<NullabilityChecker>(); \
- checker->ChecksEnabled[NullabilityChecker::CK_##name] = true; \
- checker->CheckNames[NullabilityChecker::CK_##name] = \
- mgr.getCurrentCheckerName(); \
- checker->NeedTracking = checker->NeedTracking || trackingRequired; \
- checker->NoDiagnoseCallsToSystemHeaders = \
- checker->NoDiagnoseCallsToSystemHeaders || \
- mgr.getAnalyzerOptions().getCheckerBooleanOption( \
- checker, "NoDiagnoseCallsToSystemHeaders", true); \
+#define REGISTER_CHECKER(Part, TrackingRequired) \
+ void ento::register##Part(CheckerManager &Mgr) { \
+ auto *Checker = \
+ Mgr.registerChecker<NullabilityChecker, NullabilityChecker::Part>(); \
+ Checker->NeedTracking = Checker->NeedTracking || TrackingRequired; \
+ Checker->NoDiagnoseCallsToSystemHeaders = \
+ Checker->NoDiagnoseCallsToSystemHeaders || \
+ Mgr.getAnalyzerOptions().getCheckerBooleanOption( \
+ Checker, "NoDiagnoseCallsToSystemHeaders", true); \
} \
\
- bool ento::shouldRegister##name##Checker(const CheckerManager &mgr) { \
- return true; \
- }
-
-// The checks are likely to be turned on by default and it is possible to do
-// them without tracking any nullability related information. As an optimization
-// no nullability information will be tracked when only these two checks are
-// enables.
-REGISTER_CHECKER(NullPassedToNonnull, false)
-REGISTER_CHECKER(NullReturnedFromNonnull, false)
-
-REGISTER_CHECKER(NullableDereferenced, true)
-REGISTER_CHECKER(NullablePassedToNonnull, true)
-REGISTER_CHECKER(NullableReturnedFromNonnull, true)
+ bool ento::shouldRegister##Part(const CheckerManager &) { return true; }
+
+// These checker parts are likely to be turned on by default and they don't
+// need the tracking of nullability related information. As an optimization
+// nullability information won't be tracked when the rest are disabled.
+REGISTER_CHECKER(NullabilityBase, false)
+REGISTER_CHECKER(NullPassedToNonnullChecker, false)
+REGISTER_CHECKER(NullReturnedFromNonnullChecker, false)
+
+REGISTER_CHECKER(NullableDereferencedChecker, true)
+REGISTER_CHECKER(NullablePassedToNonnullChecker, true)
+REGISTER_CHECKER(NullableReturnedFromNonnullChecker, true)
>From 2708bed01435d5953bf0446626f7c1e6727fef31 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Thu, 20 Mar 2025 17:52:24 +0100
Subject: [PATCH 2/3] Remove hidden dummy checker part NullabilityBase
As far as I see it was just a hacky implementation detail within the
old solution for registering the "real" checker parts. I'm placing this
into a separate commit to make the review easier.
---
.../clang/StaticAnalyzer/Checkers/Checkers.td | 56 +++++++++----------
.../Checkers/NullabilityChecker.cpp | 32 +++++------
.../test/Analysis/analyzer-enabled-checkers.c | 1 -
clang/test/Analysis/bugfix-124477.m | 2 +-
...c-library-functions-arg-enabled-checkers.c | 1 -
5 files changed, 41 insertions(+), 51 deletions(-)
diff --git a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 35df4e7003ac9..0df5304ccf939 100644
--- a/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/clang/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -326,39 +326,37 @@ def StdVariantChecker : Checker<"StdVariant">,
let ParentPackage = Nullability in {
-def NullabilityBase : Checker<"NullabilityBase">,
- HelpText<"Stores information during the analysis about nullability.">,
- Documentation<NotDocumented>,
- Hidden;
-
-def NullPassedToNonnullChecker : Checker<"NullPassedToNonnull">,
- HelpText<"Warns when a null pointer is passed to a pointer which has a "
- "_Nonnull type.">,
- Dependencies<[NullabilityBase]>,
- Documentation<HasDocumentation>;
+ def NullPassedToNonnullChecker
+ : Checker<"NullPassedToNonnull">,
+ HelpText<"Warns when a null pointer is passed to a pointer which has a "
+ "_Nonnull type.">,
+ Documentation<HasDocumentation>;
-def NullReturnedFromNonnullChecker : Checker<"NullReturnedFromNonnull">,
- HelpText<"Warns when a null pointer is returned from a function that has "
- "_Nonnull return type.">,
- Dependencies<[NullabilityBase]>,
- Documentation<HasDocumentation>;
+ def NullReturnedFromNonnullChecker
+ : Checker<"NullReturnedFromNonnull">,
+ HelpText<
+ "Warns when a null pointer is returned from a function that has "
+ "_Nonnull return type.">,
+ Documentation<HasDocumentation>;
-def NullableDereferencedChecker : Checker<"NullableDereferenced">,
- HelpText<"Warns when a nullable pointer is dereferenced.">,
- Dependencies<[NullabilityBase]>,
- Documentation<HasDocumentation>;
+ def NullableDereferencedChecker
+ : Checker<"NullableDereferenced">,
+ HelpText<"Warns when a nullable pointer is dereferenced.">,
+ Documentation<HasDocumentation>;
-def NullablePassedToNonnullChecker : Checker<"NullablePassedToNonnull">,
- HelpText<"Warns when a nullable pointer is passed to a pointer which has a "
- "_Nonnull type.">,
- Dependencies<[NullabilityBase]>,
- Documentation<HasDocumentation>;
+ def NullablePassedToNonnullChecker
+ : Checker<"NullablePassedToNonnull">,
+ HelpText<
+ "Warns when a nullable pointer is passed to a pointer which has a "
+ "_Nonnull type.">,
+ Documentation<HasDocumentation>;
-def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">,
- HelpText<"Warns when a nullable pointer is returned from a function that has "
- "_Nonnull return type.">,
- Dependencies<[NullabilityBase]>,
- Documentation<NotDocumented>;
+ def NullableReturnedFromNonnullChecker
+ : Checker<"NullableReturnedFromNonnull">,
+ HelpText<"Warns when a nullable pointer is returned from a function "
+ "that has "
+ "_Nonnull return type.">,
+ Documentation<NotDocumented>;
} // end "nullability"
diff --git a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index 8fe7d21ca7984..0129f6132e208 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -114,12 +114,7 @@ class NullabilityChecker
// FIXME: This enumeration of checker parts is extremely similar to the
// ErrorKind enum. It would be nice to unify them to simplify the code.
- // FIXME: The modeling checker NullabilityBase is a dummy "empty checker
- // part" that registers this checker class without enabling any of the real
- // checker parts. As far as I understand no other checker references it, so
- // it should be removed.
enum : CheckerPartIdx {
- NullabilityBase,
NullPassedToNonnullChecker,
NullReturnedFromNonnullChecker,
NullableDereferencedChecker,
@@ -130,10 +125,7 @@ class NullabilityChecker
// FIXME: Currently the `Description` fields of these `BugType`s are all
// identical ("Nullability") -- they should be more descriptive than this.
- // NOTE: NullabilityBase is a dummy checker part that does nothing, so its
- // bug type is left empty.
BugType BugTypes[NumCheckerParts] = {
- {this, NullabilityBase, "", ""},
{this, NullPassedToNonnullChecker, "Nullability",
categories::MemoryError},
{this, NullReturnedFromNonnullChecker, "Nullability",
@@ -1412,25 +1404,27 @@ void NullabilityChecker::printState(raw_ostream &Out, ProgramStateRef State,
}
#define REGISTER_CHECKER(Part, TrackingRequired) \
- void ento::register##Part(CheckerManager &Mgr) { \
- auto *Checker = \
- Mgr.registerChecker<NullabilityChecker, NullabilityChecker::Part>(); \
+ void ento::register##Part##Checker(CheckerManager &Mgr) { \
+ auto *Checker = Mgr.registerChecker<NullabilityChecker, \
+ NullabilityChecker::Part##Checker>(); \
Checker->NeedTracking = Checker->NeedTracking || TrackingRequired; \
Checker->NoDiagnoseCallsToSystemHeaders = \
Checker->NoDiagnoseCallsToSystemHeaders || \
Mgr.getAnalyzerOptions().getCheckerBooleanOption( \
- Checker, "NoDiagnoseCallsToSystemHeaders", true); \
+ Mgr.getCurrentCheckerName(), "NoDiagnoseCallsToSystemHeaders", \
+ true); \
} \
\
- bool ento::shouldRegister##Part(const CheckerManager &) { return true; }
+ bool ento::shouldRegister##Part##Checker(const CheckerManager &) { \
+ return true; \
+ }
// These checker parts are likely to be turned on by default and they don't
// need the tracking of nullability related information. As an optimization
// nullability information won't be tracked when the rest are disabled.
-REGISTER_CHECKER(NullabilityBase, false)
-REGISTER_CHECKER(NullPassedToNonnullChecker, false)
-REGISTER_CHECKER(NullReturnedFromNonnullChecker, false)
+REGISTER_CHECKER(NullPassedToNonnull, false)
+REGISTER_CHECKER(NullReturnedFromNonnull, false)
-REGISTER_CHECKER(NullableDereferencedChecker, true)
-REGISTER_CHECKER(NullablePassedToNonnullChecker, true)
-REGISTER_CHECKER(NullableReturnedFromNonnullChecker, true)
+REGISTER_CHECKER(NullableDereferenced, true)
+REGISTER_CHECKER(NullablePassedToNonnull, true)
+REGISTER_CHECKER(NullableReturnedFromNonnull, true)
diff --git a/clang/test/Analysis/analyzer-enabled-checkers.c b/clang/test/Analysis/analyzer-enabled-checkers.c
index e5d0acb84a039..6d1e5311241d2 100644
--- a/clang/test/Analysis/analyzer-enabled-checkers.c
+++ b/clang/test/Analysis/analyzer-enabled-checkers.c
@@ -33,7 +33,6 @@
// CHECK-NEXT: core.uninitialized.CapturedBlockVariable
// CHECK-NEXT: core.uninitialized.UndefReturn
// CHECK-NEXT: deadcode.DeadStores
-// CHECK-NEXT: nullability.NullabilityBase
// CHECK-NEXT: nullability.NullPassedToNonnull
// CHECK-NEXT: nullability.NullReturnedFromNonnull
// CHECK-NEXT: security.insecureAPI.SecuritySyntaxChecker
diff --git a/clang/test/Analysis/bugfix-124477.m b/clang/test/Analysis/bugfix-124477.m
index 80820f4c93444..8bb0196b2f9b8 100644
--- a/clang/test/Analysis/bugfix-124477.m
+++ b/clang/test/Analysis/bugfix-124477.m
@@ -1,4 +1,4 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,apiModeling,nullability.NullableDereferenced,nullability.NullabilityBase -x objective-c %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,apiModeling,nullability.NullableDereferenced -x objective-c %s
/*
This test is reduced from a static analyzer crash. The bug causing
the crash is explained in #124477. It can only be triggered in some
diff --git a/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c b/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c
index d2900c6a42fff..be60870fdb4dc 100644
--- a/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c
+++ b/clang/test/Analysis/std-c-library-functions-arg-enabled-checkers.c
@@ -41,7 +41,6 @@
// CHECK-NEXT: core.uninitialized.CapturedBlockVariable
// CHECK-NEXT: core.uninitialized.UndefReturn
// CHECK-NEXT: deadcode.DeadStores
-// CHECK-NEXT: nullability.NullabilityBase
// CHECK-NEXT: nullability.NullPassedToNonnull
// CHECK-NEXT: nullability.NullReturnedFromNonnull
// CHECK-NEXT: security.insecureAPI.SecuritySyntaxChecker
>From 3ca23ce42044b84507efd96874bea30cec437ff0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Don=C3=A1t=20Nagy?= <donat.nagy at ericsson.com>
Date: Thu, 20 Mar 2025 17:59:50 +0100
Subject: [PATCH 3/3] Use `BugType` parameters for
`reportBug{,IfInvariantHolds}`
---
.../Checkers/NullabilityChecker.cpp | 50 +++++++++----------
1 file changed, 25 insertions(+), 25 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
index 0129f6132e208..1529c3a3b6319 100644
--- a/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -169,15 +169,15 @@ class NullabilityChecker
/// When \p SuppressPath is set to true, no more bugs will be reported on this
/// path by this checker.
void reportBugIfInvariantHolds(StringRef Msg, ErrorKind Error,
- CheckerPartIdx Idx, ExplodedNode *N,
+ const BugType &BT, ExplodedNode *N,
const MemRegion *Region, CheckerContext &C,
const Stmt *ValueExpr = nullptr,
bool SuppressPath = false) const;
- void reportBug(StringRef Msg, ErrorKind Error, CheckerPartIdx Idx,
+ void reportBug(StringRef Msg, ErrorKind Error, const BugType &BT,
ExplodedNode *N, const MemRegion *Region, BugReporter &BR,
const Stmt *ValueExpr = nullptr) const {
- auto R = std::make_unique<PathSensitiveBugReport>(BugTypes[Idx], Msg, N);
+ auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
if (Region) {
R->markInteresting(Region);
R->addVisitor<NullabilityBugVisitor>(Region);
@@ -483,7 +483,7 @@ static bool checkInvariantViolation(ProgramStateRef State, ExplodedNode *N,
}
void NullabilityChecker::reportBugIfInvariantHolds(
- StringRef Msg, ErrorKind Error, CheckerPartIdx Idx, ExplodedNode *N,
+ StringRef Msg, ErrorKind Error, const BugType &BT, ExplodedNode *N,
const MemRegion *Region, CheckerContext &C, const Stmt *ValueExpr,
bool SuppressPath) const {
ProgramStateRef OriginalState = N->getState();
@@ -495,7 +495,7 @@ void NullabilityChecker::reportBugIfInvariantHolds(
N = C.addTransition(OriginalState, N);
}
- reportBug(Msg, Error, Idx, N, Region, C.getBugReporter(), ValueExpr);
+ reportBug(Msg, Error, BT, N, Region, C.getBugReporter(), ValueExpr);
}
/// Cleaning up the program state.
@@ -555,14 +555,15 @@ void NullabilityChecker::checkEvent(ImplicitNullDerefEvent Event) const {
// Do not suppress errors on defensive code paths, because dereferencing
// a nullable pointer is always an error.
if (Event.IsDirectDereference)
- reportBug("Nullable pointer is dereferenced",
- ErrorKind::NullableDereferenced, NullableDereferencedChecker,
- Event.SinkNode, Region, BR);
+ reportBug(
+ "Nullable pointer is dereferenced", ErrorKind::NullableDereferenced,
+ BugTypes[NullableDereferencedChecker], Event.SinkNode, Region, BR);
else {
reportBug("Nullable pointer is passed to a callee that requires a "
"non-null",
- ErrorKind::NullablePassedToNonnull, NullableDereferencedChecker,
- Event.SinkNode, Region, BR);
+ ErrorKind::NullablePassedToNonnull,
+ BugTypes[NullableDereferencedChecker], Event.SinkNode, Region,
+ BR);
}
}
}
@@ -730,8 +731,8 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
OS << " returned from a " << C.getDeclDescription(D) <<
" that is expected to return a non-null value";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NilReturnedToNonnull,
- NullReturnedFromNonnullChecker, N, nullptr, C,
- RetExpr);
+ BugTypes[NullReturnedFromNonnullChecker], N,
+ nullptr, C, RetExpr);
return;
}
@@ -764,8 +765,8 @@ void NullabilityChecker::checkPreStmt(const ReturnStmt *S,
" that is expected to return a non-null value";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NullableReturnedToNonnull,
- NullableReturnedFromNonnullChecker, N, Region,
- C);
+ BugTypes[NullableReturnedFromNonnullChecker], N,
+ Region, C);
}
return;
}
@@ -831,9 +832,8 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
OS << " passed to a callee that requires a non-null " << ParamIdx
<< llvm::getOrdinalSuffix(ParamIdx) << " parameter";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NilPassedToNonnull,
- NullPassedToNonnullChecker, N, nullptr, C,
- ArgExpr,
- /*SuppressPath=*/false);
+ BugTypes[NullPassedToNonnullChecker], N,
+ nullptr, C, ArgExpr, /*SuppressPath=*/false);
return;
}
@@ -858,8 +858,8 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
OS << "Nullable pointer is passed to a callee that requires a non-null "
<< ParamIdx << llvm::getOrdinalSuffix(ParamIdx) << " parameter";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NullablePassedToNonnull,
- NullablePassedToNonnullChecker, N, Region, C,
- ArgExpr, /*SuppressPath=*/true);
+ BugTypes[NullablePassedToNonnullChecker], N,
+ Region, C, ArgExpr, /*SuppressPath=*/true);
return;
}
if (isPartEnabled(NullableDereferencedChecker) &&
@@ -867,8 +867,8 @@ void NullabilityChecker::checkPreCall(const CallEvent &Call,
ExplodedNode *N = C.addTransition(State);
reportBugIfInvariantHolds("Nullable pointer is dereferenced",
ErrorKind::NullableDereferenced,
- NullableDereferencedChecker, N, Region, C,
- ArgExpr, /*SuppressPath=*/true);
+ BugTypes[NullableDereferencedChecker], N,
+ Region, C, ArgExpr, /*SuppressPath=*/true);
return;
}
continue;
@@ -1321,8 +1321,8 @@ void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
OS << (LocType->isObjCObjectPointerType() ? "nil" : "Null");
OS << " assigned to a pointer which is expected to have non-null value";
reportBugIfInvariantHolds(OS.str(), ErrorKind::NilAssignedToNonnull,
- NullPassedToNonnullChecker, N, nullptr, C,
- ValueStmt);
+ BugTypes[NullPassedToNonnullChecker], N, nullptr,
+ C, ValueStmt);
return;
}
@@ -1355,8 +1355,8 @@ void NullabilityChecker::checkBind(SVal L, SVal V, const Stmt *S,
reportBugIfInvariantHolds("Nullable pointer is assigned to a pointer "
"which is expected to have non-null value",
ErrorKind::NullableAssignedToNonnull,
- NullablePassedToNonnullChecker, N, ValueRegion,
- C);
+ BugTypes[NullablePassedToNonnullChecker], N,
+ ValueRegion, C);
}
return;
}
More information about the cfe-commits
mailing list