https://github.com/t-rasmud updated https://github.com/llvm/llvm-project/pull/205446
>From 62c23368f3987b6c4c0e6f4eb5a18ac19147ca4c 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 | 35 ++++++++- .../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, 182 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 f760d51ab5414..227f24f1f769f 100644 --- a/clang/include/clang/Frontend/SSAFOptions.h +++ b/clang/include/clang/Frontend/SSAFOptions.h @@ -47,10 +47,19 @@ class SSAFOptions { LLVM_PREFERRED_TYPE(bool) unsigned IncludeLocalEntities : 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; IncludeLocalEntities = false; + ExtractFromSystemHeaders = true; }; }; diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index 4974209b8db30..cba798c6aff95 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -990,6 +990,16 @@ def _ssaf_include_local_entities : "Include block-scope (function-local) declarations in extracted SSAF " "summaries. By default they are omitted.">, MarshallingInfoFlag<SSAFOpts<"IncludeLocalEntities">>; +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 1d6877ffbd8a7..2b69797a374e0 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -8078,6 +8078,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, 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); + 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 80cf371220298..f0775e3536fef 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 "clang/Frontend/SSAFOptions.h" #include "llvm/ADT/SetVector.h" @@ -37,22 +38,30 @@ class ContributorFinder : public DynamicRecursiveASTVisitor { llvm::SetVector<const NamedDecl *> Contributors; const SSAFOptions &Opts; - ContributorFinder(const SSAFOptions &Opts) : Opts(Opts) { + ContributorFinder(ASTContext &Ctx, const SSAFOptions &Opts, + bool ExtractFromSystemHeaders) + : Opts(Opts), 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: @@ -80,9 +89,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 @@ -146,8 +174,9 @@ class ContributorFactFinder : public DynamicRecursiveASTVisitor { void ssaf::findContributors( ASTContext &Ctx, const SSAFOptions &Options, llvm::DenseMap<const NamedDecl *, std::vector<const NamedDecl *>> - &Contributors) { - ContributorFinder Finder{Options}; + &Contributors, + bool ExtractFromSystemHeaders) { + ContributorFinder Finder{Ctx, Options, 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 2e602a1ad35b9..60bc4dfe2779b 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" @@ -87,7 +88,8 @@ inline void logWarningFromError(llvm::Error Err) { void findContributors( ASTContext &Ctx, const SSAFOptions &Options, 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 @@ -116,7 +118,8 @@ void extractAndAddSummaries(TUSummaryExtractor &Extractor, llvm::StringRef ExtractorName = "") { llvm::DenseMap<const NamedDecl *, std::vector<const NamedDecl *>> Contributors; - findContributors(Ctx, Extractor.getOptions(), Contributors); + findContributors(Ctx, Extractor.getOptions(), Contributors, + Extractor.getOptions().ExtractFromSystemHeaders); for (const auto &[Cano, Decls] : Contributors) { assert(!Decls.empty() && "'findContributors' guarantees that 'Decls' are non-empty"); 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 3feae2dfaa456..35b03af0677a0 100644 --- a/clang/test/Analysis/Scalable/help.cpp +++ b/clang/test/Analysis/Scalable/help.cpp @@ -11,6 +11,8 @@ // 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-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 a56a9072be097..906faf92b3a90 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" @@ -181,6 +182,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 = @@ -1618,4 +1651,49 @@ TEST_F(PointerFlowTest, LocalPointerReportedWhenIncluded) { EXPECT_TRUE(getEntitySummary("foo")); } + +////////////////////////////////////////////////////////////// +// 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 61cdcddbb607c83262c692d68195fe4138143811 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 906faf92b3a90..22f92ebf97e24 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp @@ -191,13 +191,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 7278bcd82c5c6a9310849f8ebfb58c08f721e436 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 74714b1099c6c83969194633ceed3975846871b8 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 f0775e3536fef..8b665d39e77f9 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp @@ -46,9 +46,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 b0fb7b0607701d700407eb02733f473aa9da7f6c 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 227f24f1f769f..737d8809ce24e 100644 --- a/clang/include/clang/Frontend/SSAFOptions.h +++ b/clang/include/clang/Frontend/SSAFOptions.h @@ -49,9 +49,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 f97334dc1e2eb07a5f10f8d26a1f236b855d817e 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 8b665d39e77f9..921c004e21162 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp @@ -96,11 +96,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 a0c15e0e29ace89625e874304074933d54db9f07 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 22f92ebf97e24..77a879ec6148c 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp @@ -1668,11 +1668,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 8ffe7e487f95a454d3d0b308198448ba4dd168a6 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 77a879ec6148c..1260aad81a8bf 100644 --- a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp +++ b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp @@ -1659,7 +1659,7 @@ TEST_F(PointerFlowTest, LocalPointerReportedWhenIncluded) { // 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> @@ -1672,10 +1672,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> @@ -1684,11 +1681,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 340c798e15dfaa12654fd6d4af47a743588050fb 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 54ee420ee34f0a150345893e5ec51fc05def2b22 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 cba798c6aff95..496a050c2cb1e 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -995,10 +995,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 921c004e21162..4243ac611b6c1 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp +++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp @@ -86,13 +86,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 35b03af0677a0..4e210abe35b9f 100644 --- a/clang/test/Analysis/Scalable/help.cpp +++ b/clang/test/Analysis/Scalable/help.cpp @@ -12,7 +12,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 5a846ebd5a3bae50b32d16a91514f2fac1f063ba Mon Sep 17 00:00:00 2001 From: Rashmi Mudduluru <[email protected]> Date: Tue, 14 Jul 2026 13:47:25 -0700 Subject: [PATCH 11/11] Fix code formatting --- clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h index 60bc4dfe2779b..95e3411cec386 100644 --- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h +++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h @@ -119,7 +119,7 @@ void extractAndAddSummaries(TUSummaryExtractor &Extractor, llvm::DenseMap<const NamedDecl *, std::vector<const NamedDecl *>> Contributors; findContributors(Ctx, Extractor.getOptions(), Contributors, - Extractor.getOptions().ExtractFromSystemHeaders); + Extractor.getOptions().ExtractFromSystemHeaders); for (const auto &[Cano, Decls] : Contributors) { assert(!Decls.empty() && "'findContributors' guarantees that 'Decls' are non-empty"); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
