[llvm-branch-commits] [clang] [UnsafeBufferUsage][SSAF] Change -Wunsafe-buffer-usage API for SSAF-based analysis (PR #191934)
Ziqing Luo via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Apr 16 13:53:54 PDT 2026
https://github.com/ziqingluo-90 updated https://github.com/llvm/llvm-project/pull/191934
>From d116672ae4a7f894e0989902b1e4412016b75345 Mon Sep 17 00:00:00 2001
From: Ziqing Luo <ziqing_luo at apple.com>
Date: Mon, 13 Apr 2026 20:04:26 -0700
Subject: [PATCH 1/3] [UnsafeBufferUsage][SSAF] Change -Wunsafe-buffer-usage
API for SSAF-based analysis
Change -Wunsafe-buffer-usage API to match `Stmt`s instead of `Decl`s.
It is up to clients of the API to determine how to traversal a
`Decl`. In this change, the client is SSAF-based
UnsafeBufferUsageExtractor.
---
.../Analysis/Analyses/UnsafeBufferUsage.h | 12 +-
clang/lib/Analysis/UnsafeBufferUsage.cpp | 123 ++++++++++--------
.../UnsafeBufferUsageExtractor.cpp | 24 +---
3 files changed, 72 insertions(+), 87 deletions(-)
diff --git a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
index e0d583c735e61..65b79cfc1c2ff 100644
--- a/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
+++ b/clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
@@ -201,14 +201,10 @@ bool anyConflict(const llvm::SmallVectorImpl<FixItHint> &FixIts,
const SourceManager &SM);
} // namespace internal
-/// Find unsafe pointers in body/initializer of `D`, if `D` is one of the
-/// followings:
-/// VarDecl
-/// FieldDecl
-/// FunctionDecl
-/// BlockDecl
-/// ObjCMethodDecl
-std::set<const Expr *> findUnsafePointers(const Decl *D);
+/// \return true iff `N` is an unsafe buffer usage and populates the unsafe
+/// pointers in `UnsafePointers`
+bool matchUnsafePointers(const DynTypedNode &N, ASTContext &Ctx,
+ std::set<const Expr *> &UnsafePointers);
} // end namespace clang
#endif /* LLVM_CLANG_ANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_H */
diff --git a/clang/lib/Analysis/UnsafeBufferUsage.cpp b/clang/lib/Analysis/UnsafeBufferUsage.cpp
index 3dba15cff3b52..e80dfc82e60ba 100644
--- a/clang/lib/Analysis/UnsafeBufferUsage.cpp
+++ b/clang/lib/Analysis/UnsafeBufferUsage.cpp
@@ -2975,63 +2975,6 @@ static void populateStmtsForFindingGadgets(SmallVector<const Stmt *> &Stmts,
}
}
-std::set<const Expr *> clang::findUnsafePointers(const Decl *D) {
- class MockReporter : public UnsafeBufferUsageHandler {
- public:
- MockReporter() {}
- void handleUnsafeOperation(const Stmt *, bool, ASTContext &) override {}
- void handleUnsafeLibcCall(const CallExpr *, unsigned, ASTContext &,
- const Expr *UnsafeArg = nullptr) override {}
- void handleUnsafeOperationInContainer(const Stmt *, bool,
- ASTContext &) override {}
- void handleUnsafeVariableGroup(const VarDecl *,
- const VariableGroupsManager &, FixItList &&,
- const Decl *,
- const FixitStrategy &) override {}
- void handleUnsafeUniquePtrArrayAccess(const DynTypedNode &Node,
- bool IsRelatedToDecl,
- ASTContext &Ctx) override {}
- bool ignoreUnsafeBufferInContainer(const SourceLocation &) const override {
- return false;
- }
- bool isSafeBufferOptOut(const SourceLocation &) const override {
- return false;
- }
- bool ignoreUnsafeBufferInLibcCall(const SourceLocation &) const override {
- return false;
- }
- bool ignoreUnsafeBufferInStaticSizedArray(
- const SourceLocation &Loc) const override {
- return false;
- }
- std::string getUnsafeBufferUsageAttributeTextAt(
- SourceLocation, StringRef WSSuffix = "") const override {
- return "";
- }
- };
-
- FixableGadgetList FixableGadgets;
- WarningGadgetList WarningGadgets;
- DeclUseTracker Tracker;
- MockReporter IgnoreHandler;
- ASTContext &Ctx = D->getASTContext();
- SmallVector<const Stmt *> Stmts;
-
- populateStmtsForFindingGadgets(Stmts, D);
- for (auto *Stmt : Stmts)
- findGadgets(Stmt, Ctx, IgnoreHandler, false, FixableGadgets, WarningGadgets,
- Tracker);
-
- std::set<const Expr *> Result;
- for (auto &G : WarningGadgets) {
- for (const Expr *E : G->getUnsafePtrs()) {
- Result.insert(E);
- }
- }
-
- return Result;
-}
-
struct WarningGadgetSets {
std::map<const VarDecl *, std::set<const WarningGadget *>,
// To keep keys sorted by their locations in the map so that the
@@ -4749,3 +4692,69 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
applyGadgets(D, std::move(FixableGadgets), std::move(WarningGadgets),
std::move(Tracker), Handler, EmitSuggestions);
}
+
+bool clang::matchUnsafePointers(const DynTypedNode &N, ASTContext &Ctx,
+ std::set<const Expr *> &UnsafePointers) {
+ class MockReporter : public UnsafeBufferUsageHandler {
+ public:
+ MockReporter() {}
+ void handleUnsafeOperation(const Stmt *, bool, ASTContext &) override {}
+ void handleUnsafeLibcCall(const CallExpr *, unsigned, ASTContext &,
+ const Expr *UnsafeArg = nullptr) override {}
+ void handleUnsafeOperationInContainer(const Stmt *, bool,
+ ASTContext &) override {}
+ void handleUnsafeVariableGroup(const VarDecl *,
+ const VariableGroupsManager &, FixItList &&,
+ const Decl *,
+ const FixitStrategy &) override {}
+ void handleUnsafeUniquePtrArrayAccess(const DynTypedNode &Node,
+ bool IsRelatedToDecl,
+ ASTContext &Ctx) override {}
+ bool ignoreUnsafeBufferInContainer(const SourceLocation &) const override {
+ return false;
+ }
+ bool isSafeBufferOptOut(const SourceLocation &) const override {
+ return false;
+ }
+ bool ignoreUnsafeBufferInLibcCall(const SourceLocation &) const override {
+ return false;
+ }
+ bool ignoreUnsafeBufferInStaticSizedArray(
+ const SourceLocation &Loc) const override {
+ return false;
+ }
+ std::string getUnsafeBufferUsageAttributeTextAt(
+ SourceLocation, StringRef WSSuffix = "") const override {
+ return "";
+ }
+ } Handler;
+
+ const Stmt *S = N.get<Stmt>();
+ if (!S)
+ return false;
+
+ MatchResult Result;
+ WarningGadgetList WarningGadgets;
+ bool Matched = false;
+
+ // FIXME: By design, we don't need MockReporter, and we are supposed to
+ // only define WARNING_GADGET when we want to treat WARNING_OPTIONAL_GADGET
+ // the same as WARNING_GADGET. The reason we have to do it this way now is
+ // that some WARNING_OPTIONAL_GADGETs do not have the 3-argument `matches`
+ // overload. We need to fix this problem in a separate patch.
+
+#define WARNING_GADGET(name) \
+ if (name##Gadget::matches(S, Ctx, Result)) \
+ WarningGadgets.push_back(std::make_unique<name##Gadget>(Result));
+#define WARNING_OPTIONAL_GADGET(name) \
+ if (name##Gadget::matches(S, Ctx, &Handler, Result)) \
+ WarningGadgets.push_back(std::make_unique<name##Gadget>(Result));
+#include "clang/Analysis/Analyses/UnsafeBufferUsageGadgets.def"
+
+ for (auto &WG : WarningGadgets)
+ for (auto *E : WG->getUnsafePtrs()) {
+ UnsafePointers.insert(E);
+ Matched = true;
+ }
+ return Matched;
+}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index d8b8829a19106..53e47ffde7310 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -26,25 +26,6 @@
using namespace clang;
using namespace ssaf;
-static std::set<const Expr *>
-findUnsafePointersInContributor(const DynTypedNode &Node) {
- const Decl *D = Node.get<Decl>();
-
- if (!D)
- return {};
- if (isa<FunctionDecl>(D) || isa<VarDecl>(D))
- return findUnsafePointers(D);
- if (auto *RD = dyn_cast<RecordDecl>(D)) {
- std::set<const Expr *> Result;
-
- for (const FieldDecl *FD : RD->fields()) {
- Result.merge(findUnsafePointers(FD));
- }
- return Result;
- }
- return {};
-}
-
class clang::ssaf::UnsafeBufferUsageTUSummaryExtractor
: public TUSummaryExtractor {
public:
@@ -57,9 +38,8 @@ class clang::ssaf::UnsafeBufferUsageTUSummaryExtractor
extractEntitySummary(const NamedDecl *Contributor, ASTContext &Ctx) {
std::set<const Expr *> UnsafePointers;
- auto MatchAction = [&UnsafePointers](const DynTypedNode &Node) {
- auto Result = findUnsafePointersInContributor(Node);
- UnsafePointers.insert(Result.begin(), Result.end());
+ auto MatchAction = [&Ctx, &UnsafePointers](const DynTypedNode &Node) {
+ return matchUnsafePointers(Node, Ctx, UnsafePointers);
};
findMatchesIn(Contributor, MatchAction);
>From 3cd2f6f8ed861eb52dde10bcc0f0492ac7e1924d Mon Sep 17 00:00:00 2001
From: Ziqing Luo <ziqing_luo at apple.com>
Date: Thu, 16 Apr 2026 13:49:40 -0700
Subject: [PATCH 2/3] fix linux build fail
---
.../Analyses/SSAFAnalysesCommon.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
index a00e7933165ef..8e611742b74de 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "SSAFAnalysesCommon.h"
+#include "clang/AST/ASTContext.h"
using namespace clang;
>From 51c6b68abefa5fd02d0192c9039672eafbbfd015 Mon Sep 17 00:00:00 2001
From: Ziqing Luo <ziqing_luo at apple.com>
Date: Thu, 16 Apr 2026 13:53:31 -0700
Subject: [PATCH 3/3] move ASTContext include to the header
---
.../Analyses/SSAFAnalysesCommon.cpp | 1 -
.../Analyses/SSAFAnalysesCommon.h | 1 +
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
index 8e611742b74de..a00e7933165ef 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "SSAFAnalysesCommon.h"
-#include "clang/AST/ASTContext.h"
using namespace clang;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
index e6759c1fb6e39..d2854f7fbae45 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
@@ -12,6 +12,7 @@
#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_SSAFANALYSESCOMMON_H
#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_SSAFANALYSESCOMMON_H
+#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTTypeTraits.h"
#include "clang/AST/Decl.h"
#include "llvm/Support/JSON.h"
More information about the llvm-branch-commits
mailing list