[clang] [clang][ssaf] Add --ssaf-include-local-entities flag (PR #205351)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 23 07:06:14 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-ssaf
Author: Balázs Benics (steakhal)
<details>
<summary>Changes</summary>
This option allows including local entities in summaries. This means that ContributorFinder can optionally include block-scope (function-local) variables.
Parameters are intentionally skipped: they are exposed via their parent function's USR + a parameter-index suffix in getEntityName, so registering them as independent contributors would be redundant.
Part §2 of rdar://179151023
---
Full diff: https://github.com/llvm/llvm-project/pull/205351.diff
9 Files Affected:
- (modified) clang/include/clang/Frontend/SSAFOptions.h (+7)
- (modified) clang/include/clang/Options/Options.td (+8)
- (modified) clang/lib/Driver/ToolChains/Clang.cpp (+1)
- (modified) clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp (+1-1)
- (modified) clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp (+23-4)
- (modified) clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h (+10-1)
- (modified) clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp (+1-1)
- (modified) clang/test/Analysis/Scalable/command-line-interface.cpp (+13)
- (modified) clang/test/Analysis/Scalable/help.cpp (+2)
``````````diff
diff --git a/clang/include/clang/Frontend/SSAFOptions.h b/clang/include/clang/Frontend/SSAFOptions.h
index 738262cc4a713..f760d51ab5414 100644
--- a/clang/include/clang/Frontend/SSAFOptions.h
+++ b/clang/include/clang/Frontend/SSAFOptions.h
@@ -41,9 +41,16 @@ class SSAFOptions {
LLVM_PREFERRED_TYPE(bool)
unsigned ShowFormats : 1;
+ /// Include block-scope (function-local) declarations in extracted SSAF
+ /// summaries. Defaults to false to preserve the original behavior.
+ /// Controlled by: --ssaf-include-local-entities
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned IncludeLocalEntities : 1;
+
SSAFOptions() {
ShowExtractors = false;
ShowFormats = false;
+ IncludeLocalEntities = false;
};
};
diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td
index 4fc9f4d4c3472..f4a7fb8586e99 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -981,6 +981,14 @@ def _ssaf_compilation_unit_id :
"produced SSAF TU summary. Required when '--ssaf-tu-summary-file=' is "
"set.">,
MarshallingInfoString<SSAFOpts<"CompilationUnitId">>;
+def _ssaf_include_local_entities :
+ Flag<["--"], "ssaf-include-local-entities">,
+ Group<SSAF_Group>,
+ Visibility<[ClangOption, CC1Option]>,
+ HelpText<
+ "Include block-scope (function-local) declarations in extracted SSAF "
+ "summaries. By default they are omitted.">,
+ MarshallingInfoFlag<SSAFOpts<"IncludeLocalEntities">>;
def Xarch__
: JoinedAndSeparate<["-"], "Xarch_">,
Flags<[NoXarchOption]>,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index 418d540895681..3333698c87e36 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7944,6 +7944,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
Args.AddLastArg(CmdArgs, options::OPT__ssaf_extract_summaries);
Args.AddLastArg(CmdArgs, options::OPT__ssaf_tu_summary_file);
Args.AddLastArg(CmdArgs, options::OPT__ssaf_compilation_unit_id);
+ Args.AddLastArg(CmdArgs, options::OPT__ssaf_include_local_entities);
// Handle serialized diagnostics.
if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) {
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
index ef5932c52a6c3..aee1387228ba0 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
@@ -333,7 +333,7 @@ class PointerFlowTUSummaryExtractor : public TUSummaryExtractor {
void HandleTranslationUnit(ASTContext &Ctx) override {
std::vector<const NamedDecl *> Contributors;
- findContributors(Ctx, Contributors);
+ findContributors(Ctx, getOptions(), Contributors);
for (auto *CD : Contributors) {
// Templates are skipped, but their instantiations are handled. The idea
// is that we can conclude facts about a template through all of its
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
index 660bc424fb32f..65087b2cf1227 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
@@ -12,9 +12,11 @@
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/AST/ExprCXX.h"
+#include "clang/Frontend/SSAFOptions.h"
#include <set>
using namespace clang;
+using namespace ssaf;
std::string ssaf::describeJSONValue(const llvm::json::Value &V) {
return llvm::formatv("{0:2}", V).str();
@@ -33,8 +35,9 @@ namespace {
class ContributorFinder : public DynamicRecursiveASTVisitor {
public:
std::set<const NamedDecl *> Contributors;
+ const SSAFOptions &Opts;
- ContributorFinder() {
+ ContributorFinder(const SSAFOptions &Opts) : Opts(Opts) {
ShouldVisitTemplateInstantiations = true;
ShouldVisitImplicitCode = false;
}
@@ -53,7 +56,23 @@ class ContributorFinder : public DynamicRecursiveASTVisitor {
DeclContext *DC = D->getDeclContext();
// Collects Decl for global variables or static data members:
- if (DC->isFileContext() || D->isStaticDataMember())
+ if (DC->isFileContext() || D->isStaticDataMember()) {
+ Contributors.insert(D);
+ return true;
+ }
+
+ // Optionally include block-scope (function-local) variables. Parameters
+ // are intentionally skipped: they are exposed via their parent function's
+ // USR + a parameter-index suffix in getEntityName, so registering them as
+ // independent contributors would be redundant.
+ //
+ // FIXME: clang::index::generateUSRForDecl can produce non-unique or empty
+ // USRs for some local declaration shapes (e.g., locals of certain template
+ // instantiations). The current addEntity path returns std::nullopt when
+ // that happens and downstream extractors skip gracefully, so this is
+ // tolerated for now.
+ if (Opts.IncludeLocalEntities && !D->isImplicit() && !isa<ParmVarDecl>(D) &&
+ DC->isFunctionOrMethod())
Contributors.insert(D);
return true;
}
@@ -124,9 +143,9 @@ class ContributorFactFinder : public DynamicRecursiveASTVisitor {
};
} // namespace
-void ssaf::findContributors(ASTContext &Ctx,
+void ssaf::findContributors(ASTContext &Ctx, const SSAFOptions &Options,
std::vector<const NamedDecl *> &Contributors) {
- ContributorFinder Finder;
+ ContributorFinder Finder{Options};
Finder.TraverseAST(Ctx);
Contributors.insert(Contributors.end(), Finder.Contributors.begin(),
Finder.Contributors.end());
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
index 38c37e7103b73..a2b99484af3c4 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
@@ -21,6 +21,8 @@
#include "llvm/Support/raw_ostream.h"
namespace clang::ssaf {
+class SSAFOptions;
+
///\return a short descriptions of a json::Value
std::string describeJSONValue(const llvm::json::Value &V);
///\return a short descriptions of a json::Array
@@ -67,7 +69,14 @@ inline void logWarningFromError(llvm::Error Err) {
}
/// Find all contributors in an AST.
-void findContributors(ASTContext &Ctx,
+///
+/// \p Options controls which declarations qualify as contributors. By default
+/// the visitor preserves the original SSAF behavior of skipping block-scope
+/// (function-local) variable declarations; setting
+/// \c Options.IncludeLocalEntities to \c true also collects local variables
+/// (excluding function parameters, which are addressed via their parent
+/// function's USR).
+void findContributors(ASTContext &Ctx, const SSAFOptions &Options,
std::vector<const NamedDecl *> &Contributors);
/// Perform "MatchAction" on each Stmt and Decl belonging to the `Contributor`.
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index f4067e5f315ff..ae0c2855008a0 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -72,7 +72,7 @@ void clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
ASTContext &Ctx) {
std::vector<const NamedDecl *> Contributors;
- findContributors(Ctx, Contributors);
+ findContributors(Ctx, getOptions(), Contributors);
for (auto *CD : Contributors) {
// Templates are skipped, but their instantiations are handled. The idea
// is that we can conclude facts about a template through all of its
diff --git a/clang/test/Analysis/Scalable/command-line-interface.cpp b/clang/test/Analysis/Scalable/command-line-interface.cpp
index fc01051a4a8f0..0af37cb926ae3 100644
--- a/clang/test/Analysis/Scalable/command-line-interface.cpp
+++ b/clang/test/Analysis/Scalable/command-line-interface.cpp
@@ -13,6 +13,19 @@
// RUN: not %clang -fsyntax-only %s --ssaf-tu-summary-file=%t.ssaf.json --ssaf-compilation-unit-id=test-cu --ssaf-extract-summaries=extractor1,extractor2 2>&1 | %{filecheck}=NO-EXTRACTORS-WITH-NAME
// RUN: not %clang_cc1 -fsyntax-only %s --ssaf-tu-summary-file=%t.ssaf.json --ssaf-compilation-unit-id=test-cu --ssaf-extract-summaries=extractor1,extractor2 2>&1 | %{filecheck}=NO-EXTRACTORS-WITH-NAME
+// Verify --ssaf-include-local-entities is accepted alongside summary extraction
+// in both the driver and CC1, and that without --ssaf-tu-summary-file= the
+// flag is silently ignored (same shape as --ssaf-list-extractors).
+// RUN: rm -rf %t.localents && mkdir %t.localents
+// RUN: %clang -fsyntax-only %s --ssaf-include-local-entities
+// RUN: %clang_cc1 -fsyntax-only %s --ssaf-include-local-entities
+// RUN: %clang -fsyntax-only %s --ssaf-tu-summary-file=%t.localents/a.ssaf.json --ssaf-compilation-unit-id=test-cu --ssaf-extract-summaries=CallGraph --ssaf-include-local-entities
+// RUN: %clang_cc1 -fsyntax-only %s --ssaf-tu-summary-file=%t.localents/b.ssaf.json --ssaf-compilation-unit-id=test-cu --ssaf-extract-summaries=CallGraph --ssaf-include-local-entities
+
+// Verify the driver forwards the flag to CC1.
+// RUN: %clang -### -fsyntax-only %s --ssaf-include-local-entities --ssaf-tu-summary-file=%t.localents/c.ssaf.json --ssaf-compilation-unit-id=test-cu --ssaf-extract-summaries=CallGraph 2>&1 | FileCheck %s --check-prefix=DRIVER-FORWARDS-FLAG
+// DRIVER-FORWARDS-FLAG: "-cc1"{{.+}}"--ssaf-include-local-entities"
+
void empty() {}
// NOT-MATCHING-THE-PATTERN: error: failed to parse the value of '--ssaf-tu-summary-file=foobar' the value must follow the '<path>.<format>' pattern [-Wscalable-static-analysis-framework]
diff --git a/clang/test/Analysis/Scalable/help.cpp b/clang/test/Analysis/Scalable/help.cpp
index 15d6d109360d8..3feae2dfaa456 100644
--- a/clang/test/Analysis/Scalable/help.cpp
+++ b/clang/test/Analysis/Scalable/help.cpp
@@ -7,6 +7,8 @@
// HELP-NEXT: Stable identifier used as the CompilationUnit namespace name of every produced SSAF TU summary. Required when '--ssaf-tu-summary-file=' is set.
// HELP-NEXT: --ssaf-extract-summaries=<summary-names>
// HELP-NEXT: Comma-separated list of summary names to extract
+// HELP-NEXT: --ssaf-include-local-entities
+// HELP-NEXT: Include block-scope (function-local) declarations in extracted SSAF summaries. By default they are omitted.
// HELP-NEXT: --ssaf-list-extractors Display the list of available SSAF summary extractors
// HELP-NEXT: --ssaf-list-formats Display the list of available SSAF serialization formats
// HELP-NEXT: --ssaf-tu-summary-file=<path>.<format>
``````````
</details>
https://github.com/llvm/llvm-project/pull/205351
More information about the cfe-commits
mailing list