https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/205446
>From d018322850c7999b5560b3f3cc35fe1bdb98704e Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Tue, 23 Jun 2026 15:26:09 -0700 Subject: [PATCH 01/11] [clang][SSAF] Optionally skip system-header contributors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A new —ssaf-no-extract-from-system-headers switch that gates the contributor finder so unsafe-buffer contributors located inside system headers are dropped from the per-TU summary, plus a companion workaround flag tolerating duplicated contributors that this exposed. rdar://179151040 --- clang/include/clang/Frontend/SSAFOptions.h | 9 +++ clang/include/clang/Options/Options.td | 10 +++ clang/lib/Driver/ToolChains/Clang.cpp | 1 + .../PointerFlow/PointerFlowExtractor.cpp | 1 + .../Analyses/SSAFAnalysesCommon.cpp | 34 +++++++- .../Analyses/SSAFAnalysesCommon.h | 7 +- .../UnsafeBufferUsageExtractor.cpp | 1 + .../PointerFlow/system-header-opt-out.cpp | 43 ++++++++++ clang/test/Analysis/Scalable/help.cpp | 2 + .../Analyses/PointerFlow/PointerFlowTest.cpp | 78 +++++++++++++++++++ 10 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 clang/test/Analysis/Scalable/PointerFlow/system-header-opt-out.cpp diff --git a/clang/include/clang/Frontend/SSAFOptions.h b/clang/include/clang/Frontend/SSAFOptions.h index 738262cc4a713..979501730e265 100644 --- a/clang/include/clang/Frontend/SSAFOptions.h +++ b/clang/include/clang/Frontend/SSAFOptions.h @@ -41,9 +41,18 @@ class SSAFOptions { LLVM_PREFERRED_TYPE(bool) unsigned ShowFormats : 1; + /// Extract from system-header declarations during SSAF contributor + /// enumeration. Defaults to true to preserve the original behavior. + /// Cleared by `--ssaf-no-extract-from-system-headers` (negative-marshalled + /// flag) when the caller wants to scope contributor enumeration to + /// user-source decls. + LLVM_PREFERRED_TYPE(bool) + unsigned ExtractFromSystemHeaders : 1; + SSAFOptions() { ShowExtractors = false; ShowFormats = false; + ExtractFromSystemHeaders = true; }; }; diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index dedbab4869997..847f2e3195474 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -982,6 +982,16 @@ def _ssaf_compilation_unit_id : "produced SSAF TU summary. Required when '--ssaf-tu-summary-file=' is " "set.">, MarshallingInfoString<SSAFOpts<"CompilationUnitId">>; +def _ssaf_no_extract_from_system_headers : + Flag<["--"], "ssaf-no-extract-from-system-headers">, + Group<SSAF_Group>, + Visibility<[ClangOption, CC1Option]>, + HelpText< + "Skip declarations in system headers during SSAF contributor " + "enumeration. By default the SSAF TU summary extractors enumerate " + "system-header declarations alongside user-source declarations; " + "this flag opts out of that enumeration.">, + MarshallingInfoNegativeFlag<SSAFOpts<"ExtractFromSystemHeaders">>; def Xarch__ : JoinedAndSeparate<["-"], "Xarch_">, Flags<[NoXarchOption]>, diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a30b01a675b99..a6ab0bbc10bf6 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8073,6 +8073,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_no_extract_from_system_headers); // Handle serialized diagnostics. if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) { diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp index 8961a90acaf81..826b90806ea5d 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp @@ -13,6 +13,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/Frontend/SSAFOptions.h" #include "clang/AST/Stmt.h" #include "clang/AST/TypeBase.h" #include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h" diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp index 667ef69606aad..7b6523e3e545c 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp @@ -12,6 +12,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ExprCXX.h" +#include "clang/Basic/SourceManager.h" #include <set> using namespace clang; @@ -34,22 +35,29 @@ class ContributorFinder : public DynamicRecursiveASTVisitor { public: std::set<const NamedDecl *> Contributors; - ContributorFinder() { + ContributorFinder(ASTContext &Ctx, bool ExtractFromSystemHeaders) + : Ctx(Ctx), ExtractFromSystemHeaders(ExtractFromSystemHeaders) { ShouldVisitTemplateInstantiations = true; ShouldVisitImplicitCode = false; } bool VisitFunctionDecl(FunctionDecl *D) override { + if (skipForSystemHeader(D)) + return true; Contributors.insert(D); return true; } bool VisitRecordDecl(RecordDecl *D) override { + if (skipForSystemHeader(D)) + return true; Contributors.insert(D); return true; } bool VisitVarDecl(VarDecl *D) override { + if (skipForSystemHeader(D)) + return true; DeclContext *DC = D->getDeclContext(); // Collects Decl for global variables or static data members: @@ -61,9 +69,28 @@ class ContributorFinder : public DynamicRecursiveASTVisitor { bool VisitLambdaExpr(LambdaExpr *L) override { // TraverseLambdaExpr directly visits the body stmt, skipping the // CXXMethodDecl, which is a contributor that needs to be collected. + // The system-header gate fires via the delegated VisitFunctionDecl + // (the call operator's spelling location is the lambda's source + // location), so no separate gate here. VisitFunctionDecl(L->getCallOperator()); return true; } + +private: + // Returns true when the contributor shall be skipped because its location + // is in a system header. The `Loc.isValid()` guard matches the in-tree + // precedent at `ReferenceBindingEntityExtractor.cpp` — compiler-generated + // decls (builtin FunctionDecls, implicit template instantiations) can reach + // the visitor with invalid locations and shall NOT be inadvertently skipped. + bool skipForSystemHeader(const Decl *D) const { + if (ExtractFromSystemHeaders) + return false; + SourceLocation Loc = D->getLocation(); + return Loc.isValid() && Ctx.getSourceManager().isInSystemHeader(Loc); + } + + ASTContext &Ctx; + bool ExtractFromSystemHeaders; }; /// An AST visitor that skips the root node's strict-descendants that are @@ -127,8 +154,9 @@ class ContributorFactFinder : public DynamicRecursiveASTVisitor { void ssaf::findContributors( ASTContext &Ctx, llvm::DenseMap<const NamedDecl *, std::vector<const NamedDecl *>> - &Contributors) { - ContributorFinder Finder; + &Contributors, + bool ExtractFromSystemHeaders) { + ContributorFinder Finder{Ctx, ExtractFromSystemHeaders}; Finder.TraverseAST(Ctx); for (const NamedDecl *C : Finder.Contributors) Contributors[cast<NamedDecl>(C->getCanonicalDecl())].push_back(C); diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h index 674ccfcc58313..8f84203cde15b 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h +++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h @@ -15,6 +15,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" +#include "clang/Frontend/SSAFOptions.h" #include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h" #include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h" #include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h" @@ -78,7 +79,8 @@ inline void logWarningFromError(llvm::Error Err) { void findContributors( ASTContext &Ctx, llvm::DenseMap<const NamedDecl *, std::vector<const NamedDecl *>> - &Contributors); + &Contributors, + bool ExtractFromSystemHeaders = true); /// Perform "MatchAction" on each Stmt and Decl belonging to the `Contributor`. /// \param Contributor @@ -107,7 +109,8 @@ void extractAndAddSummaries(TUSummaryExtractor &Extractor, const char *ExtractorName = "") { llvm::DenseMap<const NamedDecl *, std::vector<const NamedDecl *>> Contributors; - findContributors(Ctx, Contributors); + findContributors(Ctx, Contributors, + Extractor.getOptions().ExtractFromSystemHeaders); for (const auto &[Cano, Decls] : 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/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp index 24f49ef05e653..ff9ee00c41269 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp @@ -11,6 +11,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/Analysis/Analyses/UnsafeBufferUsage.h" +#include "clang/Frontend/SSAFOptions.h" #include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h" #include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h" #include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h" diff --git a/clang/test/Analysis/Scalable/PointerFlow/system-header-opt-out.cpp b/clang/test/Analysis/Scalable/PointerFlow/system-header-opt-out.cpp new file mode 100644 index 0000000000000..dd04cb8753851 --- /dev/null +++ b/clang/test/Analysis/Scalable/PointerFlow/system-header-opt-out.cpp @@ -0,0 +1,43 @@ +// Regression for clang-reforge-7y4 / iter-03: end-to-end verification +// of the --ssaf-no-extract-from-system-headers opt-out. Spec: +// tu-summary-extraction's "System-header contributor opt-out flag" +// requirement. + +// REQUIRES: system-darwin || system-linux + +// Setup: synthesise an -isystem header containing a benign user-named +// symbol (no USR collision — that case is exercised end-to-end by the +// parity-finale verification step against libJP2). +// RUN: rm -rf %t.dir +// RUN: mkdir -p %t.dir/sysinc +// RUN: printf '#pragma clang system_header\nint *sys_gp; void sys_fn(int *p) { sys_gp = p; }\n' > %t.dir/sysinc/sys.h + +// === Case A: flag absent (default extracts from system headers). === +// The extractor enumerates both sys_fn and user_fn; the TU summary's +// IdTable contains both names. +// RUN: rm -f %t-default.json +// RUN: %clang -c %s -o %t-default.o -isystem %t.dir/sysinc \ +// RUN: --ssaf-extract-summaries=PointerFlow \ +// RUN: --ssaf-tu-summary-file=%t-default.json \ +// RUN: --ssaf-compilation-unit-id=sys-default +// RUN: FileCheck --check-prefix=DEFAULT %s < %t-default.json +// DEFAULT-DAG: sys_fn +// DEFAULT-DAG: user_fn + +// === Case B: flag present (opt-out skips system-header decls). === +// The extractor skips sys_fn (system header) but keeps user_fn. +// The TU summary's IdTable contains user_fn but NOT sys_fn. +// RUN: rm -f %t-optout.json +// RUN: %clang -c %s -o %t-optout.o -isystem %t.dir/sysinc \ +// RUN: --ssaf-extract-summaries=PointerFlow \ +// RUN: --ssaf-tu-summary-file=%t-optout.json \ +// RUN: --ssaf-no-extract-from-system-headers \ +// RUN: --ssaf-compilation-unit-id=sys-optout +// RUN: FileCheck --check-prefix=OPTOUT %s < %t-optout.json +// OPTOUT-NOT: sys_fn +// OPTOUT: user_fn + +#include <sys.h> + +int *user_gp; +void user_fn(int *p) { user_gp = p; } diff --git a/clang/test/Analysis/Scalable/help.cpp b/clang/test/Analysis/Scalable/help.cpp index 15d6d109360d8..d34f09c65797d 100644 --- a/clang/test/Analysis/Scalable/help.cpp +++ b/clang/test/Analysis/Scalable/help.cpp @@ -9,6 +9,8 @@ // HELP-NEXT: Comma-separated list of summary names to extract // 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-no-extract-from-system-headers +// HELP-NEXT: Skip declarations in system headers during SSAF contributor enumeration. By default the SSAF TU summary extractors enumerate system-header declarations alongside user-source declarations; this flag opts out of that enumeration. // HELP-NEXT: --ssaf-tu-summary-file=<path>.<format> // HELP-NEXT: The output file for the extracted summaries. The extension selects which file format to use. diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp index b6d2b8b1af3cf..cfbef8778b507 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp @@ -13,6 +13,7 @@ #include "clang/AST/DynamicRecursiveASTVisitor.h" #include "clang/AST/ExprCXX.h" #include "clang/Frontend/ASTUnit.h" +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Frontend/SSAFOptions.h" #include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h" #include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h" @@ -180,6 +181,38 @@ class PointerFlowTest : public TestFixture { return true; } + // Variant that mounts a virtual `<sys.h>` header (with + // `#pragma clang system_header` prepended) on an `-isystem` path, + // letting tests exercise the system-header contributor gate. + // Returns true on AST build + extractor instantiation success. + bool setUpTestWithSystemHeader(StringRef Code, StringRef SysHeaderCode, + bool ExtractFromSystemHeaders) { + Opts.ExtractFromSystemHeaders = ExtractFromSystemHeaders; + std::string SysWithPragma = + ("#pragma clang system_header\n" + SysHeaderCode).str(); + tooling::FileContentMappings VirtFiles = { + {"/sysinc/sys.h", SysWithPragma}}; + AST = tooling::buildASTFromCodeWithArgs( + Code, + {"-Wno-unused-value", "-Wno-int-to-pointer-cast", "-isystem/sysinc"}, + "input.cc", "clang-tool", + std::make_shared<PCHContainerOperations>(), + tooling::getClangStripDependencyFileAdjuster(), VirtFiles); + + for (auto &E : clang::ssaf::TUSummaryExtractorRegistry::entries()) { + if (E.getName() == PointerFlowEntitySummary::Name) { + Extractor = E.instantiate(Builder); + break; + } + } + if (!Extractor) { + ADD_FAILURE() << "failed to find PointerFlowTUSummaryExtractor"; + return false; + } + Extractor->HandleTranslationUnit(AST->getASTContext()); + return true; + } + template <typename ContributorDecl = NamedDecl> const PointerFlowEntitySummary *getEntitySummary(FindEntityByName Name) { const auto *ContributorDefn = @@ -1573,4 +1606,49 @@ TEST_F(PointerFlowTest, RefBindFunctionCallInitializer) { EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"r", 1U}, {"g", 1U, true}}})); } + +////////////////////////////////////////////////////////////// +// System-header contributor opt-out gate. // +// Spec: tu-summary-extraction, // +// "System-header contributor opt-out flag". // +////////////////////////////////////////////////////////////// + +// Default: ExtractFromSystemHeaders == true. A function decl in a +// `#pragma clang system_header`-marked included header IS enumerated +// as a contributor and produces an EntitySummary. +TEST_F(PointerFlowTest, SystemHeader_ExtractDefault) { + const char *SysHeader = "int *sys_gp; void sys_fn(int *p) { sys_gp = p; }\n"; + const char *Main = R"cpp( + #include <sys.h> + int *user_gp; + void user_fn(int *p) { user_gp = p; } + )cpp"; + ASSERT_TRUE(setUpTestWithSystemHeader(Main, SysHeader, + /*ExtractFromSystemHeaders=*/true)); + // sys_fn is in a system header but the default (extract-true) enumerates + // it as a contributor — summary is non-null. + EXPECT_NE(getEntitySummary("sys_fn"), nullptr); + // user_fn is enumerated either way (positive control). + EXPECT_NE(getEntitySummary("user_fn"), nullptr); +} + +// Opt-out: ExtractFromSystemHeaders == false. The system-header decl +// is NOT enumerated; getEntitySummary returns nullptr for it. The +// user-source decl is still enumerated (gate is per-decl, not TU-wide). +TEST_F(PointerFlowTest, SystemHeader_SkipOptOut) { + const char *SysHeader = "int *sys_gp; void sys_fn(int *p) { sys_gp = p; }\n"; + const char *Main = R"cpp( + #include <sys.h> + int *user_gp; + void user_fn(int *p) { user_gp = p; } + )cpp"; + ASSERT_TRUE(setUpTestWithSystemHeader(Main, SysHeader, + /*ExtractFromSystemHeaders=*/false)); + // sys_fn lives in a system header and is skipped at the + // ContributorFinder layer when ExtractFromSystemHeaders == false. + // getEntitySummary returns nullptr (no summary was built for it). + EXPECT_EQ(getEntitySummary("sys_fn"), nullptr); + // user_fn is in non-system code so the gate does not fire for it. + EXPECT_NE(getEntitySummary("user_fn"), nullptr); +} } // namespace >From 0c52648b945eec90f4257b8813f0a0069ae26b7d Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Tue, 23 Jun 2026 15:34:16 -0700 Subject: [PATCH 02/11] Fix code formatting --- .../Analyses/PointerFlow/PointerFlowTest.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp index cfbef8778b507..f1f2f5c89c23f 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp @@ -190,13 +190,11 @@ class PointerFlowTest : public TestFixture { Opts.ExtractFromSystemHeaders = ExtractFromSystemHeaders; std::string SysWithPragma = ("#pragma clang system_header\n" + SysHeaderCode).str(); - tooling::FileContentMappings VirtFiles = { - {"/sysinc/sys.h", SysWithPragma}}; + tooling::FileContentMappings VirtFiles = {{"/sysinc/sys.h", SysWithPragma}}; AST = tooling::buildASTFromCodeWithArgs( Code, {"-Wno-unused-value", "-Wno-int-to-pointer-cast", "-isystem/sysinc"}, - "input.cc", "clang-tool", - std::make_shared<PCHContainerOperations>(), + "input.cc", "clang-tool", std::make_shared<PCHContainerOperations>(), tooling::getClangStripDependencyFileAdjuster(), VirtFiles); for (auto &E : clang::ssaf::TUSummaryExtractorRegistry::entries()) { >From 5b7eb70267d1608f92c6fb76acc71eff691880b4 Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Tue, 23 Jun 2026 15:41:29 -0700 Subject: [PATCH 03/11] Fix code formatting --- .../Analyses/PointerFlow/PointerFlowExtractor.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp index 826b90806ea5d..7ebdae77f5083 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp @@ -13,9 +13,9 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" -#include "clang/Frontend/SSAFOptions.h" #include "clang/AST/Stmt.h" #include "clang/AST/TypeBase.h" +<<<<<<< HEAD:clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp #include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h" #include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h" #include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h" @@ -23,6 +23,16 @@ #include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h" #include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h" #include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h" +======= +#include "clang/Frontend/SSAFOptions.h" +#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h" +#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h" +#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h" +#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h" +#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h" +#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h" +#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h" +>>>>>>> b1cd54411a3a (Fix code formatting):clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/Sequence.h" >From 6b98ff3996ecf233992ff4b53d193d7b25d19070 Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Wed, 24 Jun 2026 15:30:38 -0700 Subject: [PATCH 04/11] Update clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Balázs Benics <[email protected]> --- .../ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp index 7b6523e3e545c..d10272f4428c3 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp @@ -42,9 +42,8 @@ class ContributorFinder : public DynamicRecursiveASTVisitor { } bool VisitFunctionDecl(FunctionDecl *D) override { - if (skipForSystemHeader(D)) - return true; - Contributors.insert(D); + if (!skipForSystemHeader(D)) + Contributors.insert(D); return true; } >From 22614b38e86023873de97bdd10abfa79171a31f4 Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Wed, 24 Jun 2026 15:31:57 -0700 Subject: [PATCH 05/11] Update clang/include/clang/Frontend/SSAFOptions.h MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Balázs Benics <[email protected]> --- clang/include/clang/Frontend/SSAFOptions.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/clang/include/clang/Frontend/SSAFOptions.h b/clang/include/clang/Frontend/SSAFOptions.h index 979501730e265..1d28f24147e35 100644 --- a/clang/include/clang/Frontend/SSAFOptions.h +++ b/clang/include/clang/Frontend/SSAFOptions.h @@ -43,9 +43,7 @@ class SSAFOptions { /// Extract from system-header declarations during SSAF contributor /// enumeration. Defaults to true to preserve the original behavior. - /// Cleared by `--ssaf-no-extract-from-system-headers` (negative-marshalled - /// flag) when the caller wants to scope contributor enumeration to - /// user-source decls. + /// Controlled by: --ssaf-no-extract-from-system-headers LLVM_PREFERRED_TYPE(bool) unsigned ExtractFromSystemHeaders : 1; >From 522e749f26463c2b223fc0a8dd97c49019787206 Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Wed, 24 Jun 2026 15:32:34 -0700 Subject: [PATCH 06/11] Update clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Balázs Benics <[email protected]> --- .../ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp index d10272f4428c3..3f1cfff36f61e 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp @@ -76,11 +76,6 @@ class ContributorFinder : public DynamicRecursiveASTVisitor { } private: - // Returns true when the contributor shall be skipped because its location - // is in a system header. The `Loc.isValid()` guard matches the in-tree - // precedent at `ReferenceBindingEntityExtractor.cpp` — compiler-generated - // decls (builtin FunctionDecls, implicit template instantiations) can reach - // the visitor with invalid locations and shall NOT be inadvertently skipped. bool skipForSystemHeader(const Decl *D) const { if (ExtractFromSystemHeaders) return false; >From 92ec428b1e88bcd660e51d059446405a6c67c86f Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Wed, 24 Jun 2026 15:33:05 -0700 Subject: [PATCH 07/11] Update clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Balázs Benics <[email protected]> --- .../Analyses/PointerFlow/PointerFlowTest.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp index f1f2f5c89c23f..b40a14bdabdaa 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp @@ -1623,11 +1623,8 @@ TEST_F(PointerFlowTest, SystemHeader_ExtractDefault) { )cpp"; ASSERT_TRUE(setUpTestWithSystemHeader(Main, SysHeader, /*ExtractFromSystemHeaders=*/true)); - // sys_fn is in a system header but the default (extract-true) enumerates - // it as a contributor — summary is non-null. - EXPECT_NE(getEntitySummary("sys_fn"), nullptr); - // user_fn is enumerated either way (positive control). - EXPECT_NE(getEntitySummary("user_fn"), nullptr); + EXPECT_TRUE(getEntitySummary("sys_fn")); + EXPECT_TRUE(getEntitySummary("user_fn")); } // Opt-out: ExtractFromSystemHeaders == false. The system-header decl >From 590a1375a9dff3fa844d1faa56b472b92b355c38 Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Wed, 24 Jun 2026 15:34:34 -0700 Subject: [PATCH 08/11] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Balázs Benics <[email protected]> --- .../Analyses/PointerFlow/PointerFlowTest.cpp | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp index b40a14bdabdaa..b3f34961a0cd2 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp @@ -1614,7 +1614,7 @@ TEST_F(PointerFlowTest, RefBindFunctionCallInitializer) { // Default: ExtractFromSystemHeaders == true. A function decl in a // `#pragma clang system_header`-marked included header IS enumerated // as a contributor and produces an EntitySummary. -TEST_F(PointerFlowTest, SystemHeader_ExtractDefault) { +TEST_F(PointerFlowTest, ExtractFromSystemHeadersByDefault) { const char *SysHeader = "int *sys_gp; void sys_fn(int *p) { sys_gp = p; }\n"; const char *Main = R"cpp( #include <sys.h> @@ -1627,10 +1627,7 @@ TEST_F(PointerFlowTest, SystemHeader_ExtractDefault) { EXPECT_TRUE(getEntitySummary("user_fn")); } -// Opt-out: ExtractFromSystemHeaders == false. The system-header decl -// is NOT enumerated; getEntitySummary returns nullptr for it. The -// user-source decl is still enumerated (gate is per-decl, not TU-wide). -TEST_F(PointerFlowTest, SystemHeader_SkipOptOut) { +TEST_F(PointerFlowTest, DontExtractFromSystemHeadersWhenOverridden) { const char *SysHeader = "int *sys_gp; void sys_fn(int *p) { sys_gp = p; }\n"; const char *Main = R"cpp( #include <sys.h> @@ -1639,11 +1636,7 @@ TEST_F(PointerFlowTest, SystemHeader_SkipOptOut) { )cpp"; ASSERT_TRUE(setUpTestWithSystemHeader(Main, SysHeader, /*ExtractFromSystemHeaders=*/false)); - // sys_fn lives in a system header and is skipped at the - // ContributorFinder layer when ExtractFromSystemHeaders == false. - // getEntitySummary returns nullptr (no summary was built for it). - EXPECT_EQ(getEntitySummary("sys_fn"), nullptr); - // user_fn is in non-system code so the gate does not fire for it. - EXPECT_NE(getEntitySummary("user_fn"), nullptr); + EXPECT_FALSE(getEntitySummary("sys_fn")); // 'sys_fn' is skipped. + EXPECT_TRUE(getEntitySummary("user_fn")); // 'user_fn' is still present. } } // namespace >From ac59271c8c36f5191f630996804737a838002245 Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Tue, 7 Jul 2026 16:11:31 -0700 Subject: [PATCH 09/11] Fix merge --- .../Analyses/PointerFlow/PointerFlowExtractor.cpp | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp index 7ebdae77f5083..42d5b5a7de041 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp @@ -15,7 +15,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/Stmt.h" #include "clang/AST/TypeBase.h" -<<<<<<< HEAD:clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp +#include "clang/Frontend/SSAFOptions.h" #include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h" #include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h" #include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h" @@ -23,16 +23,6 @@ #include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h" #include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h" #include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h" -======= -#include "clang/Frontend/SSAFOptions.h" -#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h" -#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h" -#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h" -#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h" -#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h" -#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h" -#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h" ->>>>>>> b1cd54411a3a (Fix code formatting):clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/STLFunctionalExtras.h" #include "llvm/ADT/Sequence.h" >From 3eededb672ea1ec731f126fd29f804a8c3e1eea1 Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Wed, 8 Jul 2026 12:30:48 -0700 Subject: [PATCH 10/11] Address PR feedback --- clang/include/clang/Options/Options.td | 5 +-- .../Analyses/SSAFAnalysesCommon.cpp | 8 +---- .../PointerFlow/system-header-opt-out.cpp | 35 +++++++++---------- clang/test/Analysis/Scalable/help.cpp | 2 +- 4 files changed, 20 insertions(+), 30 deletions(-) diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 847f2e3195474..2573c203a2c30 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -987,10 +987,7 @@ def _ssaf_no_extract_from_system_headers : Group<SSAF_Group>, Visibility<[ClangOption, CC1Option]>, HelpText< - "Skip declarations in system headers during SSAF contributor " - "enumeration. By default the SSAF TU summary extractors enumerate " - "system-header declarations alongside user-source declarations; " - "this flag opts out of that enumeration.">, + "Skip declarations in system headers during SSAF summary extraction">, MarshallingInfoNegativeFlag<SSAFOpts<"ExtractFromSystemHeaders">>; def Xarch__ : JoinedAndSeparate<["-"], "Xarch_">, diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp index 3f1cfff36f61e..9257b76d2be4c 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp @@ -66,13 +66,7 @@ class ContributorFinder : public DynamicRecursiveASTVisitor { } bool VisitLambdaExpr(LambdaExpr *L) override { - // TraverseLambdaExpr directly visits the body stmt, skipping the - // CXXMethodDecl, which is a contributor that needs to be collected. - // The system-header gate fires via the delegated VisitFunctionDecl - // (the call operator's spelling location is the lambda's source - // location), so no separate gate here. - VisitFunctionDecl(L->getCallOperator()); - return true; + return VisitFunctionDecl(L->getCallOperator()); } private: diff --git a/clang/test/Analysis/Scalable/PointerFlow/system-header-opt-out.cpp b/clang/test/Analysis/Scalable/PointerFlow/system-header-opt-out.cpp index dd04cb8753851..357e63d9d9f5c 100644 --- a/clang/test/Analysis/Scalable/PointerFlow/system-header-opt-out.cpp +++ b/clang/test/Analysis/Scalable/PointerFlow/system-header-opt-out.cpp @@ -1,42 +1,41 @@ -// Regression for clang-reforge-7y4 / iter-03: end-to-end verification -// of the --ssaf-no-extract-from-system-headers opt-out. Spec: -// tu-summary-extraction's "System-header contributor opt-out flag" -// requirement. +// Synthesise an -isystem header containing a benign user-named +// symbol. // REQUIRES: system-darwin || system-linux -// Setup: synthesise an -isystem header containing a benign user-named -// symbol (no USR collision — that case is exercised end-to-end by the -// parity-finale verification step against libJP2). -// RUN: rm -rf %t.dir -// RUN: mkdir -p %t.dir/sysinc -// RUN: printf '#pragma clang system_header\nint *sys_gp; void sys_fn(int *p) { sys_gp = p; }\n' > %t.dir/sysinc/sys.h +// RUN: rm -rf %t +// RUN: mkdir -p %t +// RUN: split-file %s %t // === Case A: flag absent (default extracts from system headers). === // The extractor enumerates both sys_fn and user_fn; the TU summary's // IdTable contains both names. -// RUN: rm -f %t-default.json -// RUN: %clang -c %s -o %t-default.o -isystem %t.dir/sysinc \ +// RUN: %clang -c %t/test.cpp -o %t/default.o -isystem %t/sysinc \ // RUN: --ssaf-extract-summaries=PointerFlow \ -// RUN: --ssaf-tu-summary-file=%t-default.json \ +// RUN: --ssaf-tu-summary-file=%t/default.json \ // RUN: --ssaf-compilation-unit-id=sys-default -// RUN: FileCheck --check-prefix=DEFAULT %s < %t-default.json +// RUN: FileCheck --check-prefix=DEFAULT %s < %t/default.json // DEFAULT-DAG: sys_fn // DEFAULT-DAG: user_fn // === Case B: flag present (opt-out skips system-header decls). === // The extractor skips sys_fn (system header) but keeps user_fn. // The TU summary's IdTable contains user_fn but NOT sys_fn. -// RUN: rm -f %t-optout.json -// RUN: %clang -c %s -o %t-optout.o -isystem %t.dir/sysinc \ +// RUN: %clang -c %t/test.cpp -o %t/optout.o -isystem %t/sysinc \ // RUN: --ssaf-extract-summaries=PointerFlow \ -// RUN: --ssaf-tu-summary-file=%t-optout.json \ +// RUN: --ssaf-tu-summary-file=%t/optout.json \ // RUN: --ssaf-no-extract-from-system-headers \ // RUN: --ssaf-compilation-unit-id=sys-optout -// RUN: FileCheck --check-prefix=OPTOUT %s < %t-optout.json +// RUN: FileCheck --check-prefix=OPTOUT %s < %t/optout.json // OPTOUT-NOT: sys_fn // OPTOUT: user_fn +//--- sysinc/sys.h +#pragma clang system_header +int *sys_gp; +void sys_fn(int *p) { sys_gp = p; } + +//--- test.cpp #include <sys.h> int *user_gp; diff --git a/clang/test/Analysis/Scalable/help.cpp b/clang/test/Analysis/Scalable/help.cpp index d34f09c65797d..4532e48d80a56 100644 --- a/clang/test/Analysis/Scalable/help.cpp +++ b/clang/test/Analysis/Scalable/help.cpp @@ -10,7 +10,7 @@ // 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-no-extract-from-system-headers -// HELP-NEXT: Skip declarations in system headers during SSAF contributor enumeration. By default the SSAF TU summary extractors enumerate system-header declarations alongside user-source declarations; this flag opts out of that enumeration. +// HELP-NEXT: Skip declarations in system headers during SSAF summary extraction // HELP-NEXT: --ssaf-tu-summary-file=<path>.<format> // HELP-NEXT: The output file for the extracted summaries. The extension selects which file format to use. >From bb01436c7b10bbcc5e3aa2decfbae3afde53c757 Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Wed, 8 Jul 2026 12:58:32 -0700 Subject: [PATCH 11/11] Fix formatting --- .../Analyses/PointerFlow/PointerFlowTest.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp index b3f34961a0cd2..c1e87710c1148 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp @@ -1604,7 +1604,6 @@ TEST_F(PointerFlowTest, RefBindFunctionCallInitializer) { EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"r", 1U}, {"g", 1U, true}}})); } - ////////////////////////////////////////////////////////////// // System-header contributor opt-out gate. // // Spec: tu-summary-extraction, // _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
