[clang] [llvm] [clang][ssaf] Shorten directory name to ScalableStaticAnalysis (PR #204697)
Aviral Goel via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 24 09:49:31 PDT 2026
https://github.com/aviralg updated https://github.com/llvm/llvm-project/pull/204697
>From 3bfefd3af0842dceb6e533fd17beeb755fccb7c0 Mon Sep 17 00:00:00 2001
From: Jan Korous <jkorous at apple.com>
Date: Thu, 18 Jun 2026 15:57:45 -0700
Subject: [PATCH 1/6] [clang][ssaf] Shorten directory name to
ScalableStaticAnalysis
The directory name ScalableStaticAnalysisFramework produces build paths
that exceed Windows' MAX_PATH limit (260 chars) on downstream CI bots.
The clang-ssaf-format / clang-ssaf-linker tool names and SSAF-prefixed
source filenames are unchanged.
Assisted-By: Claude Opus 4.7
---
.github/new-prs-labeler.yml | 8 ++--
.../developer-docs/ForceLinkerHeaders.rst | 14 +++---
.../developer-docs/HowToExtend.rst | 16 +++----
.../SummaryExtractionInternals.rst | 0
.../developer-docs/index.rst | 0
.../index.rst | 0
.../user-docs/SummaryExtraction.rst | 8 ++--
clang/docs/index.rst | 2 +-
.../clang/Basic/DiagnosticFrontendKinds.td | 10 ++--
clang/include/clang/Basic/DiagnosticGroups.td | 2 +-
.../Analyses/CallGraph/CallGraphSummary.h | 12 ++---
.../EntityPointerLevel/EntityPointerLevel.h | 10 ++--
.../EntityPointerLevelFormat.h | 10 ++--
.../UnsafeBufferUsage/UnsafeBufferUsage.h | 12 ++---
.../UnsafeBufferUsage/UnsafeBufferUsageTest.h | 10 ++--
.../Core/ASTEntityMapping.h | 8 ++--
.../Core/EntityLinker/EntityLinker.h | 8 ++--
.../Core/EntityLinker/EntitySummaryEncoding.h | 8 ++--
.../Core/EntityLinker/LUSummary.h | 20 ++++----
.../Core/EntityLinker/LUSummaryEncoding.h | 20 ++++----
.../Core/EntityLinker/TUSummaryEncoding.h | 20 ++++----
.../Core/Model/BuildNamespace.h | 6 +--
.../Core/Model/EntityId.h | 6 +--
.../Core/Model/EntityIdTable.h | 10 ++--
.../Core/Model/EntityLinkage.h | 6 +--
.../Core/Model/EntityName.h | 8 ++--
.../Core/Model/PrivateFieldNames.def | 0
.../Core/Model/SummaryName.h | 6 +--
.../Core/Serialization/JSONFormat.h | 10 ++--
.../Core/Serialization/SerializationFormat.h | 26 +++++-----
.../SerializationFormatRegistry.h | 10 ++--
.../Core/SummaryData/LUSummaryConsumer.h | 12 ++---
.../Core/SummaryData/SummaryData.h | 6 +--
.../Core/SummaryData/SummaryDataBuilder.h | 18 +++----
.../SummaryData/SummaryDataBuilderRegistry.h | 8 ++--
.../Core/SummaryData/SummaryDataStore.h | 14 +++---
.../Core/SummaryData/SummaryDataTraits.h | 8 ++--
.../Core/Support/ErrorBuilder.h | 6 +--
.../Core/Support/FormatProviders.h | 18 +++----
.../Core/TUSummary/EntitySummary.h | 8 ++--
.../Core/TUSummary/ExtractorRegistry.h | 10 ++--
.../Core/TUSummary/TUSummary.h | 20 ++++----
.../Core/TUSummary/TUSummaryBuilder.h | 10 ++--
.../Core/TUSummary/TUSummaryExtractor.h | 6 +--
.../Core/WholeProgramAnalysis/AnalysisBase.h | 8 ++--
.../WholeProgramAnalysis/AnalysisDriver.h | 10 ++--
.../Core/WholeProgramAnalysis/AnalysisName.h | 6 +--
.../WholeProgramAnalysis/AnalysisRegistry.h | 14 +++---
.../WholeProgramAnalysis/AnalysisResult.h | 6 +--
.../WholeProgramAnalysis/AnalysisTraits.h | 8 ++--
.../WholeProgramAnalysis/DerivedAnalysis.h | 18 +++----
.../WholeProgramAnalysis/SummaryAnalysis.h | 20 ++++----
.../Core/WholeProgramAnalysis/WPASuite.h | 18 +++----
.../TUSummaryExtractorFrontendAction.h | 6 +--
.../SSAFBuiltinForceLinker.h | 8 ++--
.../SSAFForceLinker.h | 8 ++--
.../Tool/Utils.h | 8 ++--
clang/include/module.modulemap | 6 +--
clang/lib/CMakeLists.txt | 2 +-
clang/lib/Driver/CMakeLists.txt | 6 +--
clang/lib/Driver/Driver.cpp | 6 +--
clang/lib/FrontendTool/CMakeLists.txt | 6 +--
.../ExecuteCompilerInvocation.cpp | 4 +-
.../Analyses/CMakeLists.txt | 4 +-
.../Analyses/CallGraph/CallGraphExtractor.cpp | 8 ++--
.../CallGraph/CallGraphJSONFormat.cpp | 8 ++--
.../EntityPointerLevel/EntityPointerLevel.cpp | 8 ++--
.../Analyses/SSAFAnalysesCommon.cpp | 0
.../Analyses/SSAFAnalysesCommon.h | 6 +--
.../UnsafeBufferUsage/UnsafeBufferUsage.cpp | 10 ++--
.../UnsafeBufferUsageExtractor.cpp | 14 +++---
.../CMakeLists.txt | 0
.../Core/ASTEntityMapping.cpp | 4 +-
.../Core/CMakeLists.txt | 2 +-
.../Core/EntityLinker/EntityLinker.cpp | 14 +++---
.../Core/Model/BuildNamespace.cpp | 2 +-
.../Core/Model/EntityId.cpp | 2 +-
.../Core/Model/EntityIdTable.cpp | 2 +-
.../Core/Model/EntityLinkage.cpp | 2 +-
.../Core/Model/EntityName.cpp | 2 +-
.../Core/Model/SummaryName.cpp | 2 +-
.../Core/ModelStringConversions.h | 10 ++--
.../JSONFormat/JSONEntitySummaryEncoding.cpp | 0
.../JSONFormat/JSONEntitySummaryEncoding.h | 10 ++--
.../JSONFormat/JSONFormatImpl.cpp | 2 +-
.../Serialization/JSONFormat/JSONFormatImpl.h | 18 +++----
.../Serialization/JSONFormat/LUSummary.cpp | 2 +-
.../JSONFormat/LUSummaryEncoding.cpp | 2 +-
.../Serialization/JSONFormat/TUSummary.cpp | 2 +-
.../JSONFormat/TUSummaryEncoding.cpp | 2 +-
.../Serialization/JSONFormat/WPASuite.cpp | 2 +-
.../SerializationFormatRegistry.cpp | 2 +-
.../Core/SummaryData/LUSummaryConsumer.cpp | 6 +--
.../SummaryDataBuilderRegistry.cpp | 2 +-
.../Core/Support/ErrorBuilder.cpp | 2 +-
.../Core/TUSummary/ExtractorRegistry.cpp | 2 +-
.../Core/TUSummary/TUSummaryBuilder.cpp | 8 ++--
.../WholeProgramAnalysis/AnalysisDriver.cpp | 10 ++--
.../WholeProgramAnalysis/AnalysisName.cpp | 2 +-
.../WholeProgramAnalysis/AnalysisRegistry.cpp | 4 +-
.../Frontend/CMakeLists.txt | 15 ++++++
.../TUSummaryExtractorFrontendAction.cpp | 12 ++---
.../Plugins/CMakeLists.txt | 2 +-
.../Plugins/ExamplePlugin/AnalysisResults.h | 6 +--
.../Plugins/ExamplePlugin/CMakeLists.txt | 2 +-
.../Plugins/ExamplePlugin/PairsAnalysis.cpp | 10 ++--
.../Plugins/ExamplePlugin/TagsAnalysis.cpp | 10 ++--
.../ExamplePlugin/TagsPairsAnalysis.cpp | 6 +--
.../Tool/CMakeLists.txt | 11 +++++
.../Tool/Utils.cpp | 2 +-
.../Frontend/CMakeLists.txt | 15 ------
.../Tool/CMakeLists.txt | 11 -----
.../Scalable/command-line-interface.cpp | 10 ++--
.../Analysis/Scalable/downgradable-errors.cpp | 10 ++--
clang/tools/clang-ssaf-format/CMakeLists.txt | 6 +--
clang/tools/clang-ssaf-format/SSAFFormat.cpp | 12 ++---
clang/tools/clang-ssaf-linker/CMakeLists.txt | 6 +--
clang/tools/clang-ssaf-linker/SSAFLinker.cpp | 12 ++---
clang/unittests/CMakeLists.txt | 2 +-
.../ASTEntityMappingTest.cpp | 2 +-
.../CallGraph/CallGraphExtractorTest.cpp | 10 ++--
.../UnsafeBufferUsageTest.cpp | 22 ++++-----
.../BuildNamespaceTest.cpp | 4 +-
.../CMakeLists.txt | 6 +--
.../EntityIdTableTest.cpp | 8 ++--
.../EntityIdTest.cpp | 8 ++--
.../EntityLinkageTest.cpp | 4 +-
.../EntityLinkerTest.cpp | 20 ++++----
.../EntityNameTest.cpp | 6 +--
.../ErrorBuilderTest.cpp | 2 +-
.../TUSummaryExtractorFrontendActionTest.cpp | 10 ++--
.../ModelStringConversionsTest.cpp | 2 +-
.../Registries/FancyAnalysisData.cpp | 2 +-
.../Registries/MockSerializationFormat.cpp | 18 +++----
.../Registries/MockSerializationFormat.h | 10 ++--
.../Registries/MockSummaryExtractor1.cpp | 4 +-
.../Registries/MockSummaryExtractor2.cpp | 4 +-
.../Registries/MockTUSummaryBuilder.h | 8 ++--
.../SerializationFormatRegistryTest.cpp | 4 +-
.../SummaryExtractorRegistryTest.cpp | 4 +-
.../SSAFBuiltinTestForceLinker.h | 6 +--
.../SSAFTestForceLinker.h | 6 +--
.../JSONFormatTest/JSONFormatTest.cpp | 2 +-
.../JSONFormatTest/JSONFormatTest.h | 6 +--
.../JSONFormatTest/LUSummaryTest.cpp | 6 +--
.../JSONFormatTest/TUSummaryTest.cpp | 6 +--
.../SummaryData/SummaryDataTest.cpp | 20 ++++----
.../SummaryNameTest.cpp | 4 +-
.../TUSummaryBuilderTest.cpp | 16 +++----
.../TestFixture.cpp | 10 ++--
.../ScalableStaticAnalysis/TestFixture.h | 47 +++++++++++++++++++
.../AnalysisDriverTest.cpp | 26 +++++-----
.../TestFixture.h | 47 -------------------
.../gn/secondary/clang/lib/Driver/BUILD.gn | 6 +--
.../secondary/clang/lib/FrontendTool/BUILD.gn | 6 +--
.../Analyses/BUILD.gn | 4 +-
.../Core/BUILD.gn | 2 +-
.../Frontend/BUILD.gn | 4 +-
.../Tool/BUILD.gn | 4 +-
.../clang/tools/clang-ssaf-format/BUILD.gn | 6 +--
.../clang/tools/clang-ssaf-linker/BUILD.gn | 6 +--
.../gn/secondary/clang/unittests/BUILD.gn | 2 +-
.../BUILD.gn | 6 +--
.../llvm-project-overlay/clang/BUILD.bazel | 28 +++++------
.../clang/unittests/BUILD.bazel | 8 ++--
165 files changed, 689 insertions(+), 689 deletions(-)
rename clang/docs/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/developer-docs/ForceLinkerHeaders.rst (89%)
rename clang/docs/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/developer-docs/HowToExtend.rst (91%)
rename clang/docs/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/developer-docs/SummaryExtractionInternals.rst (100%)
rename clang/docs/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/developer-docs/index.rst (100%)
rename clang/docs/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/index.rst (100%)
rename clang/docs/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/user-docs/SummaryExtraction.rst (84%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/CallGraph/CallGraphSummary.h (74%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/EntityPointerLevel/EntityPointerLevel.h (91%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h (59%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h (74%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h (63%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/ASTEntityMapping.h (82%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/EntityLinker/EntityLinker.h (91%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/EntityLinker/EntitySummaryEncoding.h (79%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/EntityLinker/LUSummary.h (67%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/EntityLinker/LUSummaryEncoding.h (69%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/EntityLinker/TUSummaryEncoding.h (70%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/BuildNamespace.h (95%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/EntityId.h (88%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/EntityIdTable.h (79%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/EntityLinkage.h (87%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/EntityName.h (87%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/PrivateFieldNames.def (100%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/SummaryName.h (84%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/JSONFormat.h (95%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/SerializationFormat.h (89%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/SerializationFormatRegistry.h (87%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/SummaryData/LUSummaryConsumer.h (88%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/SummaryData/SummaryData.h (76%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/SummaryData/SummaryDataBuilder.h (83%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/SummaryData/SummaryDataBuilderRegistry.h (85%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/SummaryData/SummaryDataStore.h (86%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/SummaryData/SummaryDataTraits.h (80%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Support/ErrorBuilder.h (96%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Support/FormatProviders.h (78%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/TUSummary/EntitySummary.h (69%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/TUSummary/ExtractorRegistry.h (83%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/TUSummary/TUSummary.h (59%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/TUSummary/TUSummaryBuilder.h (86%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/TUSummary/TUSummaryExtractor.h (72%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/AnalysisBase.h (82%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/AnalysisDriver.h (88%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/AnalysisName.h (85%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/AnalysisRegistry.h (85%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/AnalysisResult.h (75%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/AnalysisTraits.h (75%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/DerivedAnalysis.h (86%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/SummaryAnalysis.h (83%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/WPASuite.h (81%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Frontend/TUSummaryExtractorFrontendAction.h (78%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/SSAFBuiltinForceLinker.h (88%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/SSAFForceLinker.h (76%)
rename clang/include/clang/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Tool/Utils.h (92%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/CMakeLists.txt (76%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/CallGraph/CallGraphExtractor.cpp (91%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/CallGraph/CallGraphJSONFormat.cpp (95%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/EntityPointerLevel/EntityPointerLevel.cpp (96%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/SSAFAnalysesCommon.cpp (100%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/SSAFAnalysesCommon.h (90%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp (88%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp (86%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/CMakeLists.txt (100%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/ASTEntityMapping.cpp (93%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/CMakeLists.txt (94%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/EntityLinker/EntityLinker.cpp (92%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/BuildNamespace.cpp (96%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/EntityId.cpp (88%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/EntityIdTable.cpp (92%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/EntityLinkage.cpp (93%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/EntityName.cpp (94%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Model/SummaryName.cpp (88%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/ModelStringConversions.h (87%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp (100%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h (76%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/JSONFormat/JSONFormatImpl.cpp (99%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/JSONFormat/JSONFormatImpl.h (89%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/JSONFormat/LUSummary.cpp (98%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp (98%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/JSONFormat/TUSummary.cpp (98%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp (98%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/JSONFormat/WPASuite.cpp (98%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Serialization/SerializationFormatRegistry.cpp (92%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/SummaryData/LUSummaryConsumer.cpp (90%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/SummaryData/SummaryDataBuilderRegistry.cpp (91%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/Support/ErrorBuilder.cpp (96%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/TUSummary/ExtractorRegistry.cpp (94%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/TUSummary/TUSummaryBuilder.cpp (74%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/AnalysisDriver.cpp (93%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/AnalysisName.cpp (86%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/WholeProgramAnalysis/AnalysisRegistry.cpp (89%)
create mode 100644 clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Frontend/TUSummaryExtractorFrontendAction.cpp (92%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Plugins/CMakeLists.txt (98%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Plugins/ExamplePlugin/AnalysisResults.h (81%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Plugins/ExamplePlugin/CMakeLists.txt (87%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Plugins/ExamplePlugin/PairsAnalysis.cpp (94%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Plugins/ExamplePlugin/TagsAnalysis.cpp (92%)
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp (94%)
create mode 100644 clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt
rename clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Tool/Utils.cpp (99%)
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/ASTEntityMappingTest.cpp (99%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/CallGraph/CallGraphExtractorTest.cpp (97%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp (95%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/BuildNamespaceTest.cpp (96%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/CMakeLists.txt (89%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/EntityIdTableTest.cpp (91%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/EntityIdTest.cpp (89%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/EntityLinkageTest.cpp (95%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/EntityLinkerTest.cpp (96%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/EntityNameTest.cpp (92%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/ErrorBuilderTest.cpp (98%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Frontend/TUSummaryExtractorFrontendActionTest.cpp (96%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/ModelStringConversionsTest.cpp (97%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Registries/FancyAnalysisData.cpp (96%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Registries/MockSerializationFormat.cpp (91%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Registries/MockSerializationFormat.h (84%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Registries/MockSummaryExtractor1.cpp (89%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Registries/MockSummaryExtractor2.cpp (89%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Registries/MockTUSummaryBuilder.h (69%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Registries/SerializationFormatRegistryTest.cpp (95%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Registries/SummaryExtractorRegistryTest.cpp (96%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/SSAFBuiltinTestForceLinker.h (88%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/SSAFTestForceLinker.h (75%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Serialization/JSONFormatTest/JSONFormatTest.cpp (99%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Serialization/JSONFormatTest/JSONFormatTest.h (95%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Serialization/JSONFormatTest/LUSummaryTest.cpp (99%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Serialization/JSONFormatTest/TUSummaryTest.cpp (99%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/SummaryData/SummaryDataTest.cpp (94%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/SummaryNameTest.cpp (93%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/TUSummaryBuilderTest.cpp (94%)
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/TestFixture.cpp (76%)
create mode 100644 clang/unittests/ScalableStaticAnalysis/TestFixture.h
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/WholeProgramAnalysis/AnalysisDriverTest.cpp (94%)
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h
rename llvm/utils/gn/secondary/clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Analyses/BUILD.gn (80%)
rename llvm/utils/gn/secondary/clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Core/BUILD.gn (95%)
rename llvm/utils/gn/secondary/clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Frontend/BUILD.gn (70%)
rename llvm/utils/gn/secondary/clang/lib/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Tool/BUILD.gn (60%)
rename llvm/utils/gn/secondary/clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/BUILD.gn (89%)
diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml
index d8cba3bfa7272..469dc511caf63 100644
--- a/.github/new-prs-labeler.yml
+++ b/.github/new-prs-labeler.yml
@@ -698,11 +698,11 @@ clang:analysis:
clang:ssaf:
- changed-files:
- any-glob-to-any-file:
- - clang/docs/ScalableStaticAnalysisFramework/**
- - clang/include/clang/ScalableStaticAnalysisFramework/**
- - clang/lib/ScalableStaticAnalysisFramework/**
+ - clang/docs/ScalableStaticAnalysis/**
+ - clang/include/clang/ScalableStaticAnalysis/**
+ - clang/lib/ScalableStaticAnalysis/**
- clang/test/Analysis/Scalable/**
- - clang/unittests/ScalableStaticAnalysisFramework/**
+ - clang/unittests/ScalableStaticAnalysis/**
clang:static analyzer:
- changed-files:
diff --git a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst b/clang/docs/ScalableStaticAnalysis/developer-docs/ForceLinkerHeaders.rst
similarity index 89%
rename from clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
rename to clang/docs/ScalableStaticAnalysis/developer-docs/ForceLinkerHeaders.rst
index c04b2b786308f..1a369404699da 100644
--- a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
+++ b/clang/docs/ScalableStaticAnalysis/developer-docs/ForceLinkerHeaders.rst
@@ -66,21 +66,21 @@ Header hierarchy
SSAFForceLinker.h (umbrella — include this in binaries)
└── SSAFBuiltinForceLinker.h (upstream built-in anchors only)
-- ``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h`` — anchors for
+- ``clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h`` — anchors for
upstream-provided (built-in) extractors and formats (e.g. ``JSONFormat``).
-- ``clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h`` — umbrella header
+- ``clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h`` — umbrella header
that includes ``SSAFBuiltinForceLinker.h``. This is the header that
downstream projects should modify to add their own force-linker includes
(see :doc:`HowToExtend`).
Include the umbrella header with ``// IWYU pragma: keep`` in any translation
unit that must guarantee all registrations are active — typically the entry
-point of a binary that uses ``clangScalableStaticAnalysisFrameworkCore``:
+point of a binary that uses ``clangScalableStaticAnalysisCore``:
.. code-block:: c++
// In ExecuteCompilerInvocation.cpp
- #include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
+ #include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
Naming convention
=================
@@ -103,10 +103,10 @@ library, regardless of whether any symbols are referenced:
.. code-block:: bash
# GNU ld / lld (Linux, BSD)
- -Wl,--whole-archive -lclangScalableStaticAnalysisFrameworkCore -Wl,--no-whole-archive
+ -Wl,--whole-archive -lclangScalableStaticAnalysisCore -Wl,--no-whole-archive
# Apple ld
- -Wl,-force_load,libclangScalableStaticAnalysisFrameworkCore.a
+ -Wl,-force_load,libclangScalableStaticAnalysisCore.a
Since CMake 3.24, the ``$<LINK_LIBRARY:WHOLE_ARCHIVE,...>`` generator expression
provides a portable way to do the same:
@@ -114,7 +114,7 @@ provides a portable way to do the same:
.. code-block:: cmake
target_link_libraries(clang PRIVATE
- "$<LINK_LIBRARY:WHOLE_ARCHIVE,clangScalableStaticAnalysisFrameworkCore>")
+ "$<LINK_LIBRARY:WHOLE_ARCHIVE,clangScalableStaticAnalysisCore>")
**Why we did not choose this approach**:
diff --git a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst b/clang/docs/ScalableStaticAnalysis/developer-docs/HowToExtend.rst
similarity index 91%
rename from clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
rename to clang/docs/ScalableStaticAnalysis/developer-docs/HowToExtend.rst
index 7d92d7e6f2de7..0c94cfca54dee 100644
--- a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
+++ b/clang/docs/ScalableStaticAnalysis/developer-docs/HowToExtend.rst
@@ -10,7 +10,7 @@ SSAF is designed to be extensible with new **summary extractors** and **serializ
Extensions can be added in three ways:
#. **Statically, in-tree** — built as part of the upstream LLVM/Clang tree.
-#. **Statically, out-of-tree (downstream)** — built in a downstream fork or project that links ``clangScalableStaticAnalysisFrameworkCore`` as a static library.
+#. **Statically, out-of-tree (downstream)** — built in a downstream fork or project that links ``clangScalableStaticAnalysisCore`` as a static library.
#. **Dynamically, via plugins** — loaded at runtime as shared objects.
All three approaches use the same ``llvm::Registry``-based registration mechanism.
@@ -28,7 +28,7 @@ Step 1: Implement the extractor
.. code-block:: c++
//--- MyExtractor.h
- #include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
+ #include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
namespace clang::ssaf {
@@ -49,7 +49,7 @@ Step 2: Register the extractor
//--- MyExtractor.cpp
#include "MyExtractor.h"
- #include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+ #include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
using namespace clang::ssaf;
@@ -74,7 +74,7 @@ Add the following to the appropriate force-linker header:
SSAFMyExtractorAnchorSource;
For **in-tree** additions, add this to
-``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h``.
+``clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h``.
For **downstream** additions, see `Out-of-tree (downstream) extensions`_ below.
@@ -93,7 +93,7 @@ Your format class must inherit from ``SerializationFormat`` and define a ``Forma
.. code-block:: c++
//--- MyFormat.h
- #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
+ #include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
#include "clang/Support/Compiler.h"
#include "llvm/Support/Registry.h"
@@ -121,7 +121,7 @@ Step 2: Register the format
//--- MyFormat.cpp
#include "MyFormat.h"
- #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+ #include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
using namespace clang::ssaf;
@@ -172,8 +172,8 @@ In-tree extensions
For extensions that are part of the upstream LLVM/Clang tree:
-#. Add the anchor to ``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h``.
-#. Add the source files to the ``clangScalableStaticAnalysisFrameworkCore`` CMake library target.
+#. Add the anchor to ``clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h``.
+#. Add the source files to the ``clangScalableStaticAnalysisCore`` CMake library target.
#. That's it — the ``SSAFForceLinker.h`` umbrella includes ``SSAFBuiltinForceLinker.h``
transitively, so any binary that includes the umbrella will pull in the registration.
diff --git a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/SummaryExtractionInternals.rst b/clang/docs/ScalableStaticAnalysis/developer-docs/SummaryExtractionInternals.rst
similarity index 100%
rename from clang/docs/ScalableStaticAnalysisFramework/developer-docs/SummaryExtractionInternals.rst
rename to clang/docs/ScalableStaticAnalysis/developer-docs/SummaryExtractionInternals.rst
diff --git a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/index.rst b/clang/docs/ScalableStaticAnalysis/developer-docs/index.rst
similarity index 100%
rename from clang/docs/ScalableStaticAnalysisFramework/developer-docs/index.rst
rename to clang/docs/ScalableStaticAnalysis/developer-docs/index.rst
diff --git a/clang/docs/ScalableStaticAnalysisFramework/index.rst b/clang/docs/ScalableStaticAnalysis/index.rst
similarity index 100%
rename from clang/docs/ScalableStaticAnalysisFramework/index.rst
rename to clang/docs/ScalableStaticAnalysis/index.rst
diff --git a/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst b/clang/docs/ScalableStaticAnalysis/user-docs/SummaryExtraction.rst
similarity index 84%
rename from clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
rename to clang/docs/ScalableStaticAnalysis/user-docs/SummaryExtraction.rst
index 96892cfa5fdea..fd58bf3fe931e 100644
--- a/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/SummaryExtraction.rst
@@ -30,8 +30,8 @@ Diagnostics
***********
In case the ``--ssaf-*`` flags are used incorrectly, or some extractor fails to implement the desired serialization format
-or just happens to have an error, then the error is forwarded as a ``scalable-static-analysis-framework`` error.
-These errors can be downgraded into warnings using ``-Wno-error=scalable-static-analysis-framework``.
-These errors can be completely suppressed using ``-Wno-scalable-static-analysis-framework``.
+or just happens to have an error, then the error is forwarded as a ``scalable-static-analysis`` error.
+These errors can be downgraded into warnings using ``-Wno-error=scalable-static-analysis``.
+These errors can be completely suppressed using ``-Wno-scalable-static-analysis``.
-See the `diagnostic flags <https://clang.llvm.org/docs/DiagnosticsReference.html#wscalable-static-analysis-framework>`_ for the full list of diagnostics controlled by ``-Wscalable-static-analysis-framework``.
+See the `diagnostic flags <https://clang.llvm.org/docs/DiagnosticsReference.html#wscalable-static-analysis>`_ for the full list of diagnostics controlled by ``-Wscalable-static-analysis``.
diff --git a/clang/docs/index.rst b/clang/docs/index.rst
index 898667e36011d..05abb3e80e3c1 100644
--- a/clang/docs/index.rst
+++ b/clang/docs/index.rst
@@ -29,7 +29,7 @@ Using Clang as a Compiler
ThreadSafetyAnalysis
LifetimeSafety
SafeBuffers
- ScalableStaticAnalysisFramework/index
+ ScalableStaticAnalysis/index
DataFlowAnalysisIntro
FunctionEffectAnalysis
AddressSanitizer
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index f384a97b6825e..6e0516a3834bc 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -403,25 +403,25 @@ def warn_profile_data_misexpect : Warning<
def warn_ssaf_extract_tu_summary_file_unknown_output_format :
Warning<"unknown output summary file format '%0' "
"specified by '--ssaf-tu-summary-file=%1'">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def warn_ssaf_extract_tu_summary_file_unknown_format :
Warning<"failed to parse the value of '--ssaf-tu-summary-file=%0' "
"the value must follow the '<path>.<format>' pattern">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def warn_ssaf_must_enable_summary_extractors :
Warning<"must enable some summary extractors using the "
"'--ssaf-extract-summaries=' option">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def warn_ssaf_extract_summary_unknown_extractor_name :
Warning<"no summary extractor%s0 %plural{1:was|:were}0 registered with name: %1">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def warn_ssaf_write_tu_summary_failed :
Warning<"failed to write TU summary to '%0': %1">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def err_extract_api_ignores_file_not_found :
Error<"file '%0' specified by '--extract-api-ignores=' not found">, DefaultFatal;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 74f9fab14d82c..e2b3852c55539 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1926,7 +1926,7 @@ def BitIntExtension : DiagGroup<"bit-int-extension">;
def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">;
// Warnings related to the "Scalable Static Analysis Framework" - SSAF.
-def ScalableStaticAnalysisFramework : DiagGroup<"scalable-static-analysis-framework">;
+def ScalableStaticAnalysis : DiagGroup<"scalable-static-analysis">;
// Warnings about using the non-standard extension having an explicit specialization
// with a storage class specifier.
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h
similarity index 74%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h
rename to clang/include/clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h
index 8056b1001a216..e3a335384792a 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
#include <set>
namespace clang::ssaf {
@@ -51,4 +51,4 @@ struct CallGraphSummary final : public EntitySummary {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h
similarity index 91%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
rename to clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h
index 429bb74fb417e..79b66e40be0dd 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
#include "clang/AST/Expr.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include <set>
@@ -120,4 +120,4 @@ createEntityPointerLevel(const NamedDecl *ND,
EntityPointerLevel incrementPointerLevel(const EntityPointerLevel &E);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
similarity index 59%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
rename to clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
index 7b125edb1fb7f..e34fd1007b5fd 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
namespace clang::ssaf {
llvm::json::Value
@@ -22,4 +22,4 @@ entityPointerLevelFromJSON(const llvm::json::Value &EPLData,
JSONFormat::EntityIdFromJSONFn EntityIdFromJSON);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
similarity index 74%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
rename to clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
index ec0c4334a802e..17ac0a94f3746 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
namespace clang::ssaf {
/// An UnsafeBufferUsageEntitySummary contains a set of EntityPointerLevels
@@ -47,4 +47,4 @@ class UnsafeBufferUsageEntitySummary final : public EntitySummary {
};
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h
similarity index 63%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h
rename to clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h
index 6a2d1161246f2..0f94fab106ea1 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h
@@ -10,11 +10,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
#include "llvm/Support/Error.h"
namespace clang::ssaf {
@@ -26,4 +26,4 @@ llvm::Expected<std::unique_ptr<EntitySummary>> serializeDeserializeRoundTrip(
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h b/clang/include/clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h
similarity index 82%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h
index 5057f8ac4505f..aa8ce469397a0 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ASTENTITYMAPPING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ASTENTITYMAPPING_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ASTENTITYMAPPING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ASTENTITYMAPPING_H
#include "clang/AST/Decl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
#include "llvm/ADT/StringRef.h"
#include <optional>
@@ -44,4 +44,4 @@ std::optional<EntityName> getEntityNameForReturn(const FunctionDecl *FD);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ASTENTITYMAPPING_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ASTENTITYMAPPING_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h
similarity index 91%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h
index 12a42df213e2a..680ca6ab639dd 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h
@@ -11,10 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYLINKER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYLINKER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYLINKER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYLINKER_H
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
#include "llvm/Support/Error.h"
#include <map>
#include <memory>
@@ -89,4 +89,4 @@ class EntityLinker {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYLINKER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYLINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h
similarity index 79%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h
index 461fd74c8cafe..9442ecbbe24cc 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h
@@ -11,10 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
#include "llvm/Support/Error.h"
#include <map>
@@ -39,4 +39,4 @@ class EntitySummaryEncoding {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h
similarity index 67%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h
index a36002006430c..58568d365c0ae 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h
@@ -11,15 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARY_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
#include <map>
#include <memory>
@@ -52,4 +52,4 @@ class LUSummary {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h
similarity index 69%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h
index a4248a4d1e79d..85c5fc0f1f46a 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h
@@ -11,15 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
#include <map>
#include <memory>
@@ -56,4 +56,4 @@ class LUSummaryEncoding {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h
similarity index 70%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h
index 4fcf91d1c0423..18998e6a1f862 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h
@@ -11,15 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
#include <map>
#include <memory>
@@ -57,4 +57,4 @@ class TUSummaryEncoding {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h
similarity index 95%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h
index 16c6fd6fcb4ef..6da5a9e42c4da 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h
@@ -15,8 +15,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_BUILDNAMESPACE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_BUILDNAMESPACE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_BUILDNAMESPACE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_BUILDNAMESPACE_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -126,4 +126,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_BUILDNAMESPACE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_BUILDNAMESPACE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityId.h
similarity index 88%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityId.h
index 0da76e17c823e..e8e36119927c8 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityId.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYID_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYID_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYID_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYID_H
#include "llvm/Support/raw_ostream.h"
#include <cstddef>
@@ -51,4 +51,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityId &Id);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYID_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYID_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h
similarity index 79%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h
index d74b871df3e16..316a1f36369ec 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYIDTABLE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYIDTABLE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYIDTABLE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYIDTABLE_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
#include <functional>
#include <map>
@@ -50,4 +50,4 @@ class EntityIdTable {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYIDTABLE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYIDTABLE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h
similarity index 87%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h
index cdae99ad0b6b2..164fd458b1281 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYLINKAGE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYLINKAGE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYLINKAGE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYLINKAGE_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -49,4 +49,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYLINKAGE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYLINKAGE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityName.h
similarity index 87%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityName.h
index 853ac96209a86..ecc402e05d4b8 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityName.h
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYNAME_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYNAME_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYNAME_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYNAME_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -59,4 +59,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityName &EN);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYNAME_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def b/clang/include/clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def
similarity index 100%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def
rename to clang/include/clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/SummaryName.h
similarity index 84%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Model/SummaryName.h
index 99b5308e61a4e..d299efc6fc638 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/SummaryName.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_SUMMARYNAME_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_SUMMARYNAME_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_SUMMARYNAME_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_SUMMARYNAME_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -38,4 +38,4 @@ class SummaryName {
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SummaryName &SN);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_SUMMARYNAME_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_SUMMARYNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h
similarity index 95%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h
index b0126a1abac9f..6f9b480a7afa5 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h
@@ -10,11 +10,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/Support/JSON.h"
@@ -235,4 +235,4 @@ extern template class CLANG_TEMPLATE_ABI
Registry<clang::ssaf::JSONFormat::AnalysisResultRegistry::Codec>;
} // namespace llvm
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h
similarity index 89%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h
index fd261c6d9a723..85bdc0cbcab2a 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h
@@ -11,17 +11,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
@@ -82,7 +82,7 @@ class SerializationFormat {
#define FIELD(CLASS, FIELD_NAME) \
static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def"
+#include "clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def"
/// Per-format plugin registry for analysis result (de)serializers.
///
@@ -221,4 +221,4 @@ template <class SerializerFn, class DeserializerFn> struct FormatInfoEntry {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h
similarity index 87%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h
index 5855cd84336e3..600c993264926 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h
@@ -51,7 +51,7 @@
// );
//
// Finally, insert a use of the new anchor symbol into the force-linker header:
-// clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h:
+// clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h:
//
// This anchor is used to force the linker to link the MyFormat registration.
//
@@ -61,10 +61,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Registry.h"
@@ -94,4 +94,4 @@ extern template class CLANG_TEMPLATE_ABI
Registry<clang::ssaf::SerializationFormat>;
} // namespace llvm
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h
similarity index 88%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h
index b26e5fadc58c2..c0f0308533a46 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h
@@ -11,12 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Error.h"
#include <memory>
@@ -90,4 +90,4 @@ class LUSummaryConsumer final {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h
similarity index 76%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h
index 83386a684181e..8c7f98622cc25 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATA_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATA_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATA_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATA_H
namespace clang::ssaf {
@@ -25,4 +25,4 @@ class SummaryData {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATA_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATA_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h
similarity index 83%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h
index 343e98d46ce39..071741e23b56c 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h
@@ -12,14 +12,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
#include <memory>
namespace clang::ssaf {
@@ -94,4 +94,4 @@ class SummaryDataBuilder : public SummaryDataBuilderBase {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h
similarity index 85%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h
index 630e1c298f9e1..629281a477d6c 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h
@@ -19,10 +19,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h"
#include "llvm/Support/Registry.h"
#include <memory>
#include <string>
@@ -69,4 +69,4 @@ class SummaryDataBuilderRegistry {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h
similarity index 86%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h
index 3261085f8d5a2..b0e71a4f1031f 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h
@@ -11,13 +11,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
#include "llvm/Support/Error.h"
#include <map>
#include <memory>
@@ -112,4 +112,4 @@ class SummaryDataStore {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h
similarity index 80%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h
index c6bf6b6fcd4bb..d08dd68935bac 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h
@@ -10,10 +10,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
#include <type_traits>
namespace clang::ssaf {
@@ -38,4 +38,4 @@ inline constexpr bool HasSummaryName_v = HasSummaryName<T>::value;
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h b/clang/include/clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h
similarity index 96%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h
index 2cce23766b026..2ad4d8e06eb90 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_ERRORBUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_ERRORBUILDER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_ERRORBUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_ERRORBUILDER_H
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
@@ -207,4 +207,4 @@ class ErrorBuilder {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_ERRORBUILDER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_ERRORBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h b/clang/include/clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h
similarity index 78%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h
index 437152d43f425..e4a7b54033924 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h
@@ -11,15 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_FORMATPROVIDERS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_FORMATPROVIDERS_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_FORMATPROVIDERS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_FORMATPROVIDERS_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
#include "llvm/Support/FormatProviders.h"
#include "llvm/Support/raw_ostream.h"
@@ -90,4 +90,4 @@ template <> struct format_provider<clang::ssaf::AnalysisName> {
} // namespace llvm
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_FORMATPROVIDERS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_FORMATPROVIDERS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h
similarity index 69%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h
index e6c8a4716eaf2..305abc05f19f3 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_ENTITYSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_ENTITYSUMMARY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_ENTITYSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_ENTITYSUMMARY_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
#include <type_traits>
namespace clang::ssaf {
@@ -27,4 +27,4 @@ using DerivesFromEntitySummary =
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_ENTITYSUMMARY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_ENTITYSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h
similarity index 83%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h
index da57838c64b2f..6ef0c6612f64e 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h
@@ -15,7 +15,7 @@
// X("MyExtractor", "My awesome extractor");
//
// Finally, insert a use of the new anchor symbol into the force-linker header:
-// clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h:
+// clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h:
//
// extern volatile int SSAFMyExtractorAnchorSource;
// [[maybe_unused]] static int SSAFMyExtractorAnchorDestination =
@@ -23,10 +23,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Registry.h"
@@ -55,4 +55,4 @@ using TUSummaryExtractorRegistry =
LLVM_DECLARE_REGISTRY(clang::ssaf::TUSummaryExtractorRegistry)
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h
similarity index 59%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h
index 1609e68257d57..e9ec5b19e2e4d 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h
@@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARY_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
#include <map>
#include <memory>
@@ -43,4 +43,4 @@ class TUSummary {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h
similarity index 86%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h
index fd07abfab8c87..3208c7ebb15cc 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
#include <memory>
#include <utility>
@@ -73,4 +73,4 @@ TUSummaryBuilder::addSummary(EntityId Entity,
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h
similarity index 72%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h
index 629a8d0e35ae4..185c9ddd69055 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
#include "clang/AST/ASTConsumer.h"
@@ -25,4 +25,4 @@ class TUSummaryExtractor : public ASTConsumer {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h
similarity index 82%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h
index 1a9a5de76ffab..638791f9b1646 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h
@@ -12,10 +12,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
#include <vector>
namespace clang::ssaf {
@@ -57,4 +57,4 @@ class AnalysisBase {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h
similarity index 88%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h
index 156d8e806bd0f..148234f5c9649 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h
@@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Error.h"
#include <memory>
@@ -92,4 +92,4 @@ class AnalysisDriver final {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h
similarity index 85%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h
index 32f76e73b14e0..71a0a26b9853d 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -46,4 +46,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const AnalysisName &AN);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h
similarity index 85%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h
index 44eabce6c809c..f8f76b8acd4b4 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h
@@ -28,13 +28,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Registry.h"
#include <memory>
@@ -106,4 +106,4 @@ class AnalysisRegistry {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h
similarity index 75%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h
index 07d1f0549a9ee..fc10a6f2707fb 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
namespace clang::ssaf {
@@ -27,4 +27,4 @@ class AnalysisResult {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h
similarity index 75%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h
index 78df3b35648c2..f4daf01b2660f 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h
@@ -10,10 +10,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
#include <type_traits>
namespace clang::ssaf {
@@ -33,4 +33,4 @@ inline constexpr bool HasAnalysisName_v = HasAnalysisName<T>::value;
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h
similarity index 86%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h
index ff9470e0a2284..1fb33c83ed6b0 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h
@@ -12,14 +12,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
+
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h"
#include "llvm/Support/Error.h"
#include <map>
#include <memory>
@@ -130,4 +130,4 @@ class DerivedAnalysis : public DerivedAnalysisBase {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h
similarity index 83%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h
index 5b7c2c9b6b8c2..cf3bec9bb3b5e 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h
@@ -12,15 +12,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h"
#include "llvm/Support/Error.h"
#include <memory>
@@ -118,4 +118,4 @@ class SummaryAnalysis : public SummaryAnalysisBase {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h
similarity index 81%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h
rename to clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h
index 8e7693b78d485..cdc74ded19443 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h
@@ -11,14 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h"
#include "llvm/Support/Error.h"
#include <map>
#include <memory>
@@ -96,4 +96,4 @@ class WPASuite {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h b/clang/include/clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h
similarity index 78%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h
rename to clang/include/clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h
index fe5d75149914e..300aab9560be2 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
#include "clang/Frontend/FrontendAction.h"
#include <memory>
@@ -30,4 +30,4 @@ class TUSummaryExtractorFrontendAction final : public WrapperFrontendAction {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h b/clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h
similarity index 88%
rename from clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
rename to clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h
index 5616976e10f77..811fce1142bec 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
+++ b/clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h
@@ -13,12 +13,12 @@
///
/// Include this header (with IWYU pragma: keep) in any translation unit that
/// must guarantee these registrations are active — typically the entry point
-/// of a binary that uses clangScalableStaticAnalysisFrameworkCore.
+/// of a binary that uses clangScalableStaticAnalysisCore.
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFBUILTINFORCELINKER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFBUILTINFORCELINKER_H
// TODO: Move these to the `clang::ssaf` namespace.
@@ -55,4 +55,4 @@ extern volatile int CallGraphJSONFormatAnchorSource;
[[maybe_unused]] static int CallGraphJSONFormatAnchorDestination =
CallGraphJSONFormatAnchorSource;
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFBUILTINFORCELINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h b/clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h
similarity index 76%
rename from clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h
rename to clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h
index 204a504c36435..bf0b74e3955f3 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h
+++ b/clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h
@@ -13,13 +13,13 @@
///
/// Include this header (with IWYU pragma: keep) in any translation unit that
/// must guarantee these registrations are active — typically the entry point
-/// of a binary that uses clangScalableStaticAnalysisFrameworkCore.
+/// of a binary that uses clangScalableStaticAnalysisCore.
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFFORCELINKER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFFORCELINKER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFFORCELINKER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFFORCELINKER_H
#include "SSAFBuiltinForceLinker.h" // IWYU pragma: keep
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFFORCELINKER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFFORCELINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h b/clang/include/clang/ScalableStaticAnalysis/Tool/Utils.h
similarity index 92%
rename from clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
rename to clang/include/clang/ScalableStaticAnalysis/Tool/Utils.h
index f7ee5c28ffe89..f02bb8152cfd1 100644
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
+++ b/clang/include/clang/ScalableStaticAnalysis/Tool/Utils.h
@@ -13,10 +13,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_TOOL_UTILS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_TOOL_UTILS_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
@@ -92,4 +92,4 @@ struct FormatFile {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_TOOL_UTILS_H
diff --git a/clang/include/module.modulemap b/clang/include/module.modulemap
index 62a3ba104b0df..fece3e1c2202a 100644
--- a/clang/include/module.modulemap
+++ b/clang/include/module.modulemap
@@ -146,11 +146,11 @@ module Clang_Options { requires cplusplus umbrella "clang/Options" module * { ex
module Clang_Parse { requires cplusplus umbrella "clang/Parse" module * { export * } }
module Clang_Rewrite { requires cplusplus umbrella "clang/Rewrite/Core" module * { export * } }
module Clang_RewriteFrontend { requires cplusplus umbrella "clang/Rewrite/Frontend" module * { export * } }
-module Clang_ScalableStaticAnalysisFramework {
+module Clang_ScalableStaticAnalysis {
requires cplusplus
- umbrella "clang/ScalableStaticAnalysisFramework"
+ umbrella "clang/ScalableStaticAnalysis"
- textual header "clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def"
+ textual header "clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def"
module * { export * }
}
diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt
index d9d1e4630a416..dee31cb3f166e 100644
--- a/clang/lib/CMakeLists.txt
+++ b/clang/lib/CMakeLists.txt
@@ -23,7 +23,7 @@ add_subdirectory(DirectoryWatcher)
add_subdirectory(Index)
add_subdirectory(IndexSerialization)
add_subdirectory(InstallAPI)
-add_subdirectory(ScalableStaticAnalysisFramework)
+add_subdirectory(ScalableStaticAnalysis)
add_subdirectory(StaticAnalyzer)
add_subdirectory(Format)
if(CLANG_INCLUDE_TESTS)
diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index 5fe10052d267f..feaaaa3ab2e87 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -112,9 +112,9 @@ add_clang_library(clangDriver
clangBasic
clangDependencyScanning
clangFrontend
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkFrontend
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisFrontend
clangSerialization
clangLex
clangOptions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index c98ac919f7d2a..5bd3b95a65200 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -70,9 +70,9 @@
#include "clang/Driver/Types.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Options/Options.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt
index 24623303e6bdb..514c2728170de 100644
--- a/clang/lib/FrontendTool/CMakeLists.txt
+++ b/clang/lib/FrontendTool/CMakeLists.txt
@@ -4,9 +4,9 @@ set(LLVM_LINK_COMPONENTS
)
set(link_libs
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkFrontend
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisFrontend
clangBasic
clangCodeGen
clangDriver
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index e4622496758ac..1a4a3e0050bbb 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -23,8 +23,8 @@
#include "clang/FrontendTool/Utils.h"
#include "clang/Options/Options.h"
#include "clang/Rewrite/Frontend/FrontendActions.h"
-#include "clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h"
-#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
+#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
#include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
#include "llvm/Option/OptTable.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
similarity index 76%
rename from clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
rename to clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
index 88dcef0c5a2fa..fcbdaa8303091 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
@@ -2,7 +2,7 @@ set(LLVM_LINK_COMPONENTS
Support
)
-add_clang_library(clangScalableStaticAnalysisFrameworkAnalyses
+add_clang_library(clangScalableStaticAnalysisAnalyses
CallGraph/CallGraphExtractor.cpp
CallGraph/CallGraphJSONFormat.cpp
EntityPointerLevel/EntityPointerLevel.cpp
@@ -14,7 +14,7 @@ add_clang_library(clangScalableStaticAnalysisFrameworkAnalyses
clangAST
clangAnalysis
clangBasic
- clangScalableStaticAnalysisFrameworkCore
+ clangScalableStaticAnalysisCore
DEPENDS
)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractor.cpp
similarity index 91%
rename from clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
rename to clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractor.cpp
index 1dbed7e0b0d8a..a625cb13db842 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractor.cpp
@@ -13,10 +13,10 @@
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
#include "llvm/ADT/STLExtras.h"
#include <memory>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphJSONFormat.cpp
similarity index 95%
rename from clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
rename to clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphJSONFormat.cpp
index 860e26417eb55..6cc1ab013c178 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphJSONFormat.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/JSON.h"
#include <memory>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
similarity index 96%
rename from clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
rename to clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
index 52e6705ec43af..5c0230561eec5 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
@@ -6,14 +6,14 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
#include "SSAFAnalysesCommon.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
#include <optional>
using namespace clang;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp
similarity index 100%
rename from clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
rename to clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
similarity index 90%
rename from clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
rename to clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
index acc95f799ca9d..e73e3fe7e3f2a 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
@@ -9,8 +9,8 @@
// Common code in SSAF analyses implementations
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_SSAFANALYSESCOMMON_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_SSAFANALYSESCOMMON_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_SSAFANALYSESCOMMON_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_SSAFANALYSESCOMMON_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTTypeTraits.h"
@@ -57,4 +57,4 @@ void findMatchesIn(
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_SSAFANALYSESCOMMON_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_SSAFANALYSESCOMMON_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
similarity index 88%
rename from clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
rename to clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
index ea5d2297b9836..99a5d6b3a2942 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
#include "SSAFAnalysesCommon.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
#include <cstdint>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
similarity index 86%
rename from clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
rename to clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index 550416c353fb7..9dbf586554ad8 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -11,13 +11,13 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.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"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/CMakeLists.txt
similarity index 100%
rename from clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt
rename to clang/lib/ScalableStaticAnalysis/CMakeLists.txt
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.cpp b/clang/lib/ScalableStaticAnalysis/Core/ASTEntityMapping.cpp
similarity index 93%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/ASTEntityMapping.cpp
index cac27b2c3f278..1f4bf0da274ed 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/ASTEntityMapping.cpp
@@ -10,9 +10,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
#include "clang/AST/Decl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
#include "clang/UnifiedSymbolResolution/USRGeneration.h"
#include "llvm/ADT/SmallString.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Core/CMakeLists.txt
similarity index 94%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
rename to clang/lib/ScalableStaticAnalysis/Core/CMakeLists.txt
index 83772ceff58bf..6d87d7b8f96d3 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysis/Core/CMakeLists.txt
@@ -2,7 +2,7 @@ set(LLVM_LINK_COMPONENTS
Support
)
-add_clang_library(clangScalableStaticAnalysisFrameworkCore
+add_clang_library(clangScalableStaticAnalysisCore
ASTEntityMapping.cpp
EntityLinker/EntityLinker.cpp
Model/BuildNamespace.cpp
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.cpp b/clang/lib/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.cpp
similarity index 92%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.cpp
index 5aff18999e114..462978932a53d 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.cpp
@@ -6,13 +6,13 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
#include <cassert>
using namespace clang::ssaf;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/BuildNamespace.cpp
similarity index 96%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Model/BuildNamespace.cpp
index 09fff31e8f4a8..f68ed961f71b9 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/BuildNamespace.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
#include "../ModelStringConversions.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityId.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityId.cpp
similarity index 88%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityId.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Model/EntityId.cpp
index 9c4eec2d7e299..a731bd24da4a0 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityId.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityId.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
namespace clang::ssaf {
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityIdTable.cpp
similarity index 92%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Model/EntityIdTable.cpp
index cb514581ca9ec..651179c24a342 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityIdTable.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
#include <cassert>
namespace clang::ssaf {
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityLinkage.cpp
similarity index 93%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Model/EntityLinkage.cpp
index 179b906c0b999..0bae90cd66a22 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityLinkage.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
#include "../ModelStringConversions.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityName.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityName.cpp
similarity index 94%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityName.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Model/EntityName.cpp
index 9145506865f24..c9e09df84143b 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityName.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityName.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
namespace clang::ssaf {
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/SummaryName.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/SummaryName.cpp
similarity index 88%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Model/SummaryName.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Model/SummaryName.cpp
index 1609912aa7f90..66c7726a9da90 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/SummaryName.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/SummaryName.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
namespace clang::ssaf {
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h b/clang/lib/ScalableStaticAnalysis/Core/ModelStringConversions.h
similarity index 87%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h
rename to clang/lib/ScalableStaticAnalysis/Core/ModelStringConversions.h
index f168a475de807..baec4c574dd6c 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h
+++ b/clang/lib/ScalableStaticAnalysis/Core/ModelStringConversions.h
@@ -13,11 +13,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODELSTRINGCONVERSIONS_H
-#define LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODELSTRINGCONVERSIONS_H
+#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_MODELSTRINGCONVERSIONS_H
+#define LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_MODELSTRINGCONVERSIONS_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include <optional>
@@ -84,4 +84,4 @@ entityLinkageTypeFromString(llvm::StringRef Str) {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODELSTRINGCONVERSIONS_H
+#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_MODELSTRINGCONVERSIONS_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
similarity index 100%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
similarity index 76%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
rename to clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
index 9a1f5d49757f7..697a377d185fa 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
@@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
-#define LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
+#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
+#define LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
#include "llvm/Support/JSON.h"
#include <map>
@@ -49,4 +49,4 @@ class JSONEntitySummaryEncoding final : public EntitySummaryEncoding {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
+#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
similarity index 99%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
index 8db7480e683f5..b48122e3573c5 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
#include "llvm/Support/Registry.h"
// NOLINTNEXTLINE(misc-use-internal-linkage)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.h
similarity index 89%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h
rename to clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.h
index 31a605efe90a5..8e94f75283437 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.h
@@ -11,17 +11,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
-#define LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
+#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
+#define LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
#include "../../ModelStringConversions.h"
#include "JSONEntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
@@ -169,4 +169,4 @@ llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
+#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummary.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummary.cpp
similarity index 98%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummary.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummary.cpp
index 1137499ba28c9..d26d6bf69d53c 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummary.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummary.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
#include <set>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
similarity index 98%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
index e748b021d1666..41007038c93d4 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
#include <set>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummary.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummary.cpp
similarity index 98%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummary.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummary.cpp
index cc9460e956e7a..8e23ab0ba74c7 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummary.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummary.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
#include <set>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
similarity index 98%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
index b16d70b6b0416..d241a717c64a7 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
#include <set>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/WPASuite.cpp
similarity index 98%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/WPASuite.cpp
index a37f8e838348e..6f719caee43de 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/WPASuite.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
namespace clang::ssaf {
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.cpp
similarity index 92%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.cpp
index 0eb86f2fdee2f..e8841ea527078 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
#include <memory>
using namespace clang;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.cpp b/clang/lib/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.cpp
similarity index 90%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.cpp
index 3021751213d72..fb630e8117f59 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
using namespace clang;
using namespace ssaf;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.cpp b/clang/lib/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.cpp
similarity index 91%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.cpp
index f0f2db91e6ba6..4edf09c3fa659 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h"
using namespace clang;
using namespace ssaf;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.cpp b/clang/lib/ScalableStaticAnalysis/Core/Support/ErrorBuilder.cpp
similarity index 96%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/Support/ErrorBuilder.cpp
index 3abc42e171065..99610725a6d23 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/Support/ErrorBuilder.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include <cassert>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp b/clang/lib/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.cpp
similarity index 94%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.cpp
index 01acc64f6f26c..96b4c00ca8bff 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
#include <memory>
using namespace clang;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp b/clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.cpp
similarity index 74%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.cpp
index 180a78cae33a9..93db2e3f1f9c7 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
#include <memory>
#include <utility>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.cpp b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.cpp
similarity index 93%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.cpp
index 1425f7079295f..f60c916e10b67 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.cpp
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.cpp b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.cpp
similarity index 86%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.cpp
index 9719196ed4d6d..011b816ae03dc 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
using namespace clang::ssaf;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
similarity index 89%
rename from clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
rename to clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
index 8e1ea954d9afd..04d9467f016a1 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;
diff --git a/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
new file mode 100644
index 0000000000000..d3b30e78755a8
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_library(clangScalableStaticAnalysisFrontend
+ TUSummaryExtractorFrontendAction.cpp
+
+ LINK_LIBS
+ clangAST
+ clangBasic
+ clangFrontend
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangSema
+ )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp b/clang/lib/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.cpp
similarity index 92%
rename from clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp
rename to clang/lib/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.cpp
index 1c5170e354fb5..db923feab420a 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.cpp
@@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h"
+#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Frontend/MultiplexConsumer.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/IOSandbox.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Plugins/CMakeLists.txt
similarity index 98%
rename from clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt
rename to clang/lib/ScalableStaticAnalysis/Plugins/CMakeLists.txt
index b77ffc49c0f9f..a6af1e64e0ac3 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/CMakeLists.txt
@@ -1,6 +1,6 @@
if(CLANG_PLUGIN_SUPPORT AND LLVM_ENABLE_PLUGINS AND NOT WIN32)
# Plugins must never bring LLVM or Clang libraries in statically.
- # clang-ssaf-analyzer already loads clangScalableStaticAnalysisFrameworkCore
+ # clang-ssaf-analyzer already loads clangScalableStaticAnalysisCore
# and LLVM into the process; a second static copy would produce duplicate
# llvm::Registry instances with separate global state, breaking registration.
#
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/AnalysisResults.h b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/AnalysisResults.h
similarity index 81%
rename from clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/AnalysisResults.h
rename to clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/AnalysisResults.h
index c8ae6a542b8f0..f5072dce74e23 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/AnalysisResults.h
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/AnalysisResults.h
@@ -9,9 +9,9 @@
#ifndef EXAMPLE_PLUGIN_ANALYSIS_RESULTS_H
#define EXAMPLE_PLUGIN_ANALYSIS_RESULTS_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
#include <string>
#include <utility>
#include <vector>
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/CMakeLists.txt
similarity index 87%
rename from clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt
rename to clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/CMakeLists.txt
index 06c8e2abc1bd4..b4eea284636bf 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/CMakeLists.txt
@@ -14,5 +14,5 @@ add_llvm_library(SSAFExamplePlugin MODULE BUILDTREE_ONLY
# Pull in SSAF and LLVM include paths without any static link dependency.
target_include_directories(SSAFExamplePlugin PRIVATE
- $<TARGET_PROPERTY:clangScalableStaticAnalysisFrameworkCore,INTERFACE_INCLUDE_DIRECTORIES>
+ $<TARGET_PROPERTY:clangScalableStaticAnalysisCore,INTERFACE_INCLUDE_DIRECTORIES>
)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/PairsAnalysis.cpp b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/PairsAnalysis.cpp
similarity index 94%
rename from clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/PairsAnalysis.cpp
rename to clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/PairsAnalysis.cpp
index 34923f4a15e6e..94f08d7e9fb73 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/PairsAnalysis.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/PairsAnalysis.cpp
@@ -7,11 +7,11 @@
//===----------------------------------------------------------------------===//
#include "AnalysisResults.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Registry.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsAnalysis.cpp b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsAnalysis.cpp
similarity index 92%
rename from clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsAnalysis.cpp
rename to clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsAnalysis.cpp
index 630a14544d7b0..9d74b7b30d9bf 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsAnalysis.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsAnalysis.cpp
@@ -7,11 +7,11 @@
//===----------------------------------------------------------------------===//
#include "AnalysisResults.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Registry.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
similarity index 94%
rename from clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
rename to clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
index 14750de321824..5ceb0eb971673 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
@@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
#include "AnalysisResults.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Registry.h"
diff --git a/clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt
new file mode 100644
index 0000000000000..134f8bb003f19
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_library(clangScalableStaticAnalysisTool
+ Utils.cpp
+
+ LINK_LIBS
+ clangBasic
+ clangScalableStaticAnalysisCore
+ )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp b/clang/lib/ScalableStaticAnalysis/Tool/Utils.cpp
similarity index 99%
rename from clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
rename to clang/lib/ScalableStaticAnalysis/Tool/Utils.cpp
index e8dde39a846e9..5b0963bfa4344 100644
--- a/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
+++ b/clang/lib/ScalableStaticAnalysis/Tool/Utils.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
+#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
deleted file mode 100644
index 3da1558810572..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Support
- )
-
-add_clang_library(clangScalableStaticAnalysisFrameworkFrontend
- TUSummaryExtractorFrontendAction.cpp
-
- LINK_LIBS
- clangAST
- clangBasic
- clangFrontend
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangSema
- )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
deleted file mode 100644
index 53b900ec8c042..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Support
- )
-
-add_clang_library(clangScalableStaticAnalysisFrameworkTool
- Utils.cpp
-
- LINK_LIBS
- clangBasic
- clangScalableStaticAnalysisFrameworkCore
- )
diff --git a/clang/test/Analysis/Scalable/command-line-interface.cpp b/clang/test/Analysis/Scalable/command-line-interface.cpp
index a632f487f2bb7..ace510e3ca227 100644
--- a/clang/test/Analysis/Scalable/command-line-interface.cpp
+++ b/clang/test/Analysis/Scalable/command-line-interface.cpp
@@ -15,8 +15,8 @@
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]
-// UNKNOWN-FILE-FORMAT: error: unknown output summary file format 'unknownfmt' specified by '--ssaf-tu-summary-file={{.+}}.ssaf.unknownfmt' [-Wscalable-static-analysis-framework]
-// NO-EXTRACTORS-ENABLED: error: must enable some summary extractors using the '--ssaf-extract-summaries=' option [-Wscalable-static-analysis-framework]
-// NO-EXTRACTOR-WITH-NAME: error: no summary extractor was registered with name: extractor1 [-Wscalable-static-analysis-framework]
-// NO-EXTRACTORS-WITH-NAME: error: no summary extractors were registered with name: extractor1, extractor2 [-Wscalable-static-analysis-framework]
+// 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]
+// UNKNOWN-FILE-FORMAT: error: unknown output summary file format 'unknownfmt' specified by '--ssaf-tu-summary-file={{.+}}.ssaf.unknownfmt' [-Wscalable-static-analysis]
+// NO-EXTRACTORS-ENABLED: error: must enable some summary extractors using the '--ssaf-extract-summaries=' option [-Wscalable-static-analysis]
+// NO-EXTRACTOR-WITH-NAME: error: no summary extractor was registered with name: extractor1 [-Wscalable-static-analysis]
+// NO-EXTRACTORS-WITH-NAME: error: no summary extractors were registered with name: extractor1, extractor2 [-Wscalable-static-analysis]
diff --git a/clang/test/Analysis/Scalable/downgradable-errors.cpp b/clang/test/Analysis/Scalable/downgradable-errors.cpp
index 494e3e71092ac..eeec552bbe40f 100644
--- a/clang/test/Analysis/Scalable/downgradable-errors.cpp
+++ b/clang/test/Analysis/Scalable/downgradable-errors.cpp
@@ -1,15 +1,15 @@
// DEFINE: %{filecheck} = FileCheck %s --match-full-lines --check-prefix
// RUN: not %clang -fsyntax-only %s --ssaf-tu-summary-file=foobar 2>&1 | %{filecheck}=DEFAULT-ERROR
-// RUN: %clang -fsyntax-only %s --ssaf-tu-summary-file=foobar -Wno-error=scalable-static-analysis-framework 2>&1 | %{filecheck}=DEMOTED-TO-WARNING
-// RUN: %clang -fsyntax-only %s --ssaf-tu-summary-file=foobar -Wno-scalable-static-analysis-framework 2>&1 | count 0
+// RUN: %clang -fsyntax-only %s --ssaf-tu-summary-file=foobar -Wno-error=scalable-static-analysis 2>&1 | %{filecheck}=DEMOTED-TO-WARNING
+// RUN: %clang -fsyntax-only %s --ssaf-tu-summary-file=foobar -Wno-scalable-static-analysis 2>&1 | count 0
-// This test demonstrates that the "scalable-static-analysis-framework" diagnostics can be downgraded or completely silenced with the right flags.
+// This test demonstrates that the "scalable-static-analysis" diagnostics can be downgraded or completely silenced with the right flags.
void empty() {}
-// DEFAULT-ERROR: error: failed to parse the value of '--ssaf-tu-summary-file=foobar' the value must follow the '<path>.<format>' pattern [-Wscalable-static-analysis-framework]
+// DEFAULT-ERROR: error: failed to parse the value of '--ssaf-tu-summary-file=foobar' the value must follow the '<path>.<format>' pattern [-Wscalable-static-analysis]
// DEFAULT-ERROR: 1 error generated.
-// DEMOTED-TO-WARNING: warning: failed to parse the value of '--ssaf-tu-summary-file=foobar' the value must follow the '<path>.<format>' pattern [-Wscalable-static-analysis-framework]
+// DEMOTED-TO-WARNING: warning: failed to parse the value of '--ssaf-tu-summary-file=foobar' the value must follow the '<path>.<format>' pattern [-Wscalable-static-analysis]
// DEMOTED-TO-WARNING: 1 warning generated.
diff --git a/clang/tools/clang-ssaf-format/CMakeLists.txt b/clang/tools/clang-ssaf-format/CMakeLists.txt
index 33ce432be3f4a..ab3869e441ad9 100644
--- a/clang/tools/clang-ssaf-format/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-format/CMakeLists.txt
@@ -15,9 +15,9 @@ add_clang_tool(clang-ssaf-format
clang_target_link_libraries(clang-ssaf-format
PRIVATE
clangBasic
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkTool
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisTool
)
if(CLANG_PLUGIN_SUPPORT)
diff --git a/clang/tools/clang-ssaf-format/SSAFFormat.cpp b/clang/tools/clang-ssaf-format/SSAFFormat.cpp
index c076c94e748a6..a314a73517f9d 100644
--- a/clang/tools/clang-ssaf-format/SSAFFormat.cpp
+++ b/clang/tools/clang-ssaf-format/SSAFFormat.cpp
@@ -11,12 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
-#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
diff --git a/clang/tools/clang-ssaf-linker/CMakeLists.txt b/clang/tools/clang-ssaf-linker/CMakeLists.txt
index af65aaa3b1aeb..7e6e59aaf9491 100644
--- a/clang/tools/clang-ssaf-linker/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-linker/CMakeLists.txt
@@ -10,7 +10,7 @@ add_clang_tool(clang-ssaf-linker
clang_target_link_libraries(clang-ssaf-linker
PRIVATE
clangBasic
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkTool
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisTool
)
diff --git a/clang/tools/clang-ssaf-linker/SSAFLinker.cpp b/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
index 7ee335b2a3990..84335ff55403d 100644
--- a/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
+++ b/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
@@ -11,12 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
-#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt
index 2ae0906dd1571..75e226e363812 100644
--- a/clang/unittests/CMakeLists.txt
+++ b/clang/unittests/CMakeLists.txt
@@ -91,7 +91,7 @@ add_subdirectory(Tooling)
add_subdirectory(Format)
add_subdirectory(Frontend)
add_subdirectory(Rewrite)
-add_subdirectory(ScalableStaticAnalysisFramework)
+add_subdirectory(ScalableStaticAnalysis)
add_subdirectory(Sema)
add_subdirectory(CodeGen)
if(HAVE_CLANG_REPL_SUPPORT)
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.cpp b/clang/unittests/ScalableStaticAnalysis/ASTEntityMappingTest.cpp
similarity index 99%
rename from clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/ASTEntityMappingTest.cpp
index da921b7b7ab35..a64eda451c61f 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/ASTEntityMappingTest.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractorTest.cpp
similarity index 97%
rename from clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractorTest.cpp
index 39b3cf604857d..56d0742b49283 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractorTest.cpp
@@ -11,11 +11,11 @@
#include "clang/AST/Decl.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
similarity index 95%
rename from clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
index 4a631a28897d0..cb0ec95bcfb21 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
@@ -6,21 +6,21 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
#include "TestFixture.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/Frontend/ASTUnit.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h"
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/BuildNamespaceTest.cpp b/clang/unittests/ScalableStaticAnalysis/BuildNamespaceTest.cpp
similarity index 96%
rename from clang/unittests/ScalableStaticAnalysisFramework/BuildNamespaceTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/BuildNamespaceTest.cpp
index 0fe8bb6f18122..e98efd45ea6b0 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/BuildNamespaceTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/BuildNamespaceTest.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt b/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
similarity index 89%
rename from clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt
rename to clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
index 5ae0a5de35e21..6ecc22236fe58 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt
+++ b/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
@@ -31,9 +31,9 @@ add_distinct_clang_unittest(ClangScalableAnalysisTests
clangASTMatchers
clangBasic
clangFrontend
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkFrontend
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisFrontend
clangSerialization
clangTooling
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTableTest.cpp b/clang/unittests/ScalableStaticAnalysis/EntityIdTableTest.cpp
similarity index 91%
rename from clang/unittests/ScalableStaticAnalysisFramework/EntityIdTableTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/EntityIdTableTest.cpp
index 7afa4943bcb79..ead7e35f8421f 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTableTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/EntityIdTableTest.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
#include "gtest/gtest.h"
namespace clang {
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTest.cpp b/clang/unittests/ScalableStaticAnalysis/EntityIdTest.cpp
similarity index 89%
rename from clang/unittests/ScalableStaticAnalysisFramework/EntityIdTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/EntityIdTest.cpp
index 9a07aed13a432..e01ceda75324a 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/EntityIdTest.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkageTest.cpp b/clang/unittests/ScalableStaticAnalysis/EntityLinkageTest.cpp
similarity index 95%
rename from clang/unittests/ScalableStaticAnalysisFramework/EntityLinkageTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/EntityLinkageTest.cpp
index a435f2f2c8974..ccf38ec8d93fb 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkageTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/EntityLinkageTest.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkerTest.cpp b/clang/unittests/ScalableStaticAnalysis/EntityLinkerTest.cpp
similarity index 96%
rename from clang/unittests/ScalableStaticAnalysisFramework/EntityLinkerTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/EntityLinkerTest.cpp
index 69312fd2f2b8d..3f18597649199 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkerTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/EntityLinkerTest.cpp
@@ -6,17 +6,17 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h"
#include "TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/EntityNameTest.cpp b/clang/unittests/ScalableStaticAnalysis/EntityNameTest.cpp
similarity index 92%
rename from clang/unittests/ScalableStaticAnalysisFramework/EntityNameTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/EntityNameTest.cpp
index 651b43744ed35..698b17efb6384 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/EntityNameTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/EntityNameTest.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/ErrorBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysis/ErrorBuilderTest.cpp
similarity index 98%
rename from clang/unittests/ScalableStaticAnalysisFramework/ErrorBuilderTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/ErrorBuilderTest.cpp
index 65db17416b965..5a5b74f82ae0f 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/ErrorBuilderTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/ErrorBuilderTest.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
#include "gtest/gtest.h"
#include <system_error>
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp b/clang/unittests/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendActionTest.cpp
similarity index 96%
rename from clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendActionTest.cpp
index 5d2392c9236a9..87aaf1e3337f9 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendActionTest.cpp
@@ -6,17 +6,17 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h"
+#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Lex/PreprocessorOptions.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/ModelStringConversionsTest.cpp b/clang/unittests/ScalableStaticAnalysis/ModelStringConversionsTest.cpp
similarity index 97%
rename from clang/unittests/ScalableStaticAnalysisFramework/ModelStringConversionsTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/ModelStringConversionsTest.cpp
index aff5140f26c2f..ff24a8358612d 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/ModelStringConversionsTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/ModelStringConversionsTest.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "../../lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h"
+#include "../../lib/ScalableStaticAnalysis/Core/ModelStringConversions.h"
#include "gtest/gtest.h"
using namespace clang::ssaf;
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/FancyAnalysisData.cpp
similarity index 96%
rename from clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
rename to clang/unittests/ScalableStaticAnalysis/Registries/FancyAnalysisData.cpp
index 313c53518dfe8..9c84af5ecef8d 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/FancyAnalysisData.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include "Registries/MockSerializationFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Registry.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.cpp
similarity index 91%
rename from clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
rename to clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.cpp
index 684249620e869..17142eab62908 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.cpp
@@ -7,15 +7,15 @@
//===----------------------------------------------------------------------===//
#include "Registries/MockSerializationFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h b/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.h
similarity index 84%
rename from clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h
rename to clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.h
index 8e5d5e92063af..7f5b48564039e 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.h
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/Support/Registry.h"
@@ -74,4 +74,4 @@ extern template class CLANG_TEMPLATE_ABI
Registry<clang::ssaf::MockSerializationFormat::FormatInfo>;
} // namespace llvm
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor1.cpp
similarity index 89%
rename from clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
rename to clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor1.cpp
index 1bce78c8b1030..fd68ba8e07ae7 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor1.cpp
@@ -8,8 +8,8 @@
#include "MockTUSummaryBuilder.h"
#include "clang/AST/ASTContext.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
using namespace clang;
using namespace ssaf;
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor2.cpp
similarity index 89%
rename from clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
rename to clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor2.cpp
index 242f427f5e346..58d15d407a0ae 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor2.cpp
@@ -8,8 +8,8 @@
#include "MockTUSummaryBuilder.h"
#include "clang/AST/ASTContext.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
using namespace clang;
using namespace ssaf;
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockTUSummaryBuilder.h b/clang/unittests/ScalableStaticAnalysis/Registries/MockTUSummaryBuilder.h
similarity index 69%
rename from clang/unittests/ScalableStaticAnalysisFramework/Registries/MockTUSummaryBuilder.h
rename to clang/unittests/ScalableStaticAnalysis/Registries/MockTUSummaryBuilder.h
index 389faed325050..87689634dc061 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockTUSummaryBuilder.h
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/MockTUSummaryBuilder.h
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKTUSUMMARYBUILDER_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKTUSUMMARYBUILDER_H
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKTUSUMMARYBUILDER_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKTUSUMMARYBUILDER_H
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
@@ -28,4 +28,4 @@ class MockTUSummaryBuilder : public TUSummaryBuilder {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKTUSUMMARYBUILDER_H
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKTUSUMMARYBUILDER_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/SerializationFormatRegistryTest.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/SerializationFormatRegistryTest.cpp
similarity index 95%
rename from clang/unittests/ScalableStaticAnalysisFramework/Registries/SerializationFormatRegistryTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/Registries/SerializationFormatRegistryTest.cpp
index b55754a622e31..bb61b95e0ccf6 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/SerializationFormatRegistryTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/SerializationFormatRegistryTest.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/SummaryExtractorRegistryTest.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/SummaryExtractorRegistryTest.cpp
similarity index 96%
rename from clang/unittests/ScalableStaticAnalysisFramework/Registries/SummaryExtractorRegistryTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/Registries/SummaryExtractorRegistryTest.cpp
index 10f352c234429..03b1cf0f72a40 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/SummaryExtractorRegistryTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/SummaryExtractorRegistryTest.cpp
@@ -8,8 +8,8 @@
#include "MockTUSummaryBuilder.h"
#include "clang/Frontend/MultiplexConsumer.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/StringRef.h"
#include "gmock/gmock.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h b/clang/unittests/ScalableStaticAnalysis/SSAFBuiltinTestForceLinker.h
similarity index 88%
rename from clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h
rename to clang/unittests/ScalableStaticAnalysis/SSAFBuiltinTestForceLinker.h
index 05d96af80cb27..bbc75e018bfef 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h
+++ b/clang/unittests/ScalableStaticAnalysis/SSAFBuiltinTestForceLinker.h
@@ -15,8 +15,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINTESTFORCELINKER_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINTESTFORCELINKER_H
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFBUILTINTESTFORCELINKER_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFBUILTINTESTFORCELINKER_H
// Force the linker to link NoOpExtractor registration.
extern volatile int SSAFNoOpExtractorAnchorSource;
@@ -48,4 +48,4 @@ extern volatile int SSAFFancyAnalysisDataAnchorSource;
[[maybe_unused]] static int SSAFFancyAnalysisDataAnchorDestination =
SSAFFancyAnalysisDataAnchorSource;
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINTESTFORCELINKER_H
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFBUILTINTESTFORCELINKER_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h b/clang/unittests/ScalableStaticAnalysis/SSAFTestForceLinker.h
similarity index 75%
rename from clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h
rename to clang/unittests/ScalableStaticAnalysis/SSAFTestForceLinker.h
index dd2077569a4eb..f1f1e49daa371 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h
+++ b/clang/unittests/ScalableStaticAnalysis/SSAFTestForceLinker.h
@@ -15,9 +15,9 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFTESTFORCELINKER_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFTESTFORCELINKER_H
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFTESTFORCELINKER_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFTESTFORCELINKER_H
#include "SSAFBuiltinTestForceLinker.h" // IWYU pragma: keep
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFTESTFORCELINKER_H
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFTESTFORCELINKER_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.cpp b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.cpp
similarity index 99%
rename from clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.cpp
index 2416f5e47b622..624cea28d0e5c 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.cpp
@@ -12,7 +12,7 @@
#include "JSONFormatTest.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Registry.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.h b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.h
similarity index 95%
rename from clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.h
rename to clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.h
index 515735e788d0d..b411ed3f91573 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.h
+++ b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.h
@@ -10,8 +10,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
#include "TestFixture.h"
#include "llvm/ADT/SmallString.h"
@@ -169,4 +169,4 @@ struct MismatchedEntitySummaryForJSONFormatTest final : EntitySummary {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/LUSummaryTest.cpp
similarity index 99%
rename from clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/LUSummaryTest.cpp
index 3b733634ccb03..2651d9352ce40 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/LUSummaryTest.cpp
@@ -13,9 +13,9 @@
#include "JSONFormatTest.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/TUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/TUSummaryTest.cpp
similarity index 99%
rename from clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/TUSummaryTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/TUSummaryTest.cpp
index 005fbc9340f5a..899320591fc47 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/TUSummaryTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/TUSummaryTest.cpp
@@ -13,9 +13,9 @@
#include "JSONFormatTest.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/SummaryData/SummaryDataTest.cpp b/clang/unittests/ScalableStaticAnalysis/SummaryData/SummaryDataTest.cpp
similarity index 94%
rename from clang/unittests/ScalableStaticAnalysisFramework/SummaryData/SummaryDataTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/SummaryData/SummaryDataTest.cpp
index caab7661593f3..2bf980cc116f0 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/SummaryData/SummaryDataTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/SummaryData/SummaryDataTest.cpp
@@ -7,16 +7,16 @@
//===----------------------------------------------------------------------===//
#include "../TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/SummaryNameTest.cpp b/clang/unittests/ScalableStaticAnalysis/SummaryNameTest.cpp
similarity index 93%
rename from clang/unittests/ScalableStaticAnalysisFramework/SummaryNameTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/SummaryNameTest.cpp
index e1d35f6628232..c88071491a953 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/SummaryNameTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/SummaryNameTest.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysis/TUSummaryBuilderTest.cpp
similarity index 94%
rename from clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/TUSummaryBuilderTest.cpp
index ece39e2164df7..58c08277fb288 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/TUSummaryBuilderTest.cpp
@@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
#include "TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp b/clang/unittests/ScalableStaticAnalysis/TestFixture.cpp
similarity index 76%
rename from clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
rename to clang/unittests/ScalableStaticAnalysis/TestFixture.cpp
index 772eaf069a350..440ad6055aa1c 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/TestFixture.cpp
@@ -8,11 +8,11 @@
#include "TestFixture.h"
#include "SSAFBuiltinTestForceLinker.h" // IWYU pragma: keep
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
#include <ostream>
#include <string>
diff --git a/clang/unittests/ScalableStaticAnalysis/TestFixture.h b/clang/unittests/ScalableStaticAnalysis/TestFixture.h
new file mode 100644
index 0000000000000..22fbff754fb37
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/TestFixture.h
@@ -0,0 +1,47 @@
+//===- TestFixture.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_TESTFIXTURE_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_TESTFIXTURE_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "gtest/gtest.h"
+#include <iosfwd>
+
+namespace clang::ssaf {
+
+class TestFixture : public ::testing::Test {
+protected:
+ static WPASuite makeWPASuite() { return WPASuite(); }
+
+#define FIELD(CLASS, FIELD_NAME) \
+ static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
+ static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
+#include "clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def"
+};
+
+void PrintTo(const BuildNamespace &BN, std::ostream *OS);
+void PrintTo(const EntityId &E, std::ostream *OS);
+void PrintTo(const EntityLinkage &EL, std::ostream *OS);
+void PrintTo(const EntityName &EN, std::ostream *OS);
+void PrintTo(const NestedBuildNamespace &NBN, std::ostream *OS);
+void PrintTo(const SummaryName &N, std::ostream *OS);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_TESTFIXTURE_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp b/clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/AnalysisDriverTest.cpp
similarity index 94%
rename from clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/AnalysisDriverTest.cpp
index e8290a7c3cd1f..7190b049df642 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/AnalysisDriverTest.cpp
@@ -6,20 +6,20 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
#include "../TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h b/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h
deleted file mode 100644
index 2116c2b4a664c..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- TestFixture.h --------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_TESTFIXTURE_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_TESTFIXTURE_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-#include "gtest/gtest.h"
-#include <iosfwd>
-
-namespace clang::ssaf {
-
-class TestFixture : public ::testing::Test {
-protected:
- static WPASuite makeWPASuite() { return WPASuite(); }
-
-#define FIELD(CLASS, FIELD_NAME) \
- static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
- static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def"
-};
-
-void PrintTo(const BuildNamespace &BN, std::ostream *OS);
-void PrintTo(const EntityId &E, std::ostream *OS);
-void PrintTo(const EntityLinkage &EL, std::ostream *OS);
-void PrintTo(const EntityName &EN, std::ostream *OS);
-void PrintTo(const NestedBuildNamespace &NBN, std::ostream *OS);
-void PrintTo(const SummaryName &N, std::ostream *OS);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_TESTFIXTURE_H
diff --git a/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
index 5691002325e3d..f13b1dcd8e355 100644
--- a/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
@@ -17,9 +17,9 @@ static_library("Driver") {
"//clang/lib/DependencyScanning",
"//clang/lib/Frontend",
"//clang/lib/Options",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/Frontend",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/Frontend",
"//llvm/include/llvm/Config:llvm-config",
"//llvm/lib/BinaryFormat",
"//llvm/lib/Option",
diff --git a/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn
index 4d515b7a25ce0..e2c27498f1b32 100644
--- a/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn
@@ -12,9 +12,9 @@ static_library("FrontendTool") {
"//clang/lib/Frontend",
"//clang/lib/Frontend/Rewrite",
"//clang/lib/Options",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/Frontend",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/Frontend",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Analyses/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Analyses/BUILD.gn
similarity index 80%
rename from llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Analyses/BUILD.gn
rename to llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Analyses/BUILD.gn
index 09b9bc4db3e1d..55075cd58deda 100644
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Analyses/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Analyses/BUILD.gn
@@ -1,11 +1,11 @@
static_library("Analyses") {
- output_name = "clangScalableStaticAnalysisFrameworkAnalyses"
+ output_name = "clangScalableStaticAnalysisAnalyses"
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/AST",
"//clang/lib/Analysis",
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
+ "//clang/lib/ScalableStaticAnalysis/Core",
"//llvm/lib/Support",
]
include_dirs = [ "." ]
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Core/BUILD.gn
similarity index 95%
rename from llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
rename to llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Core/BUILD.gn
index 70879d66e4700..3ce1a1a931f6b 100644
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Core/BUILD.gn
@@ -1,5 +1,5 @@
static_library("Core") {
- output_name = "clangScalableStaticAnalysisFrameworkCore"
+ output_name = "clangScalableStaticAnalysisCore"
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/AST",
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Frontend/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Frontend/BUILD.gn
similarity index 70%
rename from llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Frontend/BUILD.gn
rename to llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Frontend/BUILD.gn
index 96da539ae24da..56ca9e66e04e0 100644
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Frontend/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Frontend/BUILD.gn
@@ -1,11 +1,11 @@
static_library("Frontend") {
- output_name = "clangScalableStaticAnalysisFrameworkFrontend"
+ output_name = "clangScalableStaticAnalysisFrontend"
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/AST",
"//clang/lib/Basic",
"//clang/lib/Frontend",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
+ "//clang/lib/ScalableStaticAnalysis/Core",
"//clang/lib/Sema",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Tool/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Tool/BUILD.gn
similarity index 60%
rename from llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Tool/BUILD.gn
rename to llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Tool/BUILD.gn
index b45ecef4053c0..874d1d3da17af 100644
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Tool/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Tool/BUILD.gn
@@ -1,9 +1,9 @@
static_library("Tool") {
- output_name = "clangScalableStaticAnalysisFrameworkTool"
+ output_name = "clangScalableStaticAnalysisTool"
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
+ "//clang/lib/ScalableStaticAnalysis/Core",
"//llvm/lib/Support",
]
sources = [ "Utils.cpp" ]
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn
index 455082cd3b51a..61b970d3fd55c 100644
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn
@@ -2,9 +2,9 @@ executable("clang-ssaf-format") {
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/Tool",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/Tool",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn
index 9719218841909..36b99f70bdf1d 100644
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn
@@ -2,9 +2,9 @@ executable("clang-ssaf-linker") {
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/Tool",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/Tool",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/unittests/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/BUILD.gn
index 7d108c963c1cf..f29052a406e2d 100644
--- a/llvm/utils/gn/secondary/clang/unittests/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/unittests/BUILD.gn
@@ -29,7 +29,7 @@ group("unittests") {
deps += [
"Analysis:ClangAnalysisTests",
"Analysis/FlowSensitive:ClangAnalysisFlowSensitiveTests",
- "ScalableStaticAnalysisFramework:ClangScalableAnalysisTests",
+ "ScalableStaticAnalysis:ClangScalableAnalysisTests",
"StaticAnalyzer:StaticAnalysisTests",
]
}
diff --git a/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysisFramework/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysis/BUILD.gn
similarity index 89%
rename from llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysisFramework/BUILD.gn
rename to llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysis/BUILD.gn
index b6eebea5e843b..66914d2cab01f 100644
--- a/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysisFramework/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysis/BUILD.gn
@@ -7,9 +7,9 @@ unittest("ClangScalableAnalysisTests") {
"//clang/lib/ASTMatchers",
"//clang/lib/Basic",
"//clang/lib/Frontend",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/Frontend",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/Frontend",
"//clang/lib/Serialization",
"//clang/lib/Tooling",
"//llvm/lib/Frontend/OpenMP",
diff --git a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
index 819b6b9dcfbfd..b04e2326eeb35 100644
--- a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
@@ -2632,14 +2632,14 @@ cc_library(
cc_library(
name = "scalable_static_analysis_core",
srcs = glob([
- "lib/ScalableStaticAnalysisFramework/Core/**/*.cpp",
- "lib/ScalableStaticAnalysisFramework/Core/**/*.h",
+ "lib/ScalableStaticAnalysis/Core/**/*.cpp",
+ "lib/ScalableStaticAnalysis/Core/**/*.h",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Core/**/*.h"] + [
- "include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h",
- "include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h",
+ hdrs = glob(["include/clang/ScalableStaticAnalysis/Core/**/*.h"] + [
+ "include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h",
+ "include/clang/ScalableStaticAnalysis/SSAFForceLinker.h",
]),
- textual_hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Core/**/*.def"]),
+ textual_hdrs = glob(["include/clang/ScalableStaticAnalysis/Core/**/*.def"]),
deps = [
":ast",
":support",
@@ -2651,11 +2651,11 @@ cc_library(
cc_library(
name = "scalable_static_analysis_analyses",
srcs = glob([
- "lib/ScalableStaticAnalysisFramework/Analyses/**/*.cpp",
- "lib/ScalableStaticAnalysisFramework/Analyses/**/*.h",
+ "lib/ScalableStaticAnalysis/Analyses/**/*.cpp",
+ "lib/ScalableStaticAnalysis/Analyses/**/*.h",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Analyses/**/*.h"]),
- includes = ["lib/ScalableStaticAnalysisFramework/Analyses"],
+ hdrs = glob(["include/clang/ScalableStaticAnalysis/Analyses/**/*.h"]),
+ includes = ["lib/ScalableStaticAnalysis/Analyses"],
deps = [
":analysis",
":ast",
@@ -2668,9 +2668,9 @@ cc_library(
cc_library(
name = "scalable_static_analysis_tool",
srcs = glob([
- "lib/ScalableStaticAnalysisFramework/Tool/**/*.cpp",
+ "lib/ScalableStaticAnalysis/Tool/**/*.cpp",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Tool/**/*.h"]),
+ hdrs = glob(["include/clang/ScalableStaticAnalysis/Tool/**/*.h"]),
deps = [
":basic",
":scalable_static_analysis_core",
@@ -2681,9 +2681,9 @@ cc_library(
cc_library(
name = "scalable_static_analysis_frontend",
srcs = glob([
- "lib/ScalableStaticAnalysisFramework/Frontend/**/*.cpp",
+ "lib/ScalableStaticAnalysis/Frontend/**/*.cpp",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Frontend/**/*.h"]),
+ hdrs = glob(["include/clang/ScalableStaticAnalysis/Frontend/**/*.h"]),
deps = [
":ast",
":basic",
diff --git a/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
index 1fb1089165478..63b7d424350dc 100644
--- a/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
@@ -784,11 +784,11 @@ cc_test(
name = "scalable_static_analysis_tests",
size = "small",
srcs = glob([
- "ScalableStaticAnalysisFramework/**/*.cpp",
- "ScalableStaticAnalysisFramework/**/*.h",
+ "ScalableStaticAnalysis/**/*.cpp",
+ "ScalableStaticAnalysis/**/*.h",
]),
- features = ["-layering_check"], # #include "../../lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h"
- includes = ["ScalableStaticAnalysisFramework"],
+ features = ["-layering_check"], # #include "../../lib/ScalableStaticAnalysis/Core/ModelStringConversions.h"
+ includes = ["ScalableStaticAnalysis"],
deps = [
"//clang:ast",
"//clang:ast_matchers",
>From 535c42c32c58ddd5981c07a8fa8711699404e831 Mon Sep 17 00:00:00 2001
From: Aviral Goel <goel.aviral at gmail.com>
Date: Tue, 23 Jun 2026 16:21:52 -0700
Subject: [PATCH 2/6] Revert "[clang][ssaf] Shorten directory name to
ScalableStaticAnalysis"
This reverts commit 3bfefd3af0842dceb6e533fd17beeb755fccb7c0.
---
.github/new-prs-labeler.yml | 8 ++--
.../developer-docs/ForceLinkerHeaders.rst | 14 +++---
.../developer-docs/HowToExtend.rst | 16 +++----
.../SummaryExtractionInternals.rst | 0
.../developer-docs/index.rst | 0
.../index.rst | 0
.../user-docs/SummaryExtraction.rst | 8 ++--
clang/docs/index.rst | 2 +-
.../clang/Basic/DiagnosticFrontendKinds.td | 10 ++--
clang/include/clang/Basic/DiagnosticGroups.td | 2 +-
.../Analyses/CallGraph/CallGraphSummary.h | 12 ++---
.../EntityPointerLevel/EntityPointerLevel.h | 10 ++--
.../EntityPointerLevelFormat.h | 10 ++--
.../UnsafeBufferUsage/UnsafeBufferUsage.h | 12 ++---
.../UnsafeBufferUsage/UnsafeBufferUsageTest.h | 10 ++--
.../Core/ASTEntityMapping.h | 8 ++--
.../Core/EntityLinker/EntityLinker.h | 8 ++--
.../Core/EntityLinker/EntitySummaryEncoding.h | 8 ++--
.../Core/EntityLinker/LUSummary.h | 20 ++++----
.../Core/EntityLinker/LUSummaryEncoding.h | 20 ++++----
.../Core/EntityLinker/TUSummaryEncoding.h | 20 ++++----
.../Core/Model/BuildNamespace.h | 6 +--
.../Core/Model/EntityId.h | 6 +--
.../Core/Model/EntityIdTable.h | 10 ++--
.../Core/Model/EntityLinkage.h | 6 +--
.../Core/Model/EntityName.h | 8 ++--
.../Core/Model/PrivateFieldNames.def | 0
.../Core/Model/SummaryName.h | 6 +--
.../Core/Serialization/JSONFormat.h | 10 ++--
.../Core/Serialization/SerializationFormat.h | 26 +++++-----
.../SerializationFormatRegistry.h | 10 ++--
.../Core/SummaryData/LUSummaryConsumer.h | 12 ++---
.../Core/SummaryData/SummaryData.h | 6 +--
.../Core/SummaryData/SummaryDataBuilder.h | 18 +++----
.../SummaryData/SummaryDataBuilderRegistry.h | 8 ++--
.../Core/SummaryData/SummaryDataStore.h | 14 +++---
.../Core/SummaryData/SummaryDataTraits.h | 8 ++--
.../Core/Support/ErrorBuilder.h | 6 +--
.../Core/Support/FormatProviders.h | 18 +++----
.../Core/TUSummary/EntitySummary.h | 8 ++--
.../Core/TUSummary/ExtractorRegistry.h | 10 ++--
.../Core/TUSummary/TUSummary.h | 20 ++++----
.../Core/TUSummary/TUSummaryBuilder.h | 10 ++--
.../Core/TUSummary/TUSummaryExtractor.h | 6 +--
.../Core/WholeProgramAnalysis/AnalysisBase.h | 8 ++--
.../WholeProgramAnalysis/AnalysisDriver.h | 10 ++--
.../Core/WholeProgramAnalysis/AnalysisName.h | 6 +--
.../WholeProgramAnalysis/AnalysisRegistry.h | 14 +++---
.../WholeProgramAnalysis/AnalysisResult.h | 6 +--
.../WholeProgramAnalysis/AnalysisTraits.h | 8 ++--
.../WholeProgramAnalysis/DerivedAnalysis.h | 18 +++----
.../WholeProgramAnalysis/SummaryAnalysis.h | 20 ++++----
.../Core/WholeProgramAnalysis/WPASuite.h | 18 +++----
.../TUSummaryExtractorFrontendAction.h | 6 +--
.../SSAFBuiltinForceLinker.h | 8 ++--
.../SSAFForceLinker.h | 8 ++--
.../Tool/Utils.h | 8 ++--
clang/include/module.modulemap | 6 +--
clang/lib/CMakeLists.txt | 2 +-
clang/lib/Driver/CMakeLists.txt | 6 +--
clang/lib/Driver/Driver.cpp | 6 +--
clang/lib/FrontendTool/CMakeLists.txt | 6 +--
.../ExecuteCompilerInvocation.cpp | 4 +-
.../Frontend/CMakeLists.txt | 15 ------
.../Tool/CMakeLists.txt | 11 -----
.../Analyses/CMakeLists.txt | 4 +-
.../Analyses/CallGraph/CallGraphExtractor.cpp | 8 ++--
.../CallGraph/CallGraphJSONFormat.cpp | 8 ++--
.../EntityPointerLevel/EntityPointerLevel.cpp | 8 ++--
.../Analyses/SSAFAnalysesCommon.cpp | 0
.../Analyses/SSAFAnalysesCommon.h | 6 +--
.../UnsafeBufferUsage/UnsafeBufferUsage.cpp | 10 ++--
.../UnsafeBufferUsageExtractor.cpp | 14 +++---
.../CMakeLists.txt | 0
.../Core/ASTEntityMapping.cpp | 4 +-
.../Core/CMakeLists.txt | 2 +-
.../Core/EntityLinker/EntityLinker.cpp | 14 +++---
.../Core/Model/BuildNamespace.cpp | 2 +-
.../Core/Model/EntityId.cpp | 2 +-
.../Core/Model/EntityIdTable.cpp | 2 +-
.../Core/Model/EntityLinkage.cpp | 2 +-
.../Core/Model/EntityName.cpp | 2 +-
.../Core/Model/SummaryName.cpp | 2 +-
.../Core/ModelStringConversions.h | 10 ++--
.../JSONFormat/JSONEntitySummaryEncoding.cpp | 0
.../JSONFormat/JSONEntitySummaryEncoding.h | 10 ++--
.../JSONFormat/JSONFormatImpl.cpp | 2 +-
.../Serialization/JSONFormat/JSONFormatImpl.h | 18 +++----
.../Serialization/JSONFormat/LUSummary.cpp | 2 +-
.../JSONFormat/LUSummaryEncoding.cpp | 2 +-
.../Serialization/JSONFormat/TUSummary.cpp | 2 +-
.../JSONFormat/TUSummaryEncoding.cpp | 2 +-
.../Serialization/JSONFormat/WPASuite.cpp | 2 +-
.../SerializationFormatRegistry.cpp | 2 +-
.../Core/SummaryData/LUSummaryConsumer.cpp | 6 +--
.../SummaryDataBuilderRegistry.cpp | 2 +-
.../Core/Support/ErrorBuilder.cpp | 2 +-
.../Core/TUSummary/ExtractorRegistry.cpp | 2 +-
.../Core/TUSummary/TUSummaryBuilder.cpp | 8 ++--
.../WholeProgramAnalysis/AnalysisDriver.cpp | 10 ++--
.../WholeProgramAnalysis/AnalysisName.cpp | 2 +-
.../WholeProgramAnalysis/AnalysisRegistry.cpp | 4 +-
.../Frontend/CMakeLists.txt | 15 ++++++
.../TUSummaryExtractorFrontendAction.cpp | 12 ++---
.../Plugins/CMakeLists.txt | 2 +-
.../Plugins/ExamplePlugin/AnalysisResults.h | 6 +--
.../Plugins/ExamplePlugin/CMakeLists.txt | 2 +-
.../Plugins/ExamplePlugin/PairsAnalysis.cpp | 10 ++--
.../Plugins/ExamplePlugin/TagsAnalysis.cpp | 10 ++--
.../ExamplePlugin/TagsPairsAnalysis.cpp | 6 +--
.../Tool/CMakeLists.txt | 11 +++++
.../Tool/Utils.cpp | 2 +-
.../Scalable/command-line-interface.cpp | 10 ++--
.../Analysis/Scalable/downgradable-errors.cpp | 10 ++--
clang/tools/clang-ssaf-format/CMakeLists.txt | 6 +--
clang/tools/clang-ssaf-format/SSAFFormat.cpp | 12 ++---
clang/tools/clang-ssaf-linker/CMakeLists.txt | 6 +--
clang/tools/clang-ssaf-linker/SSAFLinker.cpp | 12 ++---
clang/unittests/CMakeLists.txt | 2 +-
.../ScalableStaticAnalysis/TestFixture.h | 47 -------------------
.../ASTEntityMappingTest.cpp | 2 +-
.../CallGraph/CallGraphExtractorTest.cpp | 10 ++--
.../UnsafeBufferUsageTest.cpp | 22 ++++-----
.../BuildNamespaceTest.cpp | 4 +-
.../CMakeLists.txt | 6 +--
.../EntityIdTableTest.cpp | 8 ++--
.../EntityIdTest.cpp | 8 ++--
.../EntityLinkageTest.cpp | 4 +-
.../EntityLinkerTest.cpp | 20 ++++----
.../EntityNameTest.cpp | 6 +--
.../ErrorBuilderTest.cpp | 2 +-
.../TUSummaryExtractorFrontendActionTest.cpp | 10 ++--
.../ModelStringConversionsTest.cpp | 2 +-
.../Registries/FancyAnalysisData.cpp | 2 +-
.../Registries/MockSerializationFormat.cpp | 18 +++----
.../Registries/MockSerializationFormat.h | 10 ++--
.../Registries/MockSummaryExtractor1.cpp | 4 +-
.../Registries/MockSummaryExtractor2.cpp | 4 +-
.../Registries/MockTUSummaryBuilder.h | 8 ++--
.../SerializationFormatRegistryTest.cpp | 4 +-
.../SummaryExtractorRegistryTest.cpp | 4 +-
.../SSAFBuiltinTestForceLinker.h | 6 +--
.../SSAFTestForceLinker.h | 6 +--
.../JSONFormatTest/JSONFormatTest.cpp | 2 +-
.../JSONFormatTest/JSONFormatTest.h | 6 +--
.../JSONFormatTest/LUSummaryTest.cpp | 6 +--
.../JSONFormatTest/TUSummaryTest.cpp | 6 +--
.../SummaryData/SummaryDataTest.cpp | 20 ++++----
.../SummaryNameTest.cpp | 4 +-
.../TUSummaryBuilderTest.cpp | 16 +++----
.../TestFixture.cpp | 10 ++--
.../TestFixture.h | 47 +++++++++++++++++++
.../AnalysisDriverTest.cpp | 26 +++++-----
.../gn/secondary/clang/lib/Driver/BUILD.gn | 6 +--
.../secondary/clang/lib/FrontendTool/BUILD.gn | 6 +--
.../Analyses/BUILD.gn | 4 +-
.../Core/BUILD.gn | 2 +-
.../Frontend/BUILD.gn | 4 +-
.../Tool/BUILD.gn | 4 +-
.../clang/tools/clang-ssaf-format/BUILD.gn | 6 +--
.../clang/tools/clang-ssaf-linker/BUILD.gn | 6 +--
.../gn/secondary/clang/unittests/BUILD.gn | 2 +-
.../BUILD.gn | 6 +--
.../llvm-project-overlay/clang/BUILD.bazel | 28 +++++------
.../clang/unittests/BUILD.bazel | 8 ++--
165 files changed, 689 insertions(+), 689 deletions(-)
rename clang/docs/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/developer-docs/ForceLinkerHeaders.rst (89%)
rename clang/docs/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/developer-docs/HowToExtend.rst (91%)
rename clang/docs/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/developer-docs/SummaryExtractionInternals.rst (100%)
rename clang/docs/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/developer-docs/index.rst (100%)
rename clang/docs/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/index.rst (100%)
rename clang/docs/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/user-docs/SummaryExtraction.rst (84%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/CallGraph/CallGraphSummary.h (74%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/EntityPointerLevel/EntityPointerLevel.h (91%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h (59%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h (74%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h (63%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/ASTEntityMapping.h (82%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/EntityLinker/EntityLinker.h (91%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/EntityLinker/EntitySummaryEncoding.h (79%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/EntityLinker/LUSummary.h (67%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/EntityLinker/LUSummaryEncoding.h (69%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/EntityLinker/TUSummaryEncoding.h (70%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/BuildNamespace.h (95%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/EntityId.h (88%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/EntityIdTable.h (79%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/EntityLinkage.h (87%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/EntityName.h (87%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/PrivateFieldNames.def (100%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/SummaryName.h (84%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/JSONFormat.h (95%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/SerializationFormat.h (89%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/SerializationFormatRegistry.h (87%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/SummaryData/LUSummaryConsumer.h (88%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/SummaryData/SummaryData.h (76%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/SummaryData/SummaryDataBuilder.h (83%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/SummaryData/SummaryDataBuilderRegistry.h (85%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/SummaryData/SummaryDataStore.h (86%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/SummaryData/SummaryDataTraits.h (80%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Support/ErrorBuilder.h (96%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Support/FormatProviders.h (78%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/TUSummary/EntitySummary.h (69%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/TUSummary/ExtractorRegistry.h (83%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/TUSummary/TUSummary.h (59%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/TUSummary/TUSummaryBuilder.h (86%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/TUSummary/TUSummaryExtractor.h (72%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/AnalysisBase.h (82%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/AnalysisDriver.h (88%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/AnalysisName.h (85%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/AnalysisRegistry.h (85%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/AnalysisResult.h (75%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/AnalysisTraits.h (75%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/DerivedAnalysis.h (86%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/SummaryAnalysis.h (83%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/WPASuite.h (81%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Frontend/TUSummaryExtractorFrontendAction.h (78%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/SSAFBuiltinForceLinker.h (88%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/SSAFForceLinker.h (76%)
rename clang/include/clang/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Tool/Utils.h (92%)
delete mode 100644 clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
delete mode 100644 clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/CMakeLists.txt (76%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/CallGraph/CallGraphExtractor.cpp (91%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/CallGraph/CallGraphJSONFormat.cpp (95%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/EntityPointerLevel/EntityPointerLevel.cpp (96%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/SSAFAnalysesCommon.cpp (100%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/SSAFAnalysesCommon.h (90%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp (88%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp (86%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/CMakeLists.txt (100%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/ASTEntityMapping.cpp (93%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/CMakeLists.txt (94%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/EntityLinker/EntityLinker.cpp (92%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/BuildNamespace.cpp (96%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/EntityId.cpp (88%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/EntityIdTable.cpp (92%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/EntityLinkage.cpp (93%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/EntityName.cpp (94%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Model/SummaryName.cpp (88%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/ModelStringConversions.h (87%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp (100%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h (76%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/JSONFormat/JSONFormatImpl.cpp (99%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/JSONFormat/JSONFormatImpl.h (89%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/JSONFormat/LUSummary.cpp (98%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp (98%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/JSONFormat/TUSummary.cpp (98%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp (98%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/JSONFormat/WPASuite.cpp (98%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Serialization/SerializationFormatRegistry.cpp (92%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/SummaryData/LUSummaryConsumer.cpp (90%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/SummaryData/SummaryDataBuilderRegistry.cpp (91%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/Support/ErrorBuilder.cpp (96%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/TUSummary/ExtractorRegistry.cpp (94%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/TUSummary/TUSummaryBuilder.cpp (74%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/AnalysisDriver.cpp (93%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/AnalysisName.cpp (86%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/WholeProgramAnalysis/AnalysisRegistry.cpp (89%)
create mode 100644 clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Frontend/TUSummaryExtractorFrontendAction.cpp (92%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Plugins/CMakeLists.txt (98%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Plugins/ExamplePlugin/AnalysisResults.h (81%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Plugins/ExamplePlugin/CMakeLists.txt (87%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Plugins/ExamplePlugin/PairsAnalysis.cpp (94%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Plugins/ExamplePlugin/TagsAnalysis.cpp (92%)
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp (94%)
create mode 100644 clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
rename clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Tool/Utils.cpp (99%)
delete mode 100644 clang/unittests/ScalableStaticAnalysis/TestFixture.h
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/ASTEntityMappingTest.cpp (99%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/CallGraph/CallGraphExtractorTest.cpp (97%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp (95%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/BuildNamespaceTest.cpp (96%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/CMakeLists.txt (89%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/EntityIdTableTest.cpp (91%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/EntityIdTest.cpp (89%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/EntityLinkageTest.cpp (95%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/EntityLinkerTest.cpp (96%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/EntityNameTest.cpp (92%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/ErrorBuilderTest.cpp (98%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Frontend/TUSummaryExtractorFrontendActionTest.cpp (96%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/ModelStringConversionsTest.cpp (97%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Registries/FancyAnalysisData.cpp (96%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Registries/MockSerializationFormat.cpp (91%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Registries/MockSerializationFormat.h (84%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Registries/MockSummaryExtractor1.cpp (89%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Registries/MockSummaryExtractor2.cpp (89%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Registries/MockTUSummaryBuilder.h (69%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Registries/SerializationFormatRegistryTest.cpp (95%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Registries/SummaryExtractorRegistryTest.cpp (96%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/SSAFBuiltinTestForceLinker.h (88%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/SSAFTestForceLinker.h (75%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Serialization/JSONFormatTest/JSONFormatTest.cpp (99%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Serialization/JSONFormatTest/JSONFormatTest.h (95%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Serialization/JSONFormatTest/LUSummaryTest.cpp (99%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Serialization/JSONFormatTest/TUSummaryTest.cpp (99%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/SummaryData/SummaryDataTest.cpp (94%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/SummaryNameTest.cpp (93%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/TUSummaryBuilderTest.cpp (94%)
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/TestFixture.cpp (76%)
create mode 100644 clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h
rename clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/WholeProgramAnalysis/AnalysisDriverTest.cpp (94%)
rename llvm/utils/gn/secondary/clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Analyses/BUILD.gn (80%)
rename llvm/utils/gn/secondary/clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Core/BUILD.gn (95%)
rename llvm/utils/gn/secondary/clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Frontend/BUILD.gn (70%)
rename llvm/utils/gn/secondary/clang/lib/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/Tool/BUILD.gn (60%)
rename llvm/utils/gn/secondary/clang/unittests/{ScalableStaticAnalysis => ScalableStaticAnalysisFramework}/BUILD.gn (89%)
diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml
index 469dc511caf63..d8cba3bfa7272 100644
--- a/.github/new-prs-labeler.yml
+++ b/.github/new-prs-labeler.yml
@@ -698,11 +698,11 @@ clang:analysis:
clang:ssaf:
- changed-files:
- any-glob-to-any-file:
- - clang/docs/ScalableStaticAnalysis/**
- - clang/include/clang/ScalableStaticAnalysis/**
- - clang/lib/ScalableStaticAnalysis/**
+ - clang/docs/ScalableStaticAnalysisFramework/**
+ - clang/include/clang/ScalableStaticAnalysisFramework/**
+ - clang/lib/ScalableStaticAnalysisFramework/**
- clang/test/Analysis/Scalable/**
- - clang/unittests/ScalableStaticAnalysis/**
+ - clang/unittests/ScalableStaticAnalysisFramework/**
clang:static analyzer:
- changed-files:
diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/ForceLinkerHeaders.rst b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
similarity index 89%
rename from clang/docs/ScalableStaticAnalysis/developer-docs/ForceLinkerHeaders.rst
rename to clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
index 1a369404699da..c04b2b786308f 100644
--- a/clang/docs/ScalableStaticAnalysis/developer-docs/ForceLinkerHeaders.rst
+++ b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
@@ -66,21 +66,21 @@ Header hierarchy
SSAFForceLinker.h (umbrella — include this in binaries)
└── SSAFBuiltinForceLinker.h (upstream built-in anchors only)
-- ``clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h`` — anchors for
+- ``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h`` — anchors for
upstream-provided (built-in) extractors and formats (e.g. ``JSONFormat``).
-- ``clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h`` — umbrella header
+- ``clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h`` — umbrella header
that includes ``SSAFBuiltinForceLinker.h``. This is the header that
downstream projects should modify to add their own force-linker includes
(see :doc:`HowToExtend`).
Include the umbrella header with ``// IWYU pragma: keep`` in any translation
unit that must guarantee all registrations are active — typically the entry
-point of a binary that uses ``clangScalableStaticAnalysisCore``:
+point of a binary that uses ``clangScalableStaticAnalysisFrameworkCore``:
.. code-block:: c++
// In ExecuteCompilerInvocation.cpp
- #include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
+ #include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
Naming convention
=================
@@ -103,10 +103,10 @@ library, regardless of whether any symbols are referenced:
.. code-block:: bash
# GNU ld / lld (Linux, BSD)
- -Wl,--whole-archive -lclangScalableStaticAnalysisCore -Wl,--no-whole-archive
+ -Wl,--whole-archive -lclangScalableStaticAnalysisFrameworkCore -Wl,--no-whole-archive
# Apple ld
- -Wl,-force_load,libclangScalableStaticAnalysisCore.a
+ -Wl,-force_load,libclangScalableStaticAnalysisFrameworkCore.a
Since CMake 3.24, the ``$<LINK_LIBRARY:WHOLE_ARCHIVE,...>`` generator expression
provides a portable way to do the same:
@@ -114,7 +114,7 @@ provides a portable way to do the same:
.. code-block:: cmake
target_link_libraries(clang PRIVATE
- "$<LINK_LIBRARY:WHOLE_ARCHIVE,clangScalableStaticAnalysisCore>")
+ "$<LINK_LIBRARY:WHOLE_ARCHIVE,clangScalableStaticAnalysisFrameworkCore>")
**Why we did not choose this approach**:
diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/HowToExtend.rst b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
similarity index 91%
rename from clang/docs/ScalableStaticAnalysis/developer-docs/HowToExtend.rst
rename to clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
index 0c94cfca54dee..7d92d7e6f2de7 100644
--- a/clang/docs/ScalableStaticAnalysis/developer-docs/HowToExtend.rst
+++ b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
@@ -10,7 +10,7 @@ SSAF is designed to be extensible with new **summary extractors** and **serializ
Extensions can be added in three ways:
#. **Statically, in-tree** — built as part of the upstream LLVM/Clang tree.
-#. **Statically, out-of-tree (downstream)** — built in a downstream fork or project that links ``clangScalableStaticAnalysisCore`` as a static library.
+#. **Statically, out-of-tree (downstream)** — built in a downstream fork or project that links ``clangScalableStaticAnalysisFrameworkCore`` as a static library.
#. **Dynamically, via plugins** — loaded at runtime as shared objects.
All three approaches use the same ``llvm::Registry``-based registration mechanism.
@@ -28,7 +28,7 @@ Step 1: Implement the extractor
.. code-block:: c++
//--- MyExtractor.h
- #include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+ #include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
namespace clang::ssaf {
@@ -49,7 +49,7 @@ Step 2: Register the extractor
//--- MyExtractor.cpp
#include "MyExtractor.h"
- #include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+ #include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
using namespace clang::ssaf;
@@ -74,7 +74,7 @@ Add the following to the appropriate force-linker header:
SSAFMyExtractorAnchorSource;
For **in-tree** additions, add this to
-``clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h``.
+``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h``.
For **downstream** additions, see `Out-of-tree (downstream) extensions`_ below.
@@ -93,7 +93,7 @@ Your format class must inherit from ``SerializationFormat`` and define a ``Forma
.. code-block:: c++
//--- MyFormat.h
- #include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+ #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
#include "clang/Support/Compiler.h"
#include "llvm/Support/Registry.h"
@@ -121,7 +121,7 @@ Step 2: Register the format
//--- MyFormat.cpp
#include "MyFormat.h"
- #include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+ #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
using namespace clang::ssaf;
@@ -172,8 +172,8 @@ In-tree extensions
For extensions that are part of the upstream LLVM/Clang tree:
-#. Add the anchor to ``clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h``.
-#. Add the source files to the ``clangScalableStaticAnalysisCore`` CMake library target.
+#. Add the anchor to ``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h``.
+#. Add the source files to the ``clangScalableStaticAnalysisFrameworkCore`` CMake library target.
#. That's it — the ``SSAFForceLinker.h`` umbrella includes ``SSAFBuiltinForceLinker.h``
transitively, so any binary that includes the umbrella will pull in the registration.
diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/SummaryExtractionInternals.rst b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/SummaryExtractionInternals.rst
similarity index 100%
rename from clang/docs/ScalableStaticAnalysis/developer-docs/SummaryExtractionInternals.rst
rename to clang/docs/ScalableStaticAnalysisFramework/developer-docs/SummaryExtractionInternals.rst
diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/index.rst b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/index.rst
similarity index 100%
rename from clang/docs/ScalableStaticAnalysis/developer-docs/index.rst
rename to clang/docs/ScalableStaticAnalysisFramework/developer-docs/index.rst
diff --git a/clang/docs/ScalableStaticAnalysis/index.rst b/clang/docs/ScalableStaticAnalysisFramework/index.rst
similarity index 100%
rename from clang/docs/ScalableStaticAnalysis/index.rst
rename to clang/docs/ScalableStaticAnalysisFramework/index.rst
diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/SummaryExtraction.rst b/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
similarity index 84%
rename from clang/docs/ScalableStaticAnalysis/user-docs/SummaryExtraction.rst
rename to clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
index fd58bf3fe931e..96892cfa5fdea 100644
--- a/clang/docs/ScalableStaticAnalysis/user-docs/SummaryExtraction.rst
+++ b/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
@@ -30,8 +30,8 @@ Diagnostics
***********
In case the ``--ssaf-*`` flags are used incorrectly, or some extractor fails to implement the desired serialization format
-or just happens to have an error, then the error is forwarded as a ``scalable-static-analysis`` error.
-These errors can be downgraded into warnings using ``-Wno-error=scalable-static-analysis``.
-These errors can be completely suppressed using ``-Wno-scalable-static-analysis``.
+or just happens to have an error, then the error is forwarded as a ``scalable-static-analysis-framework`` error.
+These errors can be downgraded into warnings using ``-Wno-error=scalable-static-analysis-framework``.
+These errors can be completely suppressed using ``-Wno-scalable-static-analysis-framework``.
-See the `diagnostic flags <https://clang.llvm.org/docs/DiagnosticsReference.html#wscalable-static-analysis>`_ for the full list of diagnostics controlled by ``-Wscalable-static-analysis``.
+See the `diagnostic flags <https://clang.llvm.org/docs/DiagnosticsReference.html#wscalable-static-analysis-framework>`_ for the full list of diagnostics controlled by ``-Wscalable-static-analysis-framework``.
diff --git a/clang/docs/index.rst b/clang/docs/index.rst
index 05abb3e80e3c1..898667e36011d 100644
--- a/clang/docs/index.rst
+++ b/clang/docs/index.rst
@@ -29,7 +29,7 @@ Using Clang as a Compiler
ThreadSafetyAnalysis
LifetimeSafety
SafeBuffers
- ScalableStaticAnalysis/index
+ ScalableStaticAnalysisFramework/index
DataFlowAnalysisIntro
FunctionEffectAnalysis
AddressSanitizer
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 6e0516a3834bc..f384a97b6825e 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -403,25 +403,25 @@ def warn_profile_data_misexpect : Warning<
def warn_ssaf_extract_tu_summary_file_unknown_output_format :
Warning<"unknown output summary file format '%0' "
"specified by '--ssaf-tu-summary-file=%1'">,
- InGroup<ScalableStaticAnalysis>, DefaultError;
+ InGroup<ScalableStaticAnalysisFramework>, DefaultError;
def warn_ssaf_extract_tu_summary_file_unknown_format :
Warning<"failed to parse the value of '--ssaf-tu-summary-file=%0' "
"the value must follow the '<path>.<format>' pattern">,
- InGroup<ScalableStaticAnalysis>, DefaultError;
+ InGroup<ScalableStaticAnalysisFramework>, DefaultError;
def warn_ssaf_must_enable_summary_extractors :
Warning<"must enable some summary extractors using the "
"'--ssaf-extract-summaries=' option">,
- InGroup<ScalableStaticAnalysis>, DefaultError;
+ InGroup<ScalableStaticAnalysisFramework>, DefaultError;
def warn_ssaf_extract_summary_unknown_extractor_name :
Warning<"no summary extractor%s0 %plural{1:was|:were}0 registered with name: %1">,
- InGroup<ScalableStaticAnalysis>, DefaultError;
+ InGroup<ScalableStaticAnalysisFramework>, DefaultError;
def warn_ssaf_write_tu_summary_failed :
Warning<"failed to write TU summary to '%0': %1">,
- InGroup<ScalableStaticAnalysis>, DefaultError;
+ InGroup<ScalableStaticAnalysisFramework>, DefaultError;
def err_extract_api_ignores_file_not_found :
Error<"file '%0' specified by '--extract-api-ignores=' not found">, DefaultFatal;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index e2b3852c55539..74f9fab14d82c 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1926,7 +1926,7 @@ def BitIntExtension : DiagGroup<"bit-int-extension">;
def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">;
// Warnings related to the "Scalable Static Analysis Framework" - SSAF.
-def ScalableStaticAnalysis : DiagGroup<"scalable-static-analysis">;
+def ScalableStaticAnalysisFramework : DiagGroup<"scalable-static-analysis-framework">;
// Warnings about using the non-standard extension having an explicit specialization
// with a storage class specifier.
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h
similarity index 74%
rename from clang/include/clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h
index e3a335384792a..8056b1001a216 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include <set>
namespace clang::ssaf {
@@ -51,4 +51,4 @@ struct CallGraphSummary final : public EntitySummary {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
similarity index 91%
rename from clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
index 79b66e40be0dd..429bb74fb417e 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
#include "clang/AST/Expr.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include <set>
@@ -120,4 +120,4 @@ createEntityPointerLevel(const NamedDecl *ND,
EntityPointerLevel incrementPointerLevel(const EntityPointerLevel &E);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
similarity index 59%
rename from clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
index e34fd1007b5fd..7b125edb1fb7f 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
-#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
namespace clang::ssaf {
llvm::json::Value
@@ -22,4 +22,4 @@ entityPointerLevelFromJSON(const llvm::json::Value &EPLData,
JSONFormat::EntityIdFromJSONFn EntityIdFromJSON);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
similarity index 74%
rename from clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
index 17ac0a94f3746..ec0c4334a802e 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
-#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
namespace clang::ssaf {
/// An UnsafeBufferUsageEntitySummary contains a set of EntityPointerLevels
@@ -47,4 +47,4 @@ class UnsafeBufferUsageEntitySummary final : public EntitySummary {
};
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h
similarity index 63%
rename from clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h
index 0f94fab106ea1..6a2d1161246f2 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h
@@ -10,11 +10,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
-#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include "llvm/Support/Error.h"
namespace clang::ssaf {
@@ -26,4 +26,4 @@ llvm::Expected<std::unique_ptr<EntitySummary>> serializeDeserializeRoundTrip(
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGETEST_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h
similarity index 82%
rename from clang/include/clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h
index aa8ce469397a0..5057f8ac4505f 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ASTENTITYMAPPING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ASTENTITYMAPPING_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ASTENTITYMAPPING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ASTENTITYMAPPING_H
#include "clang/AST/Decl.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
#include "llvm/ADT/StringRef.h"
#include <optional>
@@ -44,4 +44,4 @@ std::optional<EntityName> getEntityNameForReturn(const FunctionDecl *FD);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ASTENTITYMAPPING_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ASTENTITYMAPPING_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h
similarity index 91%
rename from clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h
index 680ca6ab639dd..12a42df213e2a 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h
@@ -11,10 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYLINKER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYLINKER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYLINKER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYLINKER_H
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
#include "llvm/Support/Error.h"
#include <map>
#include <memory>
@@ -89,4 +89,4 @@ class EntityLinker {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYLINKER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYLINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h
similarity index 79%
rename from clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h
index 9442ecbbe24cc..461fd74c8cafe 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h
@@ -11,10 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
#include "llvm/Support/Error.h"
#include <map>
@@ -39,4 +39,4 @@ class EntitySummaryEncoding {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h
similarity index 67%
rename from clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h
index 58568d365c0ae..a36002006430c 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h
@@ -11,15 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARY_H
-
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARY_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include <map>
#include <memory>
@@ -52,4 +52,4 @@ class LUSummary {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h
similarity index 69%
rename from clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h
index 85c5fc0f1f46a..a4248a4d1e79d 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h
@@ -11,15 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
-
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
#include <map>
#include <memory>
@@ -56,4 +56,4 @@ class LUSummaryEncoding {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h
similarity index 70%
rename from clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h
index 18998e6a1f862..4fcf91d1c0423 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h
@@ -11,15 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
-
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
#include <map>
#include <memory>
@@ -57,4 +57,4 @@ class TUSummaryEncoding {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h
similarity index 95%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h
index 6da5a9e42c4da..16c6fd6fcb4ef 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h
@@ -15,8 +15,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_BUILDNAMESPACE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_BUILDNAMESPACE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_BUILDNAMESPACE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_BUILDNAMESPACE_H
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
@@ -126,4 +126,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_BUILDNAMESPACE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_BUILDNAMESPACE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityId.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h
similarity index 88%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityId.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h
index e8e36119927c8..0da76e17c823e 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityId.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYID_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYID_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYID_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYID_H
#include "llvm/Support/raw_ostream.h"
#include <cstddef>
@@ -51,4 +51,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityId &Id);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYID_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYID_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h
similarity index 79%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h
index 316a1f36369ec..d74b871df3e16 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYIDTABLE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYIDTABLE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYIDTABLE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYIDTABLE_H
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
#include <functional>
#include <map>
@@ -50,4 +50,4 @@ class EntityIdTable {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYIDTABLE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYIDTABLE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h
similarity index 87%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h
index 164fd458b1281..cdae99ad0b6b2 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYLINKAGE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYLINKAGE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYLINKAGE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYLINKAGE_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -49,4 +49,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYLINKAGE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYLINKAGE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityName.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h
similarity index 87%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityName.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h
index ecc402e05d4b8..853ac96209a86 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityName.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYNAME_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYNAME_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYNAME_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYNAME_H
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -59,4 +59,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityName &EN);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYNAME_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def
similarity index 100%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/SummaryName.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h
similarity index 84%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Model/SummaryName.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h
index d299efc6fc638..99b5308e61a4e 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Model/SummaryName.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_SUMMARYNAME_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_SUMMARYNAME_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_SUMMARYNAME_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_SUMMARYNAME_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -38,4 +38,4 @@ class SummaryName {
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SummaryName &SN);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_SUMMARYNAME_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_SUMMARYNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h
similarity index 95%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h
index 6f9b480a7afa5..b0126a1abac9f 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h
@@ -10,11 +10,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_H
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/Support/JSON.h"
@@ -235,4 +235,4 @@ extern template class CLANG_TEMPLATE_ABI
Registry<clang::ssaf::JSONFormat::AnalysisResultRegistry::Codec>;
} // namespace llvm
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
similarity index 89%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
index 85bdc0cbcab2a..fd261c6d9a723 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
@@ -11,17 +11,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
-
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
@@ -82,7 +82,7 @@ class SerializationFormat {
#define FIELD(CLASS, FIELD_NAME) \
static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
-#include "clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def"
/// Per-format plugin registry for analysis result (de)serializers.
///
@@ -221,4 +221,4 @@ template <class SerializerFn, class DeserializerFn> struct FormatInfoEntry {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
similarity index 87%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
index 600c993264926..5855cd84336e3 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
@@ -51,7 +51,7 @@
// );
//
// Finally, insert a use of the new anchor symbol into the force-linker header:
-// clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h:
+// clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h:
//
// This anchor is used to force the linker to link the MyFormat registration.
//
@@ -61,10 +61,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Registry.h"
@@ -94,4 +94,4 @@ extern template class CLANG_TEMPLATE_ABI
Registry<clang::ssaf::SerializationFormat>;
} // namespace llvm
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h
similarity index 88%
rename from clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h
index c0f0308533a46..b26e5fadc58c2 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h
@@ -11,12 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Error.h"
#include <memory>
@@ -90,4 +90,4 @@ class LUSummaryConsumer final {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h
similarity index 76%
rename from clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h
index 8c7f98622cc25..83386a684181e 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATA_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATA_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATA_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATA_H
namespace clang::ssaf {
@@ -25,4 +25,4 @@ class SummaryData {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATA_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATA_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h
similarity index 83%
rename from clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h
index 071741e23b56c..343e98d46ce39 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h
@@ -12,14 +12,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
-
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h"
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include <memory>
namespace clang::ssaf {
@@ -94,4 +94,4 @@ class SummaryDataBuilder : public SummaryDataBuilderBase {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h
similarity index 85%
rename from clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h
index 629281a477d6c..630e1c298f9e1 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h
@@ -19,10 +19,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h"
#include "llvm/Support/Registry.h"
#include <memory>
#include <string>
@@ -69,4 +69,4 @@ class SummaryDataBuilderRegistry {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h
similarity index 86%
rename from clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h
index b0e71a4f1031f..3261085f8d5a2 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h
@@ -11,13 +11,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h"
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
#include "llvm/Support/Error.h"
#include <map>
#include <memory>
@@ -112,4 +112,4 @@ class SummaryDataStore {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h
similarity index 80%
rename from clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h
index d08dd68935bac..c6bf6b6fcd4bb 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h
@@ -10,10 +10,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
#include <type_traits>
namespace clang::ssaf {
@@ -38,4 +38,4 @@ inline constexpr bool HasSummaryName_v = HasSummaryName<T>::value;
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h
similarity index 96%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h
index 2ad4d8e06eb90..2cce23766b026 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_ERRORBUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_ERRORBUILDER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_ERRORBUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_ERRORBUILDER_H
#include "llvm/Support/Error.h"
#include "llvm/Support/FormatVariadic.h"
@@ -207,4 +207,4 @@ class ErrorBuilder {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_ERRORBUILDER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_ERRORBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h
similarity index 78%
rename from clang/include/clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h
index e4a7b54033924..437152d43f425 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h
@@ -11,15 +11,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_FORMATPROVIDERS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_FORMATPROVIDERS_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_FORMATPROVIDERS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_FORMATPROVIDERS_H
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
#include "llvm/Support/FormatProviders.h"
#include "llvm/Support/raw_ostream.h"
@@ -90,4 +90,4 @@ template <> struct format_provider<clang::ssaf::AnalysisName> {
} // namespace llvm
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_FORMATPROVIDERS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_FORMATPROVIDERS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h
similarity index 69%
rename from clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h
index 305abc05f19f3..e6c8a4716eaf2 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_ENTITYSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_ENTITYSUMMARY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_ENTITYSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_ENTITYSUMMARY_H
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
#include <type_traits>
namespace clang::ssaf {
@@ -27,4 +27,4 @@ using DerivesFromEntitySummary =
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_ENTITYSUMMARY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_ENTITYSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
similarity index 83%
rename from clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
index 6ef0c6612f64e..da57838c64b2f 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
@@ -15,7 +15,7 @@
// X("MyExtractor", "My awesome extractor");
//
// Finally, insert a use of the new anchor symbol into the force-linker header:
-// clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h:
+// clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h:
//
// extern volatile int SSAFMyExtractorAnchorSource;
// [[maybe_unused]] static int SSAFMyExtractorAnchorDestination =
@@ -23,10 +23,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Registry.h"
@@ -55,4 +55,4 @@ using TUSummaryExtractorRegistry =
LLVM_DECLARE_REGISTRY(clang::ssaf::TUSummaryExtractorRegistry)
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h
similarity index 59%
rename from clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h
index e9ec5b19e2e4d..1609e68257d57 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h
@@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARY_H
-
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARY_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include <map>
#include <memory>
@@ -43,4 +43,4 @@ class TUSummary {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
similarity index 86%
rename from clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
index 3208c7ebb15cc..fd07abfab8c87 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include <memory>
#include <utility>
@@ -73,4 +73,4 @@ TUSummaryBuilder::addSummary(EntityId Entity,
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
similarity index 72%
rename from clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
index 185c9ddd69055..629a8d0e35ae4 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
#include "clang/AST/ASTConsumer.h"
@@ -25,4 +25,4 @@ class TUSummaryExtractor : public ASTConsumer {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h
similarity index 82%
rename from clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h
index 638791f9b1646..1a9a5de76ffab 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h
@@ -12,10 +12,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
#include <vector>
namespace clang::ssaf {
@@ -57,4 +57,4 @@ class AnalysisBase {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h
similarity index 88%
rename from clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h
index 148234f5c9649..156d8e806bd0f 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h
@@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/Support/Error.h"
#include <memory>
@@ -92,4 +92,4 @@ class AnalysisDriver final {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h
similarity index 85%
rename from clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h
index 71a0a26b9853d..32f76e73b14e0 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
@@ -46,4 +46,4 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const AnalysisName &AN);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
similarity index 85%
rename from clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
index f8f76b8acd4b4..44eabce6c809c 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
@@ -28,13 +28,13 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Registry.h"
#include <memory>
@@ -106,4 +106,4 @@ class AnalysisRegistry {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h
similarity index 75%
rename from clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h
index fc10a6f2707fb..07d1f0549a9ee 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h
@@ -11,8 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
namespace clang::ssaf {
@@ -27,4 +27,4 @@ class AnalysisResult {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h
similarity index 75%
rename from clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h
index f4daf01b2660f..78df3b35648c2 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h
@@ -10,10 +10,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
#include <type_traits>
namespace clang::ssaf {
@@ -33,4 +33,4 @@ inline constexpr bool HasAnalysisName_v = HasAnalysisName<T>::value;
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h
similarity index 86%
rename from clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h
index 1fb33c83ed6b0..ff9470e0a2284 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h
@@ -12,14 +12,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
-
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h"
#include "llvm/Support/Error.h"
#include <map>
#include <memory>
@@ -130,4 +130,4 @@ class DerivedAnalysis : public DerivedAnalysisBase {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h
similarity index 83%
rename from clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h
index cf3bec9bb3b5e..5b7c2c9b6b8c2 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h
@@ -12,15 +12,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
-
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h"
#include "llvm/Support/Error.h"
#include <memory>
@@ -118,4 +118,4 @@ class SummaryAnalysis : public SummaryAnalysisBase {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h
similarity index 81%
rename from clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h
index cdc74ded19443..8e7693b78d485 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h
@@ -11,14 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
-
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h"
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h"
#include "llvm/Support/Error.h"
#include <map>
#include <memory>
@@ -96,4 +96,4 @@ class WPASuite {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h b/clang/include/clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h
similarity index 78%
rename from clang/include/clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h
index 300aab9560be2..fe5d75149914e 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
#include "clang/Frontend/FrontendAction.h"
#include <memory>
@@ -30,4 +30,4 @@ class TUSummaryExtractorFrontendAction final : public WrapperFrontendAction {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
similarity index 88%
rename from clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
index 811fce1142bec..5616976e10f77 100644
--- a/clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
@@ -13,12 +13,12 @@
///
/// Include this header (with IWYU pragma: keep) in any translation unit that
/// must guarantee these registrations are active — typically the entry point
-/// of a binary that uses clangScalableStaticAnalysisCore.
+/// of a binary that uses clangScalableStaticAnalysisFrameworkCore.
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFBUILTINFORCELINKER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFBUILTINFORCELINKER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
// TODO: Move these to the `clang::ssaf` namespace.
@@ -55,4 +55,4 @@ extern volatile int CallGraphJSONFormatAnchorSource;
[[maybe_unused]] static int CallGraphJSONFormatAnchorDestination =
CallGraphJSONFormatAnchorSource;
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFBUILTINFORCELINKER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h
similarity index 76%
rename from clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h
index bf0b74e3955f3..204a504c36435 100644
--- a/clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h
@@ -13,13 +13,13 @@
///
/// Include this header (with IWYU pragma: keep) in any translation unit that
/// must guarantee these registrations are active — typically the entry point
-/// of a binary that uses clangScalableStaticAnalysisCore.
+/// of a binary that uses clangScalableStaticAnalysisFrameworkCore.
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFFORCELINKER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFFORCELINKER_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFFORCELINKER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFFORCELINKER_H
#include "SSAFBuiltinForceLinker.h" // IWYU pragma: keep
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFFORCELINKER_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFFORCELINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Tool/Utils.h b/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
similarity index 92%
rename from clang/include/clang/ScalableStaticAnalysis/Tool/Utils.h
rename to clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
index f02bb8152cfd1..f7ee5c28ffe89 100644
--- a/clang/include/clang/ScalableStaticAnalysis/Tool/Utils.h
+++ b/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
@@ -13,10 +13,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_TOOL_UTILS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_TOOL_UTILS_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CommandLine.h"
@@ -92,4 +92,4 @@ struct FormatFile {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_TOOL_UTILS_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
diff --git a/clang/include/module.modulemap b/clang/include/module.modulemap
index fece3e1c2202a..62a3ba104b0df 100644
--- a/clang/include/module.modulemap
+++ b/clang/include/module.modulemap
@@ -146,11 +146,11 @@ module Clang_Options { requires cplusplus umbrella "clang/Options" module * { ex
module Clang_Parse { requires cplusplus umbrella "clang/Parse" module * { export * } }
module Clang_Rewrite { requires cplusplus umbrella "clang/Rewrite/Core" module * { export * } }
module Clang_RewriteFrontend { requires cplusplus umbrella "clang/Rewrite/Frontend" module * { export * } }
-module Clang_ScalableStaticAnalysis {
+module Clang_ScalableStaticAnalysisFramework {
requires cplusplus
- umbrella "clang/ScalableStaticAnalysis"
+ umbrella "clang/ScalableStaticAnalysisFramework"
- textual header "clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def"
+ textual header "clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def"
module * { export * }
}
diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt
index dee31cb3f166e..d9d1e4630a416 100644
--- a/clang/lib/CMakeLists.txt
+++ b/clang/lib/CMakeLists.txt
@@ -23,7 +23,7 @@ add_subdirectory(DirectoryWatcher)
add_subdirectory(Index)
add_subdirectory(IndexSerialization)
add_subdirectory(InstallAPI)
-add_subdirectory(ScalableStaticAnalysis)
+add_subdirectory(ScalableStaticAnalysisFramework)
add_subdirectory(StaticAnalyzer)
add_subdirectory(Format)
if(CLANG_INCLUDE_TESTS)
diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index feaaaa3ab2e87..5fe10052d267f 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -112,9 +112,9 @@ add_clang_library(clangDriver
clangBasic
clangDependencyScanning
clangFrontend
- clangScalableStaticAnalysisAnalyses
- clangScalableStaticAnalysisCore
- clangScalableStaticAnalysisFrontend
+ clangScalableStaticAnalysisFrameworkAnalyses
+ clangScalableStaticAnalysisFrameworkCore
+ clangScalableStaticAnalysisFrameworkFrontend
clangSerialization
clangLex
clangOptions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 5bd3b95a65200..c98ac919f7d2a 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -70,9 +70,9 @@
#include "clang/Driver/Types.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Options/Options.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallSet.h"
diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt
index 514c2728170de..24623303e6bdb 100644
--- a/clang/lib/FrontendTool/CMakeLists.txt
+++ b/clang/lib/FrontendTool/CMakeLists.txt
@@ -4,9 +4,9 @@ set(LLVM_LINK_COMPONENTS
)
set(link_libs
- clangScalableStaticAnalysisAnalyses
- clangScalableStaticAnalysisCore
- clangScalableStaticAnalysisFrontend
+ clangScalableStaticAnalysisFrameworkAnalyses
+ clangScalableStaticAnalysisFrameworkCore
+ clangScalableStaticAnalysisFrameworkFrontend
clangBasic
clangCodeGen
clangDriver
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 1a4a3e0050bbb..e4622496758ac 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -23,8 +23,8 @@
#include "clang/FrontendTool/Utils.h"
#include "clang/Options/Options.h"
#include "clang/Rewrite/Frontend/FrontendActions.h"
-#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
-#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h"
+#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
#include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
#include "llvm/Option/OptTable.h"
diff --git a/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
deleted file mode 100644
index d3b30e78755a8..0000000000000
--- a/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Support
- )
-
-add_clang_library(clangScalableStaticAnalysisFrontend
- TUSummaryExtractorFrontendAction.cpp
-
- LINK_LIBS
- clangAST
- clangBasic
- clangFrontend
- clangScalableStaticAnalysisAnalyses
- clangScalableStaticAnalysisCore
- clangSema
- )
diff --git a/clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt
deleted file mode 100644
index 134f8bb003f19..0000000000000
--- a/clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Support
- )
-
-add_clang_library(clangScalableStaticAnalysisTool
- Utils.cpp
-
- LINK_LIBS
- clangBasic
- clangScalableStaticAnalysisCore
- )
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
similarity index 76%
rename from clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
rename to clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
index fcbdaa8303091..88dcef0c5a2fa 100644
--- a/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
@@ -2,7 +2,7 @@ set(LLVM_LINK_COMPONENTS
Support
)
-add_clang_library(clangScalableStaticAnalysisAnalyses
+add_clang_library(clangScalableStaticAnalysisFrameworkAnalyses
CallGraph/CallGraphExtractor.cpp
CallGraph/CallGraphJSONFormat.cpp
EntityPointerLevel/EntityPointerLevel.cpp
@@ -14,7 +14,7 @@ add_clang_library(clangScalableStaticAnalysisAnalyses
clangAST
clangAnalysis
clangBasic
- clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisFrameworkCore
DEPENDS
)
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
similarity index 91%
rename from clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractor.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
index a625cb13db842..1dbed7e0b0d8a 100644
--- a/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
@@ -13,10 +13,10 @@
#include "clang/Analysis/AnalysisDeclContext.h"
#include "clang/Analysis/CallGraph.h"
#include "clang/Basic/SourceManager.h"
-#include "clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
#include "llvm/ADT/STLExtras.h"
#include <memory>
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphJSONFormat.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
similarity index 95%
rename from clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphJSONFormat.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
index 6cc1ab013c178..860e26417eb55 100644
--- a/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphJSONFormat.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/JSON.h"
#include <memory>
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
similarity index 96%
rename from clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
index 5c0230561eec5..52e6705ec43af 100644
--- a/clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
@@ -6,14 +6,14 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
#include "SSAFAnalysesCommon.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/StmtVisitor.h"
-#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
#include <optional>
using namespace clang;
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
similarity index 100%
rename from clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
similarity index 90%
rename from clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
rename to clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
index e73e3fe7e3f2a..acc95f799ca9d 100644
--- a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
@@ -9,8 +9,8 @@
// Common code in SSAF analyses implementations
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_SSAFANALYSESCOMMON_H
-#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_SSAFANALYSESCOMMON_H
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_SSAFANALYSESCOMMON_H
+#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_SSAFANALYSESCOMMON_H
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTTypeTraits.h"
@@ -57,4 +57,4 @@ void findMatchesIn(
} // namespace clang::ssaf
-#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_SSAFANALYSESCOMMON_H
+#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_SSAFANALYSESCOMMON_H
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
similarity index 88%
rename from clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
index 99a5d6b3a2942..ea5d2297b9836 100644
--- a/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
@@ -6,12 +6,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
#include "SSAFAnalysesCommon.h"
-#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
-#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
#include <cstdint>
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
similarity index 86%
rename from clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
index 9dbf586554ad8..550416c353fb7 100644
--- a/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -11,13 +11,13 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.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"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/clang/lib/ScalableStaticAnalysis/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt
similarity index 100%
rename from clang/lib/ScalableStaticAnalysis/CMakeLists.txt
rename to clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt
diff --git a/clang/lib/ScalableStaticAnalysis/Core/ASTEntityMapping.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.cpp
similarity index 93%
rename from clang/lib/ScalableStaticAnalysis/Core/ASTEntityMapping.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.cpp
index 1f4bf0da274ed..cac27b2c3f278 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/ASTEntityMapping.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.cpp
@@ -10,9 +10,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
#include "clang/AST/Decl.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
#include "clang/UnifiedSymbolResolution/USRGeneration.h"
#include "llvm/ADT/SmallString.h"
diff --git a/clang/lib/ScalableStaticAnalysis/Core/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
similarity index 94%
rename from clang/lib/ScalableStaticAnalysis/Core/CMakeLists.txt
rename to clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
index 6d87d7b8f96d3..83772ceff58bf 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
@@ -2,7 +2,7 @@ set(LLVM_LINK_COMPONENTS
Support
)
-add_clang_library(clangScalableStaticAnalysisCore
+add_clang_library(clangScalableStaticAnalysisFrameworkCore
ASTEntityMapping.cpp
EntityLinker/EntityLinker.cpp
Model/BuildNamespace.cpp
diff --git a/clang/lib/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.cpp
similarity index 92%
rename from clang/lib/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.cpp
index 462978932a53d..5aff18999e114 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.cpp
@@ -6,13 +6,13 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
#include <cassert>
using namespace clang::ssaf;
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/BuildNamespace.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.cpp
similarity index 96%
rename from clang/lib/ScalableStaticAnalysis/Core/Model/BuildNamespace.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.cpp
index f68ed961f71b9..09fff31e8f4a8 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Model/BuildNamespace.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
#include "../ModelStringConversions.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityId.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityId.cpp
similarity index 88%
rename from clang/lib/ScalableStaticAnalysis/Core/Model/EntityId.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityId.cpp
index a731bd24da4a0..9c4eec2d7e299 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityId.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityId.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
namespace clang::ssaf {
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityIdTable.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.cpp
similarity index 92%
rename from clang/lib/ScalableStaticAnalysis/Core/Model/EntityIdTable.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.cpp
index 651179c24a342..cb514581ca9ec 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityIdTable.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
#include <cassert>
namespace clang::ssaf {
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityLinkage.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.cpp
similarity index 93%
rename from clang/lib/ScalableStaticAnalysis/Core/Model/EntityLinkage.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.cpp
index 0bae90cd66a22..179b906c0b999 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityLinkage.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
#include "../ModelStringConversions.h"
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityName.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityName.cpp
similarity index 94%
rename from clang/lib/ScalableStaticAnalysis/Core/Model/EntityName.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityName.cpp
index c9e09df84143b..9145506865f24 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityName.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityName.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
namespace clang::ssaf {
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/SummaryName.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/SummaryName.cpp
similarity index 88%
rename from clang/lib/ScalableStaticAnalysis/Core/Model/SummaryName.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Model/SummaryName.cpp
index 66c7726a9da90..1609912aa7f90 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Model/SummaryName.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/SummaryName.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
namespace clang::ssaf {
diff --git a/clang/lib/ScalableStaticAnalysis/Core/ModelStringConversions.h b/clang/lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h
similarity index 87%
rename from clang/lib/ScalableStaticAnalysis/Core/ModelStringConversions.h
rename to clang/lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h
index baec4c574dd6c..f168a475de807 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/ModelStringConversions.h
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h
@@ -13,11 +13,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_MODELSTRINGCONVERSIONS_H
-#define LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_MODELSTRINGCONVERSIONS_H
+#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODELSTRINGCONVERSIONS_H
+#define LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODELSTRINGCONVERSIONS_H
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include <optional>
@@ -84,4 +84,4 @@ entityLinkageTypeFromString(llvm::StringRef Str) {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_MODELSTRINGCONVERSIONS_H
+#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODELSTRINGCONVERSIONS_H
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
similarity index 100%
rename from clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
similarity index 76%
rename from clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
index 697a377d185fa..9a1f5d49757f7 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
@@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
-#define LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
+#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
+#define LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
#include "llvm/Support/JSON.h"
#include <map>
@@ -49,4 +49,4 @@ class JSONEntitySummaryEncoding final : public EntitySummaryEncoding {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
+#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
similarity index 99%
rename from clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
index b48122e3573c5..8db7480e683f5 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
#include "llvm/Support/Registry.h"
// NOLINTNEXTLINE(misc-use-internal-linkage)
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.h b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h
similarity index 89%
rename from clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.h
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h
index 8e94f75283437..31a605efe90a5 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.h
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h
@@ -11,17 +11,17 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
-#define LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
+#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
+#define LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
#include "../../ModelStringConversions.h"
#include "JSONEntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/ErrorHandling.h"
@@ -169,4 +169,4 @@ llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT);
} // namespace clang::ssaf
-#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
+#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummary.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummary.cpp
similarity index 98%
rename from clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummary.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummary.cpp
index d26d6bf69d53c..1137499ba28c9 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummary.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummary.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
#include <set>
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
similarity index 98%
rename from clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
index 41007038c93d4..e748b021d1666 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
#include <set>
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummary.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummary.cpp
similarity index 98%
rename from clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummary.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummary.cpp
index 8e23ab0ba74c7..cc9460e956e7a 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummary.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummary.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
#include <set>
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
similarity index 98%
rename from clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
index d241a717c64a7..b16d70b6b0416 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
#include <set>
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/WPASuite.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp
similarity index 98%
rename from clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/WPASuite.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp
index 6f719caee43de..a37f8e838348e 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/WPASuite.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp
@@ -8,7 +8,7 @@
#include "JSONFormatImpl.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
namespace clang::ssaf {
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.cpp
similarity index 92%
rename from clang/lib/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.cpp
index e8841ea527078..0eb86f2fdee2f 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
#include <memory>
using namespace clang;
diff --git a/clang/lib/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.cpp
similarity index 90%
rename from clang/lib/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.cpp
index fb630e8117f59..3021751213d72 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h"
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
using namespace clang;
using namespace ssaf;
diff --git a/clang/lib/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.cpp
similarity index 91%
rename from clang/lib/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.cpp
index 4edf09c3fa659..f0f2db91e6ba6 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h"
using namespace clang;
using namespace ssaf;
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Support/ErrorBuilder.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.cpp
similarity index 96%
rename from clang/lib/ScalableStaticAnalysis/Core/Support/ErrorBuilder.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.cpp
index 99610725a6d23..3abc42e171065 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/Support/ErrorBuilder.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include <cassert>
diff --git a/clang/lib/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
similarity index 94%
rename from clang/lib/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
index 96b4c00ca8bff..01acc64f6f26c 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
#include <memory>
using namespace clang;
diff --git a/clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
similarity index 74%
rename from clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
index 93db2e3f1f9c7..180a78cae33a9 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
#include <memory>
#include <utility>
diff --git a/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.cpp
similarity index 93%
rename from clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.cpp
index f60c916e10b67..1425f7079295f 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.cpp
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
diff --git a/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.cpp
similarity index 86%
rename from clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.cpp
index 011b816ae03dc..9719196ed4d6d 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
using namespace clang::ssaf;
diff --git a/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
similarity index 89%
rename from clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
index 04d9467f016a1..8e1ea954d9afd 100644
--- a/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
#include "llvm/ADT/STLExtras.h"
using namespace clang;
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
new file mode 100644
index 0000000000000..3da1558810572
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
@@ -0,0 +1,15 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_library(clangScalableStaticAnalysisFrameworkFrontend
+ TUSummaryExtractorFrontendAction.cpp
+
+ LINK_LIBS
+ clangAST
+ clangBasic
+ clangFrontend
+ clangScalableStaticAnalysisFrameworkAnalyses
+ clangScalableStaticAnalysisFrameworkCore
+ clangSema
+ )
diff --git a/clang/lib/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.cpp b/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp
similarity index 92%
rename from clang/lib/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp
index db923feab420a..1c5170e354fb5 100644
--- a/clang/lib/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp
@@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
+#include "clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Basic/DiagnosticFrontend.h"
#include "clang/Frontend/MultiplexConsumer.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/IOSandbox.h"
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt
similarity index 98%
rename from clang/lib/ScalableStaticAnalysis/Plugins/CMakeLists.txt
rename to clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt
index a6af1e64e0ac3..b77ffc49c0f9f 100644
--- a/clang/lib/ScalableStaticAnalysis/Plugins/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt
@@ -1,6 +1,6 @@
if(CLANG_PLUGIN_SUPPORT AND LLVM_ENABLE_PLUGINS AND NOT WIN32)
# Plugins must never bring LLVM or Clang libraries in statically.
- # clang-ssaf-analyzer already loads clangScalableStaticAnalysisCore
+ # clang-ssaf-analyzer already loads clangScalableStaticAnalysisFrameworkCore
# and LLVM into the process; a second static copy would produce duplicate
# llvm::Registry instances with separate global state, breaking registration.
#
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/AnalysisResults.h b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/AnalysisResults.h
similarity index 81%
rename from clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/AnalysisResults.h
rename to clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/AnalysisResults.h
index f5072dce74e23..c8ae6a542b8f0 100644
--- a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/AnalysisResults.h
+++ b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/AnalysisResults.h
@@ -9,9 +9,9 @@
#ifndef EXAMPLE_PLUGIN_ANALYSIS_RESULTS_H
#define EXAMPLE_PLUGIN_ANALYSIS_RESULTS_H
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
#include <string>
#include <utility>
#include <vector>
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt
similarity index 87%
rename from clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/CMakeLists.txt
rename to clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt
index b4eea284636bf..06c8e2abc1bd4 100644
--- a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/CMakeLists.txt
+++ b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt
@@ -14,5 +14,5 @@ add_llvm_library(SSAFExamplePlugin MODULE BUILDTREE_ONLY
# Pull in SSAF and LLVM include paths without any static link dependency.
target_include_directories(SSAFExamplePlugin PRIVATE
- $<TARGET_PROPERTY:clangScalableStaticAnalysisCore,INTERFACE_INCLUDE_DIRECTORIES>
+ $<TARGET_PROPERTY:clangScalableStaticAnalysisFrameworkCore,INTERFACE_INCLUDE_DIRECTORIES>
)
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/PairsAnalysis.cpp b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/PairsAnalysis.cpp
similarity index 94%
rename from clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/PairsAnalysis.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/PairsAnalysis.cpp
index 94f08d7e9fb73..34923f4a15e6e 100644
--- a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/PairsAnalysis.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/PairsAnalysis.cpp
@@ -7,11 +7,11 @@
//===----------------------------------------------------------------------===//
#include "AnalysisResults.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Registry.h"
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsAnalysis.cpp b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsAnalysis.cpp
similarity index 92%
rename from clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsAnalysis.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsAnalysis.cpp
index 9d74b7b30d9bf..630a14544d7b0 100644
--- a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsAnalysis.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsAnalysis.cpp
@@ -7,11 +7,11 @@
//===----------------------------------------------------------------------===//
#include "AnalysisResults.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Registry.h"
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
similarity index 94%
rename from clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
index 5ceb0eb971673..14750de321824 100644
--- a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
@@ -7,9 +7,9 @@
//===----------------------------------------------------------------------===//
#include "AnalysisResults.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
#include "llvm/Support/Registry.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
new file mode 100644
index 0000000000000..53b900ec8c042
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
@@ -0,0 +1,11 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_library(clangScalableStaticAnalysisFrameworkTool
+ Utils.cpp
+
+ LINK_LIBS
+ clangBasic
+ clangScalableStaticAnalysisFrameworkCore
+ )
diff --git a/clang/lib/ScalableStaticAnalysis/Tool/Utils.cpp b/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
similarity index 99%
rename from clang/lib/ScalableStaticAnalysis/Tool/Utils.cpp
rename to clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
index 5b0963bfa4344..e8dde39a846e9 100644
--- a/clang/lib/ScalableStaticAnalysis/Tool/Utils.cpp
+++ b/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
+#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
diff --git a/clang/test/Analysis/Scalable/command-line-interface.cpp b/clang/test/Analysis/Scalable/command-line-interface.cpp
index ace510e3ca227..a632f487f2bb7 100644
--- a/clang/test/Analysis/Scalable/command-line-interface.cpp
+++ b/clang/test/Analysis/Scalable/command-line-interface.cpp
@@ -15,8 +15,8 @@
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]
-// UNKNOWN-FILE-FORMAT: error: unknown output summary file format 'unknownfmt' specified by '--ssaf-tu-summary-file={{.+}}.ssaf.unknownfmt' [-Wscalable-static-analysis]
-// NO-EXTRACTORS-ENABLED: error: must enable some summary extractors using the '--ssaf-extract-summaries=' option [-Wscalable-static-analysis]
-// NO-EXTRACTOR-WITH-NAME: error: no summary extractor was registered with name: extractor1 [-Wscalable-static-analysis]
-// NO-EXTRACTORS-WITH-NAME: error: no summary extractors were registered with name: extractor1, extractor2 [-Wscalable-static-analysis]
+// 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]
+// UNKNOWN-FILE-FORMAT: error: unknown output summary file format 'unknownfmt' specified by '--ssaf-tu-summary-file={{.+}}.ssaf.unknownfmt' [-Wscalable-static-analysis-framework]
+// NO-EXTRACTORS-ENABLED: error: must enable some summary extractors using the '--ssaf-extract-summaries=' option [-Wscalable-static-analysis-framework]
+// NO-EXTRACTOR-WITH-NAME: error: no summary extractor was registered with name: extractor1 [-Wscalable-static-analysis-framework]
+// NO-EXTRACTORS-WITH-NAME: error: no summary extractors were registered with name: extractor1, extractor2 [-Wscalable-static-analysis-framework]
diff --git a/clang/test/Analysis/Scalable/downgradable-errors.cpp b/clang/test/Analysis/Scalable/downgradable-errors.cpp
index eeec552bbe40f..494e3e71092ac 100644
--- a/clang/test/Analysis/Scalable/downgradable-errors.cpp
+++ b/clang/test/Analysis/Scalable/downgradable-errors.cpp
@@ -1,15 +1,15 @@
// DEFINE: %{filecheck} = FileCheck %s --match-full-lines --check-prefix
// RUN: not %clang -fsyntax-only %s --ssaf-tu-summary-file=foobar 2>&1 | %{filecheck}=DEFAULT-ERROR
-// RUN: %clang -fsyntax-only %s --ssaf-tu-summary-file=foobar -Wno-error=scalable-static-analysis 2>&1 | %{filecheck}=DEMOTED-TO-WARNING
-// RUN: %clang -fsyntax-only %s --ssaf-tu-summary-file=foobar -Wno-scalable-static-analysis 2>&1 | count 0
+// RUN: %clang -fsyntax-only %s --ssaf-tu-summary-file=foobar -Wno-error=scalable-static-analysis-framework 2>&1 | %{filecheck}=DEMOTED-TO-WARNING
+// RUN: %clang -fsyntax-only %s --ssaf-tu-summary-file=foobar -Wno-scalable-static-analysis-framework 2>&1 | count 0
-// This test demonstrates that the "scalable-static-analysis" diagnostics can be downgraded or completely silenced with the right flags.
+// This test demonstrates that the "scalable-static-analysis-framework" diagnostics can be downgraded or completely silenced with the right flags.
void empty() {}
-// DEFAULT-ERROR: error: failed to parse the value of '--ssaf-tu-summary-file=foobar' the value must follow the '<path>.<format>' pattern [-Wscalable-static-analysis]
+// DEFAULT-ERROR: error: failed to parse the value of '--ssaf-tu-summary-file=foobar' the value must follow the '<path>.<format>' pattern [-Wscalable-static-analysis-framework]
// DEFAULT-ERROR: 1 error generated.
-// DEMOTED-TO-WARNING: warning: failed to parse the value of '--ssaf-tu-summary-file=foobar' the value must follow the '<path>.<format>' pattern [-Wscalable-static-analysis]
+// DEMOTED-TO-WARNING: warning: failed to parse the value of '--ssaf-tu-summary-file=foobar' the value must follow the '<path>.<format>' pattern [-Wscalable-static-analysis-framework]
// DEMOTED-TO-WARNING: 1 warning generated.
diff --git a/clang/tools/clang-ssaf-format/CMakeLists.txt b/clang/tools/clang-ssaf-format/CMakeLists.txt
index ab3869e441ad9..33ce432be3f4a 100644
--- a/clang/tools/clang-ssaf-format/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-format/CMakeLists.txt
@@ -15,9 +15,9 @@ add_clang_tool(clang-ssaf-format
clang_target_link_libraries(clang-ssaf-format
PRIVATE
clangBasic
- clangScalableStaticAnalysisAnalyses
- clangScalableStaticAnalysisCore
- clangScalableStaticAnalysisTool
+ clangScalableStaticAnalysisFrameworkAnalyses
+ clangScalableStaticAnalysisFrameworkCore
+ clangScalableStaticAnalysisFrameworkTool
)
if(CLANG_PLUGIN_SUPPORT)
diff --git a/clang/tools/clang-ssaf-format/SSAFFormat.cpp b/clang/tools/clang-ssaf-format/SSAFFormat.cpp
index a314a73517f9d..c076c94e748a6 100644
--- a/clang/tools/clang-ssaf-format/SSAFFormat.cpp
+++ b/clang/tools/clang-ssaf-format/SSAFFormat.cpp
@@ -11,12 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
-#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
diff --git a/clang/tools/clang-ssaf-linker/CMakeLists.txt b/clang/tools/clang-ssaf-linker/CMakeLists.txt
index 7e6e59aaf9491..af65aaa3b1aeb 100644
--- a/clang/tools/clang-ssaf-linker/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-linker/CMakeLists.txt
@@ -10,7 +10,7 @@ add_clang_tool(clang-ssaf-linker
clang_target_link_libraries(clang-ssaf-linker
PRIVATE
clangBasic
- clangScalableStaticAnalysisAnalyses
- clangScalableStaticAnalysisCore
- clangScalableStaticAnalysisTool
+ clangScalableStaticAnalysisFrameworkAnalyses
+ clangScalableStaticAnalysisFrameworkCore
+ clangScalableStaticAnalysisFrameworkTool
)
diff --git a/clang/tools/clang-ssaf-linker/SSAFLinker.cpp b/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
index 84335ff55403d..7ee335b2a3990 100644
--- a/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
+++ b/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
@@ -11,12 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
-#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt
index 75e226e363812..2ae0906dd1571 100644
--- a/clang/unittests/CMakeLists.txt
+++ b/clang/unittests/CMakeLists.txt
@@ -91,7 +91,7 @@ add_subdirectory(Tooling)
add_subdirectory(Format)
add_subdirectory(Frontend)
add_subdirectory(Rewrite)
-add_subdirectory(ScalableStaticAnalysis)
+add_subdirectory(ScalableStaticAnalysisFramework)
add_subdirectory(Sema)
add_subdirectory(CodeGen)
if(HAVE_CLANG_REPL_SUPPORT)
diff --git a/clang/unittests/ScalableStaticAnalysis/TestFixture.h b/clang/unittests/ScalableStaticAnalysis/TestFixture.h
deleted file mode 100644
index 22fbff754fb37..0000000000000
--- a/clang/unittests/ScalableStaticAnalysis/TestFixture.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- TestFixture.h --------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_TESTFIXTURE_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_TESTFIXTURE_H
-
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
-#include "gtest/gtest.h"
-#include <iosfwd>
-
-namespace clang::ssaf {
-
-class TestFixture : public ::testing::Test {
-protected:
- static WPASuite makeWPASuite() { return WPASuite(); }
-
-#define FIELD(CLASS, FIELD_NAME) \
- static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
- static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
-#include "clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def"
-};
-
-void PrintTo(const BuildNamespace &BN, std::ostream *OS);
-void PrintTo(const EntityId &E, std::ostream *OS);
-void PrintTo(const EntityLinkage &EL, std::ostream *OS);
-void PrintTo(const EntityName &EN, std::ostream *OS);
-void PrintTo(const NestedBuildNamespace &NBN, std::ostream *OS);
-void PrintTo(const SummaryName &N, std::ostream *OS);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_TESTFIXTURE_H
diff --git a/clang/unittests/ScalableStaticAnalysis/ASTEntityMappingTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.cpp
similarity index 99%
rename from clang/unittests/ScalableStaticAnalysis/ASTEntityMappingTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.cpp
index a64eda451c61f..da921b7b7ab35 100644
--- a/clang/unittests/ScalableStaticAnalysis/ASTEntityMappingTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractorTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
similarity index 97%
rename from clang/unittests/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractorTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
index 56d0742b49283..39b3cf604857d 100644
--- a/clang/unittests/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractorTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
@@ -11,11 +11,11 @@
#include "clang/AST/Decl.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
similarity index 95%
rename from clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
index cb0ec95bcfb21..4a631a28897d0 100644
--- a/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
@@ -6,21 +6,21 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
#include "TestFixture.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/DynamicRecursiveASTVisitor.h"
#include "clang/Frontend/ASTUnit.h"
-#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h"
-#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/BuildNamespaceTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/BuildNamespaceTest.cpp
similarity index 96%
rename from clang/unittests/ScalableStaticAnalysis/BuildNamespaceTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/BuildNamespaceTest.cpp
index e98efd45ea6b0..0fe8bb6f18122 100644
--- a/clang/unittests/ScalableStaticAnalysis/BuildNamespaceTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/BuildNamespaceTest.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt b/clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt
similarity index 89%
rename from clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
rename to clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt
index 6ecc22236fe58..5ae0a5de35e21 100644
--- a/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
+++ b/clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt
@@ -31,9 +31,9 @@ add_distinct_clang_unittest(ClangScalableAnalysisTests
clangASTMatchers
clangBasic
clangFrontend
- clangScalableStaticAnalysisAnalyses
- clangScalableStaticAnalysisCore
- clangScalableStaticAnalysisFrontend
+ clangScalableStaticAnalysisFrameworkAnalyses
+ clangScalableStaticAnalysisFrameworkCore
+ clangScalableStaticAnalysisFrameworkFrontend
clangSerialization
clangTooling
diff --git a/clang/unittests/ScalableStaticAnalysis/EntityIdTableTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTableTest.cpp
similarity index 91%
rename from clang/unittests/ScalableStaticAnalysis/EntityIdTableTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/EntityIdTableTest.cpp
index ead7e35f8421f..7afa4943bcb79 100644
--- a/clang/unittests/ScalableStaticAnalysis/EntityIdTableTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTableTest.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
#include "gtest/gtest.h"
namespace clang {
diff --git a/clang/unittests/ScalableStaticAnalysis/EntityIdTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTest.cpp
similarity index 89%
rename from clang/unittests/ScalableStaticAnalysis/EntityIdTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/EntityIdTest.cpp
index e01ceda75324a..9a07aed13a432 100644
--- a/clang/unittests/ScalableStaticAnalysis/EntityIdTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTest.cpp
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/EntityLinkageTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkageTest.cpp
similarity index 95%
rename from clang/unittests/ScalableStaticAnalysis/EntityLinkageTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/EntityLinkageTest.cpp
index ccf38ec8d93fb..a435f2f2c8974 100644
--- a/clang/unittests/ScalableStaticAnalysis/EntityLinkageTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkageTest.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/EntityLinkerTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkerTest.cpp
similarity index 96%
rename from clang/unittests/ScalableStaticAnalysis/EntityLinkerTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/EntityLinkerTest.cpp
index 3f18597649199..69312fd2f2b8d 100644
--- a/clang/unittests/ScalableStaticAnalysis/EntityLinkerTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkerTest.cpp
@@ -6,17 +6,17 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
#include "TestFixture.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/EntityNameTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/EntityNameTest.cpp
similarity index 92%
rename from clang/unittests/ScalableStaticAnalysis/EntityNameTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/EntityNameTest.cpp
index 698b17efb6384..651b43744ed35 100644
--- a/clang/unittests/ScalableStaticAnalysis/EntityNameTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/EntityNameTest.cpp
@@ -6,9 +6,9 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/ErrorBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/ErrorBuilderTest.cpp
similarity index 98%
rename from clang/unittests/ScalableStaticAnalysis/ErrorBuilderTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/ErrorBuilderTest.cpp
index 5a5b74f82ae0f..65db17416b965 100644
--- a/clang/unittests/ScalableStaticAnalysis/ErrorBuilderTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/ErrorBuilderTest.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
#include "gtest/gtest.h"
#include <system_error>
diff --git a/clang/unittests/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendActionTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
similarity index 96%
rename from clang/unittests/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendActionTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
index 87aaf1e3337f9..5d2392c9236a9 100644
--- a/clang/unittests/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendActionTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
@@ -6,17 +6,17 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
+#include "clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Lex/PreprocessorOptions.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/ModelStringConversionsTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/ModelStringConversionsTest.cpp
similarity index 97%
rename from clang/unittests/ScalableStaticAnalysis/ModelStringConversionsTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/ModelStringConversionsTest.cpp
index ff24a8358612d..aff5140f26c2f 100644
--- a/clang/unittests/ScalableStaticAnalysis/ModelStringConversionsTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/ModelStringConversionsTest.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "../../lib/ScalableStaticAnalysis/Core/ModelStringConversions.h"
+#include "../../lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h"
#include "gtest/gtest.h"
using namespace clang::ssaf;
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/FancyAnalysisData.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
similarity index 96%
rename from clang/unittests/ScalableStaticAnalysis/Registries/FancyAnalysisData.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
index 9c84af5ecef8d..313c53518dfe8 100644
--- a/clang/unittests/ScalableStaticAnalysis/Registries/FancyAnalysisData.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
#include "Registries/MockSerializationFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Registry.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
similarity index 91%
rename from clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
index 17142eab62908..684249620e869 100644
--- a/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
@@ -7,15 +7,15 @@
//===----------------------------------------------------------------------===//
#include "Registries/MockSerializationFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.h b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h
similarity index 84%
rename from clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.h
rename to clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h
index 7f5b48564039e..8e5d5e92063af 100644
--- a/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.h
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h
@@ -6,11 +6,11 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
#include "clang/Support/Compiler.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/Support/Registry.h"
@@ -74,4 +74,4 @@ extern template class CLANG_TEMPLATE_ABI
Registry<clang::ssaf::MockSerializationFormat::FormatInfo>;
} // namespace llvm
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor1.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
similarity index 89%
rename from clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor1.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
index fd68ba8e07ae7..1bce78c8b1030 100644
--- a/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor1.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
@@ -8,8 +8,8 @@
#include "MockTUSummaryBuilder.h"
#include "clang/AST/ASTContext.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
using namespace clang;
using namespace ssaf;
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor2.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
similarity index 89%
rename from clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor2.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
index 58d15d407a0ae..242f427f5e346 100644
--- a/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor2.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
@@ -8,8 +8,8 @@
#include "MockTUSummaryBuilder.h"
#include "clang/AST/ASTContext.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
using namespace clang;
using namespace ssaf;
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/MockTUSummaryBuilder.h b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockTUSummaryBuilder.h
similarity index 69%
rename from clang/unittests/ScalableStaticAnalysis/Registries/MockTUSummaryBuilder.h
rename to clang/unittests/ScalableStaticAnalysisFramework/Registries/MockTUSummaryBuilder.h
index 87689634dc061..389faed325050 100644
--- a/clang/unittests/ScalableStaticAnalysis/Registries/MockTUSummaryBuilder.h
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockTUSummaryBuilder.h
@@ -6,10 +6,10 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKTUSUMMARYBUILDER_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKTUSUMMARYBUILDER_H
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKTUSUMMARYBUILDER_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKTUSUMMARYBUILDER_H
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/raw_ostream.h"
@@ -28,4 +28,4 @@ class MockTUSummaryBuilder : public TUSummaryBuilder {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKTUSUMMARYBUILDER_H
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKTUSUMMARYBUILDER_H
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/SerializationFormatRegistryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/SerializationFormatRegistryTest.cpp
similarity index 95%
rename from clang/unittests/ScalableStaticAnalysis/Registries/SerializationFormatRegistryTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Registries/SerializationFormatRegistryTest.cpp
index bb61b95e0ccf6..b55754a622e31 100644
--- a/clang/unittests/ScalableStaticAnalysis/Registries/SerializationFormatRegistryTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/SerializationFormatRegistryTest.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/StringRef.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/SummaryExtractorRegistryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/SummaryExtractorRegistryTest.cpp
similarity index 96%
rename from clang/unittests/ScalableStaticAnalysis/Registries/SummaryExtractorRegistryTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Registries/SummaryExtractorRegistryTest.cpp
index 03b1cf0f72a40..10f352c234429 100644
--- a/clang/unittests/ScalableStaticAnalysis/Registries/SummaryExtractorRegistryTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Registries/SummaryExtractorRegistryTest.cpp
@@ -8,8 +8,8 @@
#include "MockTUSummaryBuilder.h"
#include "clang/Frontend/MultiplexConsumer.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/StringRef.h"
#include "gmock/gmock.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/SSAFBuiltinTestForceLinker.h b/clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h
similarity index 88%
rename from clang/unittests/ScalableStaticAnalysis/SSAFBuiltinTestForceLinker.h
rename to clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h
index bbc75e018bfef..05d96af80cb27 100644
--- a/clang/unittests/ScalableStaticAnalysis/SSAFBuiltinTestForceLinker.h
+++ b/clang/unittests/ScalableStaticAnalysisFramework/SSAFBuiltinTestForceLinker.h
@@ -15,8 +15,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFBUILTINTESTFORCELINKER_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFBUILTINTESTFORCELINKER_H
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINTESTFORCELINKER_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINTESTFORCELINKER_H
// Force the linker to link NoOpExtractor registration.
extern volatile int SSAFNoOpExtractorAnchorSource;
@@ -48,4 +48,4 @@ extern volatile int SSAFFancyAnalysisDataAnchorSource;
[[maybe_unused]] static int SSAFFancyAnalysisDataAnchorDestination =
SSAFFancyAnalysisDataAnchorSource;
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFBUILTINTESTFORCELINKER_H
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINTESTFORCELINKER_H
diff --git a/clang/unittests/ScalableStaticAnalysis/SSAFTestForceLinker.h b/clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h
similarity index 75%
rename from clang/unittests/ScalableStaticAnalysis/SSAFTestForceLinker.h
rename to clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h
index f1f1e49daa371..dd2077569a4eb 100644
--- a/clang/unittests/ScalableStaticAnalysis/SSAFTestForceLinker.h
+++ b/clang/unittests/ScalableStaticAnalysisFramework/SSAFTestForceLinker.h
@@ -15,9 +15,9 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFTESTFORCELINKER_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFTESTFORCELINKER_H
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFTESTFORCELINKER_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFTESTFORCELINKER_H
#include "SSAFBuiltinTestForceLinker.h" // IWYU pragma: keep
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SSAFTESTFORCELINKER_H
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SSAFTESTFORCELINKER_H
diff --git a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.cpp
similarity index 99%
rename from clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.cpp
index 624cea28d0e5c..2416f5e47b622 100644
--- a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.cpp
@@ -12,7 +12,7 @@
#include "JSONFormatTest.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Registry.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.h b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.h
similarity index 95%
rename from clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.h
rename to clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.h
index b411ed3f91573..515735e788d0d 100644
--- a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.h
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.h
@@ -10,8 +10,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
#include "TestFixture.h"
#include "llvm/ADT/SmallString.h"
@@ -169,4 +169,4 @@ struct MismatchedEntitySummaryForJSONFormatTest final : EntitySummary {
} // namespace clang::ssaf
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
diff --git a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/LUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
similarity index 99%
rename from clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/LUSummaryTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
index 2651d9352ce40..3b733634ccb03 100644
--- a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/LUSummaryTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
@@ -13,9 +13,9 @@
#include "JSONFormatTest.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/TUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/TUSummaryTest.cpp
similarity index 99%
rename from clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/TUSummaryTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/TUSummaryTest.cpp
index 899320591fc47..005fbc9340f5a 100644
--- a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/TUSummaryTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/TUSummaryTest.cpp
@@ -13,9 +13,9 @@
#include "JSONFormatTest.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
#include "llvm/Testing/Support/Error.h"
#include "gmock/gmock.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/SummaryData/SummaryDataTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/SummaryData/SummaryDataTest.cpp
similarity index 94%
rename from clang/unittests/ScalableStaticAnalysis/SummaryData/SummaryDataTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/SummaryData/SummaryDataTest.cpp
index 2bf980cc116f0..caab7661593f3 100644
--- a/clang/unittests/ScalableStaticAnalysis/SummaryData/SummaryDataTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/SummaryData/SummaryDataTest.cpp
@@ -7,16 +7,16 @@
//===----------------------------------------------------------------------===//
#include "../TestFixture.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h"
-#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/SummaryNameTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/SummaryNameTest.cpp
similarity index 93%
rename from clang/unittests/ScalableStaticAnalysis/SummaryNameTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/SummaryNameTest.cpp
index c88071491a953..e1d35f6628232 100644
--- a/clang/unittests/ScalableStaticAnalysis/SummaryNameTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/SummaryNameTest.cpp
@@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/raw_ostream.h"
#include "gtest/gtest.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/TUSummaryBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
similarity index 94%
rename from clang/unittests/ScalableStaticAnalysis/TUSummaryBuilderTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
index 58c08277fb288..ece39e2164df7 100644
--- a/clang/unittests/ScalableStaticAnalysis/TUSummaryBuilderTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
@@ -6,15 +6,15 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
#include "TestFixture.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
diff --git a/clang/unittests/ScalableStaticAnalysis/TestFixture.cpp b/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
similarity index 76%
rename from clang/unittests/ScalableStaticAnalysis/TestFixture.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
index 440ad6055aa1c..772eaf069a350 100644
--- a/clang/unittests/ScalableStaticAnalysis/TestFixture.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
@@ -8,11 +8,11 @@
#include "TestFixture.h"
#include "SSAFBuiltinTestForceLinker.h" // IWYU pragma: keep
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
#include <ostream>
#include <string>
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h b/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h
new file mode 100644
index 0000000000000..2116c2b4a664c
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h
@@ -0,0 +1,47 @@
+//===- TestFixture.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_TESTFIXTURE_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_TESTFIXTURE_H
+
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
+#include "gtest/gtest.h"
+#include <iosfwd>
+
+namespace clang::ssaf {
+
+class TestFixture : public ::testing::Test {
+protected:
+ static WPASuite makeWPASuite() { return WPASuite(); }
+
+#define FIELD(CLASS, FIELD_NAME) \
+ static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
+ static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def"
+};
+
+void PrintTo(const BuildNamespace &BN, std::ostream *OS);
+void PrintTo(const EntityId &E, std::ostream *OS);
+void PrintTo(const EntityLinkage &EL, std::ostream *OS);
+void PrintTo(const EntityName &EN, std::ostream *OS);
+void PrintTo(const NestedBuildNamespace &NBN, std::ostream *OS);
+void PrintTo(const SummaryName &N, std::ostream *OS);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_TESTFIXTURE_H
diff --git a/clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/AnalysisDriverTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
similarity index 94%
rename from clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/AnalysisDriverTest.cpp
rename to clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
index 7190b049df642..e8290a7c3cd1f 100644
--- a/clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/AnalysisDriverTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
@@ -6,20 +6,20 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
#include "../TestFixture.h"
-#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
-#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
diff --git a/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
index f13b1dcd8e355..5691002325e3d 100644
--- a/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
@@ -17,9 +17,9 @@ static_library("Driver") {
"//clang/lib/DependencyScanning",
"//clang/lib/Frontend",
"//clang/lib/Options",
- "//clang/lib/ScalableStaticAnalysis/Analyses",
- "//clang/lib/ScalableStaticAnalysis/Core",
- "//clang/lib/ScalableStaticAnalysis/Frontend",
+ "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
+ "//clang/lib/ScalableStaticAnalysisFramework/Core",
+ "//clang/lib/ScalableStaticAnalysisFramework/Frontend",
"//llvm/include/llvm/Config:llvm-config",
"//llvm/lib/BinaryFormat",
"//llvm/lib/Option",
diff --git a/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn
index e2c27498f1b32..4d515b7a25ce0 100644
--- a/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn
@@ -12,9 +12,9 @@ static_library("FrontendTool") {
"//clang/lib/Frontend",
"//clang/lib/Frontend/Rewrite",
"//clang/lib/Options",
- "//clang/lib/ScalableStaticAnalysis/Analyses",
- "//clang/lib/ScalableStaticAnalysis/Core",
- "//clang/lib/ScalableStaticAnalysis/Frontend",
+ "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
+ "//clang/lib/ScalableStaticAnalysisFramework/Core",
+ "//clang/lib/ScalableStaticAnalysisFramework/Frontend",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Analyses/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Analyses/BUILD.gn
similarity index 80%
rename from llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Analyses/BUILD.gn
rename to llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Analyses/BUILD.gn
index 55075cd58deda..09b9bc4db3e1d 100644
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Analyses/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Analyses/BUILD.gn
@@ -1,11 +1,11 @@
static_library("Analyses") {
- output_name = "clangScalableStaticAnalysisAnalyses"
+ output_name = "clangScalableStaticAnalysisFrameworkAnalyses"
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/AST",
"//clang/lib/Analysis",
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysisFramework/Core",
"//llvm/lib/Support",
]
include_dirs = [ "." ]
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Core/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
similarity index 95%
rename from llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Core/BUILD.gn
rename to llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
index 3ce1a1a931f6b..70879d66e4700 100644
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Core/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
@@ -1,5 +1,5 @@
static_library("Core") {
- output_name = "clangScalableStaticAnalysisCore"
+ output_name = "clangScalableStaticAnalysisFrameworkCore"
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/AST",
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Frontend/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Frontend/BUILD.gn
similarity index 70%
rename from llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Frontend/BUILD.gn
rename to llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Frontend/BUILD.gn
index 56ca9e66e04e0..96da539ae24da 100644
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Frontend/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Frontend/BUILD.gn
@@ -1,11 +1,11 @@
static_library("Frontend") {
- output_name = "clangScalableStaticAnalysisFrontend"
+ output_name = "clangScalableStaticAnalysisFrameworkFrontend"
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/AST",
"//clang/lib/Basic",
"//clang/lib/Frontend",
- "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysisFramework/Core",
"//clang/lib/Sema",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Tool/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Tool/BUILD.gn
similarity index 60%
rename from llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Tool/BUILD.gn
rename to llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Tool/BUILD.gn
index 874d1d3da17af..b45ecef4053c0 100644
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Tool/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Tool/BUILD.gn
@@ -1,9 +1,9 @@
static_library("Tool") {
- output_name = "clangScalableStaticAnalysisTool"
+ output_name = "clangScalableStaticAnalysisFrameworkTool"
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysisFramework/Core",
"//llvm/lib/Support",
]
sources = [ "Utils.cpp" ]
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn
index 61b970d3fd55c..455082cd3b51a 100644
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn
@@ -2,9 +2,9 @@ executable("clang-ssaf-format") {
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysis/Analyses",
- "//clang/lib/ScalableStaticAnalysis/Core",
- "//clang/lib/ScalableStaticAnalysis/Tool",
+ "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
+ "//clang/lib/ScalableStaticAnalysisFramework/Core",
+ "//clang/lib/ScalableStaticAnalysisFramework/Tool",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn
index 36b99f70bdf1d..9719218841909 100644
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn
@@ -2,9 +2,9 @@ executable("clang-ssaf-linker") {
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysis/Analyses",
- "//clang/lib/ScalableStaticAnalysis/Core",
- "//clang/lib/ScalableStaticAnalysis/Tool",
+ "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
+ "//clang/lib/ScalableStaticAnalysisFramework/Core",
+ "//clang/lib/ScalableStaticAnalysisFramework/Tool",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/unittests/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/BUILD.gn
index f29052a406e2d..7d108c963c1cf 100644
--- a/llvm/utils/gn/secondary/clang/unittests/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/unittests/BUILD.gn
@@ -29,7 +29,7 @@ group("unittests") {
deps += [
"Analysis:ClangAnalysisTests",
"Analysis/FlowSensitive:ClangAnalysisFlowSensitiveTests",
- "ScalableStaticAnalysis:ClangScalableAnalysisTests",
+ "ScalableStaticAnalysisFramework:ClangScalableAnalysisTests",
"StaticAnalyzer:StaticAnalysisTests",
]
}
diff --git a/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysis/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysisFramework/BUILD.gn
similarity index 89%
rename from llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysis/BUILD.gn
rename to llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysisFramework/BUILD.gn
index 66914d2cab01f..b6eebea5e843b 100644
--- a/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysis/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysisFramework/BUILD.gn
@@ -7,9 +7,9 @@ unittest("ClangScalableAnalysisTests") {
"//clang/lib/ASTMatchers",
"//clang/lib/Basic",
"//clang/lib/Frontend",
- "//clang/lib/ScalableStaticAnalysis/Analyses",
- "//clang/lib/ScalableStaticAnalysis/Core",
- "//clang/lib/ScalableStaticAnalysis/Frontend",
+ "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
+ "//clang/lib/ScalableStaticAnalysisFramework/Core",
+ "//clang/lib/ScalableStaticAnalysisFramework/Frontend",
"//clang/lib/Serialization",
"//clang/lib/Tooling",
"//llvm/lib/Frontend/OpenMP",
diff --git a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
index b04e2326eeb35..819b6b9dcfbfd 100644
--- a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
@@ -2632,14 +2632,14 @@ cc_library(
cc_library(
name = "scalable_static_analysis_core",
srcs = glob([
- "lib/ScalableStaticAnalysis/Core/**/*.cpp",
- "lib/ScalableStaticAnalysis/Core/**/*.h",
+ "lib/ScalableStaticAnalysisFramework/Core/**/*.cpp",
+ "lib/ScalableStaticAnalysisFramework/Core/**/*.h",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysis/Core/**/*.h"] + [
- "include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h",
- "include/clang/ScalableStaticAnalysis/SSAFForceLinker.h",
+ hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Core/**/*.h"] + [
+ "include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h",
+ "include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h",
]),
- textual_hdrs = glob(["include/clang/ScalableStaticAnalysis/Core/**/*.def"]),
+ textual_hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Core/**/*.def"]),
deps = [
":ast",
":support",
@@ -2651,11 +2651,11 @@ cc_library(
cc_library(
name = "scalable_static_analysis_analyses",
srcs = glob([
- "lib/ScalableStaticAnalysis/Analyses/**/*.cpp",
- "lib/ScalableStaticAnalysis/Analyses/**/*.h",
+ "lib/ScalableStaticAnalysisFramework/Analyses/**/*.cpp",
+ "lib/ScalableStaticAnalysisFramework/Analyses/**/*.h",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysis/Analyses/**/*.h"]),
- includes = ["lib/ScalableStaticAnalysis/Analyses"],
+ hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Analyses/**/*.h"]),
+ includes = ["lib/ScalableStaticAnalysisFramework/Analyses"],
deps = [
":analysis",
":ast",
@@ -2668,9 +2668,9 @@ cc_library(
cc_library(
name = "scalable_static_analysis_tool",
srcs = glob([
- "lib/ScalableStaticAnalysis/Tool/**/*.cpp",
+ "lib/ScalableStaticAnalysisFramework/Tool/**/*.cpp",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysis/Tool/**/*.h"]),
+ hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Tool/**/*.h"]),
deps = [
":basic",
":scalable_static_analysis_core",
@@ -2681,9 +2681,9 @@ cc_library(
cc_library(
name = "scalable_static_analysis_frontend",
srcs = glob([
- "lib/ScalableStaticAnalysis/Frontend/**/*.cpp",
+ "lib/ScalableStaticAnalysisFramework/Frontend/**/*.cpp",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysis/Frontend/**/*.h"]),
+ hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Frontend/**/*.h"]),
deps = [
":ast",
":basic",
diff --git a/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
index 63b7d424350dc..1fb1089165478 100644
--- a/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
@@ -784,11 +784,11 @@ cc_test(
name = "scalable_static_analysis_tests",
size = "small",
srcs = glob([
- "ScalableStaticAnalysis/**/*.cpp",
- "ScalableStaticAnalysis/**/*.h",
+ "ScalableStaticAnalysisFramework/**/*.cpp",
+ "ScalableStaticAnalysisFramework/**/*.h",
]),
- features = ["-layering_check"], # #include "../../lib/ScalableStaticAnalysis/Core/ModelStringConversions.h"
- includes = ["ScalableStaticAnalysis"],
+ features = ["-layering_check"], # #include "../../lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h"
+ includes = ["ScalableStaticAnalysisFramework"],
deps = [
"//clang:ast",
"//clang:ast_matchers",
>From 94ee76bc44f398c453bc75f5ee4b6630f49daa76 Mon Sep 17 00:00:00 2001
From: Aviral Goel <goel.aviral at gmail.com>
Date: Tue, 23 Jun 2026 16:48:20 -0700
Subject: [PATCH 3/6] Rename
---
.github/new-prs-labeler.yml | 8 +-
.../developer-docs/ForceLinkerHeaders.rst | 158 --
.../developer-docs/HowToExtend.rst | 222 ---
.../SummaryExtractionInternals.rst | 31 -
.../developer-docs/index.rst | 10 -
.../ScalableStaticAnalysisFramework/index.rst | 19 -
.../user-docs/SummaryExtraction.rst | 37 -
clang/docs/index.rst | 2 +-
.../clang/Basic/DiagnosticFrontendKinds.td | 12 +-
clang/include/clang/Basic/DiagnosticGroups.td | 2 +-
.../Analyses/CallGraph/CallGraphSummary.h | 54 -
.../EntityPointerLevel/EntityPointerLevel.h | 121 --
.../EntityPointerLevelFormat.h | 48 -
.../Analyses/PointerFlow/PointerFlow.h | 52 -
.../PointerFlow/PointerFlowAnalysis.h | 46 -
.../Analyses/PointerFlow/PointerFlowFormat.h | 37 -
.../UnsafeBufferUsage/UnsafeBufferUsage.h | 50 -
.../UnsafeBufferUsageAnalysis.h | 62 -
.../BuiltinAnchorSources.def | 31 -
.../Core/ASTEntityMapping.h | 47 -
.../Core/EntityLinker/EntityLinker.h | 95 --
.../Core/EntityLinker/EntitySummaryEncoding.h | 42 -
.../Core/EntityLinker/LUSummary.h | 62 -
.../Core/EntityLinker/LUSummaryEncoding.h | 64 -
.../Core/EntityLinker/TUSummaryEncoding.h | 67 -
.../Core/Model/BuildNamespace.h | 129 --
.../Core/Model/EntityId.h | 54 -
.../Core/Model/EntityIdTable.h | 53 -
.../Core/Model/EntityLinkage.h | 53 -
.../Core/Model/EntityName.h | 62 -
.../Core/Model/PrivateFieldNames.def | 52 -
.../Core/Model/SummaryName.h | 41 -
.../Core/Serialization/JSONFormat.h | 268 ---
.../Core/Serialization/SerializationFormat.h | 266 ---
.../SerializationFormatRegistry.h | 89 -
.../Core/SummaryData/LUSummaryConsumer.h | 93 --
.../Core/SummaryData/SummaryData.h | 28 -
.../Core/SummaryData/SummaryDataBuilder.h | 97 --
.../SummaryData/SummaryDataBuilderRegistry.h | 74 -
.../Core/SummaryData/SummaryDataStore.h | 115 --
.../Core/SummaryData/SummaryDataTraits.h | 41 -
.../Core/Support/ErrorBuilder.h | 210 ---
.../Core/Support/FormatProviders.h | 93 --
.../Core/TUSummary/EntitySummary.h | 30 -
.../Core/TUSummary/ExtractorRegistry.h | 56 -
.../Core/TUSummary/TUSummary.h | 51 -
.../Core/TUSummary/TUSummaryBuilder.h | 81 -
.../Core/TUSummary/TUSummaryExtractor.h | 45 -
.../Core/WholeProgramAnalysis/AnalysisBase.h | 60 -
.../WholeProgramAnalysis/AnalysisDriver.h | 95 --
.../Core/WholeProgramAnalysis/AnalysisName.h | 49 -
.../WholeProgramAnalysis/AnalysisRegistry.h | 111 --
.../WholeProgramAnalysis/AnalysisResult.h | 30 -
.../WholeProgramAnalysis/AnalysisTraits.h | 36 -
.../WholeProgramAnalysis/DerivedAnalysis.h | 133 --
.../WholeProgramAnalysis/SummaryAnalysis.h | 121 --
.../Core/WholeProgramAnalysis/WPASuite.h | 99 --
.../TUSummaryExtractorFrontendAction.h | 33 -
.../SSAFBuiltinForceLinker.h | 43 -
.../SSAFForceLinker.h | 25 -
.../SourceTransformation/SourceEditEmitter.h | 29 -
.../SourceTransformation/Transformation.h | 38 -
.../TransformationRegistry.h | 66 -
.../TransformationReportEmitter.h | 33 -
.../Tool/Utils.h | 95 --
clang/include/module.modulemap | 8 +-
clang/lib/CMakeLists.txt | 2 +-
clang/lib/Driver/CMakeLists.txt | 8 +-
clang/lib/Driver/Driver.cpp | 6 +-
clang/lib/FrontendTool/CMakeLists.txt | 8 +-
.../ExecuteCompilerInvocation.cpp | 4 +-
.../Analyses/CMakeLists.txt | 28 -
.../Analyses/CallGraph/CallGraphExtractor.cpp | 108 --
.../CallGraph/CallGraphJSONFormat.cpp | 174 --
.../EntityPointerLevel/EntityPointerLevel.cpp | 366 -----
.../EntityPointerLevelFormat.cpp | 134 --
.../Analyses/PointerFlow/PointerFlow.cpp | 22 -
.../PointerFlow/PointerFlowAnalysis.cpp | 122 --
.../PointerFlow/PointerFlowExtractor.cpp | 372 -----
.../PointerFlow/PointerFlowFormat.cpp | 132 --
.../Analyses/SSAFAnalysesCommon.cpp | 145 --
.../Analyses/SSAFAnalysesCommon.h | 82 -
.../UnsafeBufferUsage/UnsafeBufferUsage.cpp | 22 -
.../UnsafeBufferUsageAnalysis.cpp | 250 ---
.../UnsafeBufferUsageExtractor.cpp | 110 --
.../UnsafeBufferUsageFormat.cpp | 86 -
.../CMakeLists.txt | 6 -
.../Core/ASTEntityMapping.cpp | 83 -
.../Core/CMakeLists.txt | 39 -
.../Core/EntityLinker/EntityLinker.cpp | 197 ---
.../Core/Model/BuildNamespace.cpp | 73 -
.../Core/Model/EntityId.cpp | 17 -
.../Core/Model/EntityIdTable.cpp | 31 -
.../Core/Model/EntityLinkage.cpp | 33 -
.../Core/Model/EntityName.cpp | 41 -
.../Core/Model/SummaryName.cpp | 17 -
.../Core/ModelStringConversions.h | 87 -
.../Serialization/JSONFormat/Artifact.cpp | 173 --
.../JSONFormat/JSONEntitySummaryEncoding.cpp | 86 -
.../JSONFormat/JSONEntitySummaryEncoding.h | 52 -
.../JSONFormat/JSONFormatImpl.cpp | 1380 ----------------
.../Serialization/JSONFormat/JSONFormatImpl.h | 219 ---
.../Serialization/JSONFormat/LUSummary.cpp | 196 ---
.../JSONFormat/LUSummaryEncoding.cpp | 193 ---
.../Serialization/JSONFormat/TUSummary.cpp | 196 ---
.../JSONFormat/TUSummaryEncoding.cpp | 193 ---
.../Serialization/JSONFormat/WPASuite.cpp | 226 ---
.../SerializationFormatRegistry.cpp | 37 -
.../Core/SummaryData/LUSummaryConsumer.cpp | 78 -
.../SummaryDataBuilderRegistry.cpp | 36 -
.../Core/Support/ErrorBuilder.cpp | 63 -
.../Core/TUSummary/ExtractorRegistry.cpp | 39 -
.../Core/TUSummary/TUSummaryBuilder.cpp | 36 -
.../Core/TUSummary/TUSummaryExtractor.cpp | 80 -
.../WholeProgramAnalysis/AnalysisDriver.cpp | 212 ---
.../WholeProgramAnalysis/AnalysisName.cpp | 16 -
.../WholeProgramAnalysis/AnalysisRegistry.cpp | 46 -
.../Frontend/CMakeLists.txt | 16 -
.../TUSummaryExtractorFrontendAction.cpp | 199 ---
.../Plugins/CMakeLists.txt | 15 -
.../Plugins/ExamplePlugin/AnalysisResults.h | 39 -
.../Plugins/ExamplePlugin/CMakeLists.txt | 18 -
.../Plugins/ExamplePlugin/PairsAnalysis.cpp | 197 ---
.../Plugins/ExamplePlugin/TagsAnalysis.cpp | 160 --
.../ExamplePlugin/TagsPairsAnalysis.cpp | 136 --
.../SourceTransformation/CMakeLists.txt | 13 -
.../TransformationRegistry.cpp | 44 -
.../Tool/CMakeLists.txt | 12 -
.../Tool/Utils.cpp | 207 ---
.../tools/clang-ssaf-analyzer/CMakeLists.txt | 8 +-
.../clang-ssaf-analyzer/SSAFAnalyzer.cpp | 10 +-
clang/tools/clang-ssaf-format/CMakeLists.txt | 8 +-
clang/tools/clang-ssaf-format/SSAFFormat.cpp | 12 +-
clang/tools/clang-ssaf-linker/CMakeLists.txt | 8 +-
clang/tools/clang-ssaf-linker/SSAFLinker.cpp | 12 +-
clang/unittests/CMakeLists.txt | 4 +-
.../TUSummaryExtractorFrontendActionTest.cpp | 27 +-
.../ASTEntityMappingTest.cpp | 341 ----
.../CallGraph/CallGraphExtractorTest.cpp | 517 ------
.../Analyses/PointerFlow/PointerFlowTest.cpp | 1443 -----------------
.../PointerFlow/PointerFlowWPATest.cpp | 141 --
.../UnsafeBufferUsageTest.cpp | 783 ---------
.../UnsafeBufferUsageWPATest.cpp | 132 --
.../BuildNamespaceTest.cpp | 158 --
.../CMakeLists.txt | 56 -
.../EntityIdTableTest.cpp | 142 --
.../EntityIdTest.cpp | 100 --
.../EntityLinkageTest.cpp | 117 --
.../EntityLinkerTest.cpp | 667 --------
.../EntityNameTest.cpp | 95 --
.../ErrorBuilderTest.cpp | 196 ---
.../FindDecl.h | 53 -
.../LUSummaryTest.cpp | 25 -
.../ModelStringConversionsTest.cpp | 106 --
.../Registries/FancyAnalysisData.cpp | 60 -
.../Registries/MockSerializationFormat.cpp | 232 ---
.../Registries/MockSerializationFormat.h | 85 -
.../Registries/MockSummaryExtractor1.cpp | 44 -
.../Registries/MockSummaryExtractor2.cpp | 44 -
.../Registries/MockTUSummaryBuilder.h | 31 -
.../SerializationFormatRegistryTest.cpp | 115 --
.../SummaryExtractorRegistryTest.cpp | 113 --
.../JSONFormatTest/JSONFormatTest.cpp | 639 --------
.../JSONFormatTest/JSONFormatTest.h | 172 --
.../JSONFormatTest/LUSummaryTest.cpp | 452 ------
.../JSONFormatTest/TUSummaryTest.cpp | 445 -----
.../SourceTransformation/EmitterTest.cpp | 81 -
.../SourceTransformation/RegistryTest.cpp | 78 -
.../SummaryData/SummaryDataTest.cpp | 398 -----
.../SummaryNameTest.cpp | 67 -
.../TUSummaryBuilderTest.cpp | 404 -----
.../TestFixture.cpp | 42 -
.../TestFixture.h | 47 -
.../AnalysisDriverTest.cpp | 563 -------
.../UnsafeBufferReachableAnalysisTest.cpp | 582 -------
.../gn/secondary/clang/lib/Driver/BUILD.gn | 8 +-
.../secondary/clang/lib/FrontendTool/BUILD.gn | 8 +-
.../Analyses/BUILD.gn | 27 -
.../Core/BUILD.gn | 37 -
.../Frontend/BUILD.gn | 13 -
.../SourceTransformation/BUILD.gn | 12 -
.../Tool/BUILD.gn | 10 -
.../clang/tools/clang-ssaf-analyzer/BUILD.gn | 8 +-
.../clang/tools/clang-ssaf-format/BUILD.gn | 8 +-
.../clang/tools/clang-ssaf-linker/BUILD.gn | 8 +-
.../gn/secondary/clang/unittests/BUILD.gn | 2 +-
.../ScalableStaticAnalysisFramework/BUILD.gn | 57 -
.../llvm-project-overlay/clang/BUILD.bazel | 34 +-
.../clang/unittests/BUILD.bazel | 8 +-
189 files changed, 115 insertions(+), 21962 deletions(-)
delete mode 100644 clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
delete mode 100644 clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
delete mode 100644 clang/docs/ScalableStaticAnalysisFramework/developer-docs/SummaryExtractionInternals.rst
delete mode 100644 clang/docs/ScalableStaticAnalysisFramework/developer-docs/index.rst
delete mode 100644 clang/docs/ScalableStaticAnalysisFramework/index.rst
delete mode 100644 clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/SourceEditEmitter.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/Transformation.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationRegistry.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationReportEmitter.h
delete mode 100644 clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityId.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityName.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Model/SummaryName.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/Artifact.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummary.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummary.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/AnalysisResults.h
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/PairsAnalysis.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsAnalysis.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/CMakeLists.txt
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/TransformationRegistry.cpp
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
delete mode 100644 clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
rename clang/unittests/{ScalableStaticAnalysisFramework => ScalableStaticAnalysis}/Frontend/TUSummaryExtractorFrontendActionTest.cpp (95%)
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowWPATest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/BuildNamespaceTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/EntityIdTableTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/EntityIdTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/EntityLinkageTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/EntityLinkerTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/EntityNameTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/ErrorBuilderTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/FindDecl.h
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/LUSummaryTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/ModelStringConversionsTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Registries/MockTUSummaryBuilder.h
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Registries/SerializationFormatRegistryTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Registries/SummaryExtractorRegistryTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.h
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/TUSummaryTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/SourceTransformation/EmitterTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/SourceTransformation/RegistryTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/SummaryData/SummaryDataTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/SummaryNameTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
delete mode 100644 clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp
delete mode 100644 llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Analyses/BUILD.gn
delete mode 100644 llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
delete mode 100644 llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Frontend/BUILD.gn
delete mode 100644 llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/BUILD.gn
delete mode 100644 llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Tool/BUILD.gn
delete mode 100644 llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysisFramework/BUILD.gn
diff --git a/.github/new-prs-labeler.yml b/.github/new-prs-labeler.yml
index b51d2c197c762..3ef5afe8b1da5 100644
--- a/.github/new-prs-labeler.yml
+++ b/.github/new-prs-labeler.yml
@@ -698,11 +698,11 @@ clang:analysis:
clang:ssaf:
- changed-files:
- any-glob-to-any-file:
- - clang/docs/ScalableStaticAnalysisFramework/**
- - clang/include/clang/ScalableStaticAnalysisFramework/**
- - clang/lib/ScalableStaticAnalysisFramework/**
+ - clang/docs/ScalableStaticAnalysis/**
+ - clang/include/clang/ScalableStaticAnalysis/**
+ - clang/lib/ScalableStaticAnalysis/**
- clang/test/Analysis/Scalable/**
- - clang/unittests/ScalableStaticAnalysisFramework/**
+ - clang/unittests/ScalableStaticAnalysis/**
clang:static analyzer:
- changed-files:
diff --git a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
deleted file mode 100644
index fb113824217ea..0000000000000
--- a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/ForceLinkerHeaders.rst
+++ /dev/null
@@ -1,158 +0,0 @@
-====================
-Force-Linker Headers
-====================
-
-.. WARNING:: The framework is rapidly evolving.
- The documentation might be out-of-sync with the implementation.
- The purpose of this documentation is to give context for upcoming reviews.
-
-The problem
-***********
-
-SSAF uses `llvm::Registry\<\> <https://llvm.org/doxygen/classllvm_1_1Registry.html>`_
-for decentralized registration of summary extractors and serialization formats.
-Each registration is a file-scope static object whose constructor adds an entry
-to the global registry:
-
-.. code-block:: c++
-
- // In MyExtractor.cpp
- static TUSummaryExtractorRegistry::Add<MyExtractor>
- RegisterExtractor("MyExtractor", "My summary extractor");
-
-When the translation unit containing this static object is compiled into a
-**static library** (``.a`` / ``.lib``), the static linker will only pull in
-object files that resolve an undefined symbol in the consuming binary.
-Because no code ever calls anything in ``MyExtractor.o`` directly, the linker
-discards the object file — and the registration never runs.
-
-This is not a problem for **shared libraries** (``.so`` / ``.dylib``), because
-the dynamic linker loads the entire shared object and runs all global
-constructors unconditionally.
-
-The solution: anchor symbols
-****************************
-
-Each registration translation unit defines a ``volatile int`` **anchor symbol**:
-
-.. code-block:: c++
-
- // In MyExtractor.cpp - next to the registry Add<> object in the ``clang::ssaf`` namespace
- // NOLINTNEXTLINE(misc-use-internal-linkage)
- volatile int MyExtractorAnchorSource = 0;
-
-For **in-tree** anchors, add a single ``ANCHOR(...)`` entry to
-``BuiltinAnchorSources.def`` (in alphabetical order):
-
-.. code-block:: c++
-
- // In clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def
- ANCHOR(JSONFormatAnchorSource)
- ANCHOR(MyExtractorAnchorSource) // <-- Add here, in alphabetical order
-
-``SSAFBuiltinForceLinker.h`` includes this ``.def`` file automatically to
-generate the ``extern`` declarations and the ``AnchorSources`` array — there is
-no need to edit that header directly.
-
-Any translation unit that ``#include``\s this header now has a reference to
-``MyExtractorAnchorSource``, which forces the linker to pull in
-``MyExtractor.o`` — and with it, the static ``Add<>`` registration object.
-
-The ``volatile`` qualifier is essential: without it the compiler could
-constant-fold the ``0`` and eliminate the reference entirely.
-
-These anchor symbols must be mutable (not ``const``), because otherwise on MSVC
-``const volatile`` variables would still have **internal linkage** — despite
-that the standard specifies that these should have **external linkage**.
-
-Header hierarchy
-================
-
-.. code-block:: text
-
- SSAFForceLinker.h (umbrella — include this in binaries)
- └── SSAFBuiltinForceLinker.h (upstream built-in anchors only)
-
-- ``clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h`` — anchors for
- upstream-provided (built-in) extractors and formats (e.g. ``JSONFormat``).
-- ``clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h`` — umbrella header
- that includes ``SSAFBuiltinForceLinker.h``. This is the header that
- downstream projects should modify to add their own force-linker includes
- (see :doc:`HowToExtend`).
-
-Include the umbrella header with ``// IWYU pragma: keep`` in any translation
-unit that must guarantee all registrations are active — typically the entry
-point of a binary that uses ``clangScalableStaticAnalysisFrameworkCore``:
-
-.. code-block:: c++
-
- // In ExecuteCompilerInvocation.cpp
- #include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
-
-Naming convention
-=================
-
-Anchor symbols follow the pattern ``<Component>AnchorSource`` in the ``clang::ssaf`` namespace.
-For example:
-
-- ``JSONFormatAnchorSource``
-- ``MyExtractorAnchorSource``
-
-All anchor sources are aggregated into a single ``BuiltinAnchorDestination``
-lambda in the force-linker header (see ``SSAFBuiltinForceLinker.h``).
-
-Considered alternatives
-***********************
-
-``--whole-archive`` / ``-force_load``
-=====================================
-
-The linker can be instructed to include *every* object file from a static
-library, regardless of whether any symbols are referenced:
-
-.. code-block:: bash
-
- # GNU ld / lld (Linux, BSD)
- -Wl,--whole-archive -lclangScalableStaticAnalysisFrameworkCore -Wl,--no-whole-archive
-
- # Apple ld
- -Wl,-force_load,libclangScalableStaticAnalysisFrameworkCore.a
-
-Since CMake 3.24, the ``$<LINK_LIBRARY:WHOLE_ARCHIVE,...>`` generator expression
-provides a portable way to do the same:
-
-.. code-block:: cmake
-
- target_link_libraries(clang PRIVATE
- "$<LINK_LIBRARY:WHOLE_ARCHIVE,clangScalableStaticAnalysisFrameworkCore>")
-
-**Why we did not choose this approach**:
-
-- It is a blunt instrument — *all* object files in the library are pulled in,
- increasing binary size.
-- The anchor approach only targets specific object files: only registrations
- whose anchors are referenced in a force-linker header are pulled in.
-- ``--whole-archive`` semantics vary across platforms and toolchains, requiring
- platform-specific CMake logic or the relatively new ``WHOLE_ARCHIVE``
- generator expression.
-
-Explicit initialization functions
-=================================
-
-An alternative is a central ``initializeSSAFRegistrations()`` function that
-explicitly calls into each registration module:
-
-.. code-block:: c++
-
- void initializeSSAFRegistrations() {
- initializeJSONFormat();
- initializeMyExtractor();
- // ... one entry per registration
- }
-
-**Why we did not choose this approach**:
-
-- It reintroduces a centralized list that must be maintained manually, defeating
- the decoupled-registration benefit of ``llvm::Registry``.
-- Adding a new extractor or format requires modifying a central file, which
- increases merge-conflict risk for downstream users.
diff --git a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
deleted file mode 100644
index 4b5194f2b0a0b..0000000000000
--- a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/HowToExtend.rst
+++ /dev/null
@@ -1,222 +0,0 @@
-===========================
-How to Extend the Framework
-===========================
-
-.. WARNING:: The framework is rapidly evolving.
- The documentation might be out-of-sync with the implementation.
- The purpose of this documentation is to give context for upcoming reviews.
-
-SSAF is designed to be extensible with new **summary extractors** and **serialization formats**.
-Extensions can be added in three ways:
-
-#. **Statically, in-tree** — built as part of the upstream LLVM/Clang tree.
-#. **Statically, out-of-tree (downstream)** — built in a downstream fork or project that links ``clangScalableStaticAnalysisFrameworkCore`` as a static library.
-#. **Dynamically, via plugins** — loaded at runtime as shared objects.
-
-All three approaches use the same ``llvm::Registry``-based registration mechanism.
-The key difference is how the linker sees the registration:
-static libraries need :doc:`force-linker anchors <ForceLinkerHeaders>` to prevent dead-stripping, while shared libraries do not.
-
-Adding a summary extractor
-**************************
-
-A summary extractor is an ``ASTConsumer`` that inspects the AST and populates a ``TUSummary`` via the ``TUSummaryBuilder`` interface.
-
-Step 1: Implement the extractor
-===============================
-
-.. code-block:: c++
-
- //--- MyExtractor.h
- #include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
-
- namespace clang::ssaf {
-
- class MyExtractor : public TUSummaryExtractor {
- public:
- using TUSummaryExtractor::TUSummaryExtractor;
-
- // Override HandleTranslationUnit or any other virtual functions of an ASTConsumer...
- // Use the SummaryBuilder to populate the summary while walking the AST.
- };
-
- } // namespace clang::ssaf
-
-Step 2: Register the extractor
-==============================
-
-.. code-block:: c++
-
- //--- MyExtractor.cpp
- #include "MyExtractor.h"
- #include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-
- using namespace clang::ssaf;
-
- namespace clang::ssaf {
- // NOLINTNEXTLINE(misc-use-internal-linkage)
- volatile int MyExtractorAnchorSource = 0;
- } // namespace clang::ssaf
-
- static TUSummaryExtractorRegistry::Add<MyExtractor>
- RegisterExtractor("MyExtractor", "My awesome summary extractor");
-
-The ``"MyExtractor"`` string is the name users pass to ``--ssaf-extract-summaries=MyExtractor``.
-
-Step 3: Add the force-linker anchor
-===================================
-
-See :doc:`ForceLinkerHeaders` for a full explanation of why this is needed.
-
-For **in-tree** additions, add one line to
-``clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def``
-(in alphabetical order):
-
-.. code-block:: c++
-
- ANCHOR(MyExtractorAnchorSource)
-
-``SSAFBuiltinForceLinker.h`` includes this ``.def`` file automatically — no
-need to edit it directly.
-
-For **downstream** additions, see `Out-of-tree (downstream) extensions`_ below.
-
-
-Adding a serialization format
-*****************************
-
-A serialization format controls how the ``TUSummary`` is written to (and read from) disk.
-This involves more boilerplate than an extractor because each format has a per-analysis ``FormatInfo`` sub-registry.
-
-Step 1: Define the format class
-===============================
-
-Your format class must inherit from ``SerializationFormat`` and define a ``FormatInfo`` type alias:
-
-.. code-block:: c++
-
- //--- MyFormat.h
- #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
- #include "clang/Support/Compiler.h"
- #include "llvm/Support/Registry.h"
-
- namespace clang::ssaf {
-
- class MyFormat : public SerializationFormat {
- public:
- // Define the type aliases: SerializerFn, DeserializerFn
- using FormatInfo = FormatInfoEntry<SerializerFn, DeserializerFn>;
-
- // Override readTUSummaryEncoding, writeTUSummary, etc.
- };
-
- } // namespace clang::ssaf
-
- LLVM_DECLARE_REGISTRY(llvm::Registry<MyFormat::FormatInfo>)
-
-Step 2: Register the format
-===========================
-
-.. code-block:: c++
-
- //--- MyFormat.cpp
- #include "MyFormat.h"
- #include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-
- using namespace clang::ssaf;
-
- namespace clang::ssaf {
- // NOLINTNEXTLINE(misc-use-internal-linkage)
- volatile int MyFormatAnchorSource = 0;
- } // namespace clang::ssaf
-
- static SerializationFormatRegistry::Add<MyFormat>
- RegisterFormat("myformat", "My awesome serialization format");
-
- LLVM_DEFINE_REGISTRY(llvm::Registry<MyFormat::FormatInfo>)
-
-The format name (``"myformat"``) is matched against the file extension in ``--ssaf-tu-summary-file=output.myformat``.
-
-Step 3: Register per-analysis FormatInfo entries
-================================================
-
-For each analysis that should be serializable in your format, register a ``FormatInfo`` entry.
-``FormatInfo`` must be implemented for any of the summaries that wants to support ``myformat``:
-
-.. code-block:: c++
-
- namespace {
- using FormatInfo = MyFormat::FormatInfo;
- struct MyAnalysisFormatInfo final : FormatInfo {
- MyAnalysisFormatInfo() : FormatInfo{
- SummaryName("MyAnalysis"),
- serializeMyAnalysis,
- deserializeMyAnalysis,
- } {}
- };
- } // namespace
-
- static llvm::Registry<FormatInfo>::Add<MyAnalysisFormatInfo>
- RegisterFormatInfo("MyAnalysisFormatInfo",
- "MyFormat format info for MyAnalysis");
-
-Step 4: Add the force-linker anchor
-===================================
-
-Same pattern as for extractors — add the anchor to ``BuiltinAnchorSources.def``
-(in alphabetical order). See `Adding a summary extractor`_ Step 3,
-and :doc:`ForceLinkerHeaders`.
-
-
-Static extensibility
-********************
-
-In-tree extensions
-==================
-
-For extensions that are part of the upstream LLVM/Clang tree:
-
-#. Add the anchor to ``clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def`` (in alphabetical order).
-#. Add the source files to the ``clangScalableStaticAnalysisFrameworkCore`` CMake library target.
-#. That's it — the ``SSAFForceLinker.h`` umbrella includes ``SSAFBuiltinForceLinker.h``
- transitively, so any binary that includes the umbrella will pull in the registration.
-
-Out-of-tree (downstream) extensions
-===================================
-
-Downstream projects that maintain a fork can add their own extensions without
-modifying upstream files — reducing the risk of merge-conflicts:
-
-#. Create a downstream force-linker header, e.g. ``SSAFDownstreamForceLinker.h``,
- containing the anchor references for downstream-only extractors and formats.
-#. Include it from ``SSAFForceLinker.h`` (the umbrella):
-
- .. code-block:: c++
-
- // In SSAFForceLinker.h
- #include "SSAFBuiltinForceLinker.h" // IWYU pragma: keep
- #include "SSAFDownstreamForceLinker.h" // IWYU pragma: keep
-
- This is a single-line addition per downstream project, minimizing conflicts with upstream changes.
- Upstream will try to avoid modifying this umbrella header, making it a stable static extension point.
-
-#. Add the downstream source files to the build system as usual.
-
-
-Dynamic extensibility (plugins)
-*******************************
-
-Shared libraries loaded at runtime — via ``dlopen`` / ``LoadLibrary`` or the
-Clang plugin mechanism — do **not** need force-linker anchors, but having them also does not hurt.
-
-When a shared object (``.so`` / ``.dylib``) is loaded, the dynamic linker runs all global constructors in that library unconditionally.
-This means the ``llvm::Registry::Add<>`` objects execute their constructors and register themselves automatically.
-
-To use a plugin:
-
-#. Build your extractor or format as a shared library.
-#. Load it with the Clang plugin mechanism (``-fplugin=`` or ``-load``).
-#. Pass the extractor name to ``--ssaf-extract-summaries=`` as usual.
-
-No changes to any force-linker header are required.
-The ``llvm::Registry`` infrastructure handles everything once the shared object is loaded.
diff --git a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/SummaryExtractionInternals.rst b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/SummaryExtractionInternals.rst
deleted file mode 100644
index 8190f2c8c7fae..0000000000000
--- a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/SummaryExtractionInternals.rst
+++ /dev/null
@@ -1,31 +0,0 @@
-============================
-Summary Extraction Internals
-============================
-
-.. WARNING:: The framework is rapidly evolving.
- The documentation might be out-of-sync with the implementation.
- The purpose of this documentation is to give context for upcoming reviews.
-
-When ``--ssaf-tu-summary-file=`` is non-empty, ``CreateFrontendAction()`` (in ``ExecuteCompilerInvocation.cpp``)
-wraps the original ``FrontendAction`` inside a ``TUSummaryExtractorFrontendAction``.
-This ensures that the summary extraction transparently happens after the original frontend action, which is usually either compilation (``-c``) or just ``-fsyntax-only`` in tests.
-
-Lifetime of a summary extraction
-********************************
-
-The ``TUSummaryExtractorFrontendAction`` will try to construct a ``TUSummaryRunner`` ASTConsumer and report an error on failure.
-When it succeeds, it will multiplex the handlers of the ASTConsumer to every summary extractor and in the end, serialize and write the results to the desired file.
-
-Implementation details
-**********************
-
-Global Registries
-=================
-
-The framework uses `llvm::Registry\<\> <https://llvm.org/doxygen/classllvm_1_1Registry.html>`_
-as an extension point for adding new summary analyses or serialization formats.
-Each entry in the *registry* holds a name, a description and a pointer to a constructor.
-Because static linking can discard unreferenced registration objects, the framework
-uses :doc:`ForceLinkerHeaders` to ensure they are retained.
-
-For details on how to add new extractors and formats, see :doc:`HowToExtend`.
diff --git a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/index.rst b/clang/docs/ScalableStaticAnalysisFramework/developer-docs/index.rst
deleted file mode 100644
index 139cb281a2ab4..0000000000000
--- a/clang/docs/ScalableStaticAnalysisFramework/developer-docs/index.rst
+++ /dev/null
@@ -1,10 +0,0 @@
-=======================
-Developer Documentation
-=======================
-
-.. toctree::
- :numbered:
- :maxdepth: 2
- :glob:
-
- *
diff --git a/clang/docs/ScalableStaticAnalysisFramework/index.rst b/clang/docs/ScalableStaticAnalysisFramework/index.rst
deleted file mode 100644
index 1a2699fd7423f..0000000000000
--- a/clang/docs/ScalableStaticAnalysisFramework/index.rst
+++ /dev/null
@@ -1,19 +0,0 @@
-==================================
-Scalable Static Analysis Framework
-==================================
-
-This is a framework for writing cross-translation unit analyses in a scalable and extensible setting.
-
-.. toctree::
- :numbered:
- :maxdepth: 2
- :glob:
-
- user-docs/*
-
-:doc:`Developer documentation <developer-docs/index>`
-
-.. toctree::
- :hidden:
-
- developer-docs/index
diff --git a/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst b/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
deleted file mode 100644
index 96892cfa5fdea..0000000000000
--- a/clang/docs/ScalableStaticAnalysisFramework/user-docs/SummaryExtraction.rst
+++ /dev/null
@@ -1,37 +0,0 @@
-==================
-Summary Extraction
-==================
-
-.. WARNING:: The framework is rapidly evolving.
- The documentation might be out-of-sync with the implementation.
- The purpose of this documentation is to give context for upcoming reviews.
-
-Command-line interface
-**********************
-
-Two flags control summary extraction:
-
-- ``--ssaf-extract-summaries=<name1>,<name2>,...``: Comma-separated list of summary extractor names to enable.
-- ``--ssaf-tu-summary-file=<path>.<format>``: Output file for the extracted summaries. The file extension selects the serialization format (e.g. ``.json``).
-- ``--ssaf-list-extractors``: List the available summary extractors.
-- ``--ssaf-list-formats``: List the available serialization formats.
-
-Example invocation:
-
-.. code-block:: bash
-
- clang --ssaf-extract-summaries=MyAwesomeAnalysis \
- --ssaf-tu-summary-file=my-tu-summary.json \
- -c input.cpp -o input.o
-
- clang --ssaf-list-extractors --ssaf-list-formats
-
-Diagnostics
-***********
-
-In case the ``--ssaf-*`` flags are used incorrectly, or some extractor fails to implement the desired serialization format
-or just happens to have an error, then the error is forwarded as a ``scalable-static-analysis-framework`` error.
-These errors can be downgraded into warnings using ``-Wno-error=scalable-static-analysis-framework``.
-These errors can be completely suppressed using ``-Wno-scalable-static-analysis-framework``.
-
-See the `diagnostic flags <https://clang.llvm.org/docs/DiagnosticsReference.html#wscalable-static-analysis-framework>`_ for the full list of diagnostics controlled by ``-Wscalable-static-analysis-framework``.
diff --git a/clang/docs/index.rst b/clang/docs/index.rst
index 05bb7512fda92..b57e8178f3237 100644
--- a/clang/docs/index.rst
+++ b/clang/docs/index.rst
@@ -29,7 +29,7 @@ Using Clang as a Compiler
ThreadSafetyAnalysis
LifetimeSafety
SafeBuffers
- ScalableStaticAnalysisFramework/index
+ ScalableStaticAnalysis/index
DataFlowAnalysisIntro
FunctionEffectAnalysis
AddressSanitizer
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index 058449ef47a46..d9e4858f5f648 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -409,30 +409,30 @@ def warn_profile_data_misexpect : Warning<
def warn_ssaf_extract_tu_summary_file_unknown_output_format :
Warning<"unknown output summary file format '%0' "
"specified by '--ssaf-tu-summary-file=%1'">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def warn_ssaf_extract_tu_summary_file_unknown_format :
Warning<"failed to parse the value of '--ssaf-tu-summary-file=%0' "
"the value must follow the '<path>.<format>' pattern">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def warn_ssaf_must_enable_summary_extractors :
Warning<"must enable some summary extractors using the "
"'--ssaf-extract-summaries=' option">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def warn_ssaf_extract_summary_unknown_extractor_name :
Warning<"no summary extractor%s0 %plural{1:was|:were}0 registered with name: %1">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def warn_ssaf_write_tu_summary_failed :
Warning<"failed to write TU summary to '%0': %1">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def warn_ssaf_tu_summary_requires_compilation_unit_id :
Warning<"option '--ssaf-tu-summary-file=' requires "
"'--ssaf-compilation-unit-id=' to be set">,
- InGroup<ScalableStaticAnalysisFramework>, DefaultError;
+ InGroup<ScalableStaticAnalysis>, DefaultError;
def err_extract_api_ignores_file_not_found :
Error<"file '%0' specified by '--extract-api-ignores=' not found">, DefaultFatal;
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 5cdebd35ba05d..6418ab4757a0c 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -1972,7 +1972,7 @@ def BitIntExtension : DiagGroup<"bit-int-extension">;
def ExtractAPIMisuse : DiagGroup<"extractapi-misuse">;
// Warnings related to the "Scalable Static Analysis Framework" - SSAF.
-def ScalableStaticAnalysisFramework : DiagGroup<"scalable-static-analysis-framework">;
+def ScalableStaticAnalysis : DiagGroup<"scalable-static-analysis-framework">;
// Warnings about using the non-standard extension having an explicit specialization
// with a storage class specifier.
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h
deleted file mode 100644
index 8056b1001a216..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- CallGraphSummary.h ---------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include <set>
-
-namespace clang::ssaf {
-
-/// Summary of direct call-graph edges for a single function entity.
-///
-/// Represents a function definition, and information about its callees.
-///
-/// \bug Indirect calls (e.g. function pointers) are not represented.
-/// \bug ObjCMessageExprs are not represented.
-/// \bug Primary template functions are not represented.
-struct CallGraphSummary final : public EntitySummary {
- struct Location {
- std::string File;
- unsigned Line;
- unsigned Column;
- };
-
- static constexpr llvm::StringLiteral Name = "CallGraph";
- SummaryName getSummaryName() const override {
- return SummaryName(Name.str());
- }
-
- /// Represents the location of the function.
- Location Definition = {};
-
- /// The set of direct callees of this function.
- std::set<EntityId> DirectCallees;
-
- /// The set of virtual callees of this function.
- std::set<EntityId> VirtualCallees;
-
- /// A human-readable name of the function.
- /// This is not guaranteed to be accurate or unique.
- std::string PrettyName;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
deleted file mode 100644
index 35eae269105f7..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h
+++ /dev/null
@@ -1,121 +0,0 @@
-//===- EntityPointerLevel.h -------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
-
-#include "clang/AST/Expr.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include <set>
-
-namespace clang::ssaf {
-class TUSummaryExtractor;
-
-/// An EntityPointerLevel is associated with a level of the declared
-/// pointer/array type of an entity. In the fully-expanded spelling of the
-/// declared type, a EntityPointerLevel is associated with a '*' (or a '[]`) in
-/// that declaration.
-///
-/// For example, for 'int *p[10];', there are two EntityPointerLevels.
-/// One is associated with 'int *[10]' of 'p' and the other is associated with
-/// 'int *' of 'p'.
-///
-/// An EntityPointerLevel can be identified by an EntityId and an unsigned
-/// integer indicating the pointer level: '(EntityId, PointerLevel)'.
-/// An EntityPointerLevel 'P' is valid iff 'P.EntityId' has a pointer type with
-/// at least 'P.PointerLevel' levels (This implies 'P.PointerLevel > 0').
-///
-/// For the same example 'int *p[10];', the EntityPointerLevels below are valid:
-/// - '(p, 2)' is associated with the 'int *' part of the declared type of 'p';
-/// - '(p, 1)' is associated with the 'int *[10]' part of the declared type of
-/// 'p'.
-class EntityPointerLevel {
- EntityId Entity;
- unsigned PointerLevel;
-
- friend class EntityPointerLevelTranslator;
- // For unittests:
- friend EntityPointerLevel buildEntityPointerLevel(EntityId, unsigned);
-
- explicit EntityPointerLevel(std::pair<EntityId, unsigned> Pair)
- : Entity(Pair.first), PointerLevel(Pair.second) {}
-
-public:
- EntityId getEntity() const { return Entity; }
- unsigned getPointerLevel() const { return PointerLevel; }
-
- bool operator==(const EntityPointerLevel &Other) const {
- return std::tie(Entity, PointerLevel) ==
- std::tie(Other.Entity, Other.PointerLevel);
- }
-
- bool operator!=(const EntityPointerLevel &Other) const {
- return !(*this == Other);
- }
-
- bool operator<(const EntityPointerLevel &Other) const {
- return std::tie(Entity, PointerLevel) <
- std::tie(Other.Entity, Other.PointerLevel);
- }
-
- /// Compares `EntityPointerLevel`s; additionally, partially compares
- /// `EntityPointerLevel` with `EntityId`.
- struct Comparator {
- using is_transparent = void;
- bool operator()(const EntityPointerLevel &L,
- const EntityPointerLevel &R) const {
- return L < R;
- }
- bool operator()(const EntityId &L, const EntityPointerLevel &R) const {
- return L < R.getEntity();
- }
- bool operator()(const EntityPointerLevel &L, const EntityId &R) const {
- return L.getEntity() < R;
- }
- };
-};
-
-using EntityPointerLevelSet =
- std::set<EntityPointerLevel, EntityPointerLevel::Comparator>;
-
-/// Translate a pointer/array type expression 'E' to a (set of)
-/// EntityPointerLevel(s) associated with the declared type of the base address
-/// of `E`. If the base address of `E` is not associated with an entity, the
-/// translation result is an empty set.
-///
-/// \param E the pointer expression to be translated
-/// \param Ctx the AST context of `E`
-/// \param AddEntity the callback provided by the caller to convert EntityNames
-/// to EntityIds.
-llvm::Expected<EntityPointerLevelSet>
-translateEntityPointerLevel(const Expr *E, ASTContext &Ctx,
- TUSummaryExtractor &Extractor);
-
-/// Creates a `EntityPointerLevel` from a pair of an EntityId and a pointer
-/// level:
-EntityPointerLevel buildEntityPointerLevel(EntityId, unsigned);
-
-/// Create an EntityPointerLevel (EPL) from a NamedDecl of a pointer/array type.
-///
-/// \param ND the NamedDecl of a pointer/array type.
-/// \param AddEntity the callback provided by the caller to convert EntityNames
-/// to EntityIds.
-/// \param IsFunRet true iff the created EPL is associated with the return type
-/// of a function entity.
-llvm::Expected<EntityPointerLevel>
-createEntityPointerLevel(const NamedDecl *ND, TUSummaryExtractor &Extractor,
- bool IsFunRet = false);
-
-/// Creates a new EntityPointerLevel (EPL) from `E` by incrementing `E`'s
-/// pointer level.
-/// \return the EPL that is associated with the pointee (or array element) type
-/// of `E`'s associated pointer/array type of the same entity.
-EntityPointerLevel incrementPointerLevel(const EntityPointerLevel &E);
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
deleted file mode 100644
index bccd1a1dc6225..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
+++ /dev/null
@@ -1,48 +0,0 @@
-//===- EntityPointerLevelFormat.h -------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "llvm/ADT/iterator_range.h"
-#include <map>
-
-namespace clang::ssaf {
-llvm::json::Value
-entityPointerLevelToJSON(const EntityPointerLevel &EPL,
- JSONFormat::EntityIdToJSONFn EntityId2JSON);
-
-Expected<EntityPointerLevel>
-entityPointerLevelFromJSON(const llvm::json::Value &EPLData,
- JSONFormat::EntityIdFromJSONFn EntityIdFromJSON);
-
-llvm::json::Array entityPointerLevelSetToJSON(
- llvm::iterator_range<EntityPointerLevelSet::const_iterator> EPLs,
- JSONFormat::EntityIdToJSONFn EntityId2JSON);
-
-Expected<EntityPointerLevelSet>
-entityPointerLevelSetFromJSON(const llvm::json::Array &EPLsData,
- JSONFormat::EntityIdFromJSONFn EntityIdFromJSON);
-
-/// Serialize a map<EntityId, EntityPointerLevelSet> as a flat array of
-/// alternating [EntityId, EntityPointerLevelSet, ...] pairs.
-llvm::json::Array entityPointerLevelMapToJSON(
- const std::map<EntityId, EntityPointerLevelSet> &Map,
- JSONFormat::EntityIdToJSONFn IdToJSON);
-
-/// Deserialize a flat array of alternating [EntityId, EntityPointerLevelSet,
-/// ...] pairs into a map.
-Expected<std::map<EntityId, EntityPointerLevelSet>>
-entityPointerLevelMapFromJSON(const llvm::json::Array &Content,
- JSONFormat::EntityIdFromJSONFn IdFromJSON);
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h
deleted file mode 100644
index 2b5bcfc650486..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- PointerFlow.h --------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the per-translation-unit summary type for the
-// pointer-flow analysis, which records static pointer assignment sites
-// as directed graph edges (EdgeSet).
-//
-//===----------------------------------------------------------------------===//
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOW_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOW_H
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-
-namespace clang::ssaf {
-
-/// Maps each LHS pointer (source / assignee) to the set of RHS pointers
-/// (destinations / assigned values) at static assignment sites.
-using EdgeSet = std::map<EntityPointerLevel, EntityPointerLevelSet>;
-
-class PointerFlowEntitySummary final : public EntitySummary {
- EdgeSet Edges;
-
- friend PointerFlowEntitySummary buildPointerFlowEntitySummary(EdgeSet Edges);
- friend llvm::iterator_range<EdgeSet::const_iterator>
- getEdges(const PointerFlowEntitySummary &);
-
- explicit PointerFlowEntitySummary(EdgeSet Edges) : Edges(std::move(Edges)) {}
-
-public:
- static constexpr llvm::StringLiteral Name = "PointerFlow";
-
- SummaryName getSummaryName() const override { return summaryName(); }
-
- bool operator==(const EdgeSet &Other) const { return Edges == Other; }
-
- bool operator==(const PointerFlowEntitySummary &Other) const {
- return Edges == Other.Edges;
- }
-
- bool empty() const { return Edges.empty(); }
-
- static SummaryName summaryName() { return SummaryName{Name.str()}; }
-};
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOW_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h
deleted file mode 100644
index 38cbd7d634895..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h
+++ /dev/null
@@ -1,46 +0,0 @@
-//===- PointerFlowAnalysis.h ------------------------------------*- C++- *-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines PointerFlowAnalysisResult — the whole-program pointer-flow graph
-// aggregated from per-translation-unit EdgeSet summaries.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOWANALYSIS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOWANALYSIS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "llvm/ADT/StringRef.h"
-#include <map>
-
-namespace clang::ssaf {
-
-constexpr llvm::StringLiteral PointerFlowAnalysisResultName =
- "PointerFlowAnalysisResult";
-
-/// The whole-program pointer-flow graph. Each directed edge 'src -> dest'
-/// records a static assignment site where 'src' (the LHS / assignee) is
-/// assigned the value of 'dest' (the RHS / assigned value).
-///
-/// This edge direction matches property-propagation direction: if a property
-/// (such as a bounds requirement) holds for 'src', it must also hold for
-/// 'dest', because 'dest' supplies the value that 'src' will hold.
-struct PointerFlowAnalysisResult final : AnalysisResult {
- static AnalysisName analysisName() {
- return AnalysisName(PointerFlowAnalysisResultName.str());
- }
-
- std::map<EntityId, EdgeSet> Edges;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOWANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.h
deleted file mode 100644
index be68e92317beb..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- PointerFlowFormat.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// JSON serialization helpers for EdgeSet (PointerFlow edge maps).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOWFORMAT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOWFORMAT_H
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "llvm/ADT/iterator_range.h"
-
-namespace clang::ssaf {
-
-/// Serialize an EdgeSet
-/// {(src1, dest1), (src1, dest2), (src2, dest3), (src2, dest4), ...}
-/// to an array of arrays of EntityPointerLevels:
-/// [ [src1, dest1, dest2, ...], [src2, dest3, dest4, ...], ... ]
-llvm::json::Array
-edgeSetToJSON(llvm::iterator_range<EdgeSet::const_iterator> Edges,
- JSONFormat::EntityIdToJSONFn IdToJSON);
-
-/// Deserialize an EdgeSet from the array format produced by `edgeSetToJSON`.
-llvm::Expected<EdgeSet>
-edgeSetFromJSON(const llvm::json::Array &EdgesData,
- JSONFormat::EntityIdFromJSONFn IdFromJSON);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_POINTERFLOW_POINTERFLOWFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
deleted file mode 100644
index 972ff6a21bb25..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//===- UnsafeBufferUsage.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-
-namespace clang::ssaf {
-/// An UnsafeBufferUsageEntitySummary contains a set of EntityPointerLevels
-/// extracted from unsafe buffer pointers contributed by an entity.
-class UnsafeBufferUsageEntitySummary final : public EntitySummary {
- const EntityPointerLevelSet UnsafeBuffers;
-
- friend class UnsafeBufferUsageTUSummaryExtractor;
- friend UnsafeBufferUsageEntitySummary
- buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet);
- friend llvm::iterator_range<EntityPointerLevelSet::const_iterator>
- getUnsafeBuffers(const UnsafeBufferUsageEntitySummary &);
-
- explicit UnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers)
- : UnsafeBuffers(std::move(UnsafeBuffers)) {}
-
-public:
- static constexpr llvm::StringLiteral Name = "UnsafeBufferUsage";
-
- SummaryName getSummaryName() const override { return summaryName(); };
-
- bool operator==(const EntityPointerLevelSet &Other) const {
- return UnsafeBuffers == Other;
- }
-
- bool operator==(const UnsafeBufferUsageEntitySummary &Other) const {
- return UnsafeBuffers == Other.UnsafeBuffers;
- }
-
- bool empty() const { return UnsafeBuffers.empty(); }
-
- static SummaryName summaryName() { return SummaryName{Name.str()}; }
-};
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h b/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h
deleted file mode 100644
index da9115679bb2c..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//===- UnsafeBufferUsageAnalysis.h ------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines:
-// - UnsafeBufferUsageAnalysisResult
-// - the whole-program analysis result
-// type for UnsafeBufferUsageAnalysis. It collects unsafe buffer usages
-// throughout the whole program.
-//
-// - UnsafeBufferReachableAnalysisResult
-// - the whole-program analysis result
-// type for UnsafeBufferReachableAnalysis. It propagates unsafe buffer
-// usages through the pointer flow graph, starting from the initial set
-// collected by UnsafeBufferUsageAnalysis.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEANALYSIS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEANALYSIS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "llvm/ADT/StringRef.h"
-#include <map>
-
-namespace clang::ssaf {
-
-constexpr llvm::StringLiteral UnsafeBufferUsageAnalysisResultName =
- "UnsafeBufferUsageAnalysisResult";
-constexpr llvm::StringLiteral UnsafeBufferReachableAnalysisResultName =
- "UnsafeBufferReachableAnalysisResult";
-
-struct UnsafeBufferUsageAnalysisResult final : AnalysisResult {
- static AnalysisName analysisName() {
- return AnalysisName(UnsafeBufferUsageAnalysisResultName.str());
- }
-
- /// Whole-program set of unsafe buffer pointers:
- std::map<EntityId, EntityPointerLevelSet> UnsafeBuffers;
-
- auto begin() const { return UnsafeBuffers.begin(); }
- auto end() const { return UnsafeBuffers.end(); }
-};
-
-struct UnsafeBufferReachableAnalysisResult final : AnalysisResult {
- static AnalysisName analysisName() {
- return AnalysisName(UnsafeBufferReachableAnalysisResultName.str());
- }
-
- std::map<EntityId, EntityPointerLevelSet> Reachables;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def b/clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def
deleted file mode 100644
index ba4944ea984cb..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- BuiltinAnchorSources.def ---------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file lists all the SSAF Anchor source names.
-/// This file should be exclusively used by SSAFBuiltinForceLinker.h
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef ANCHOR
-#define ANCHOR(NAME)
-#endif
-
-ANCHOR(AnalysisRegistryAnchorSource)
-ANCHOR(CallGraphExtractorAnchorSource)
-ANCHOR(CallGraphJSONFormatAnchorSource)
-ANCHOR(JSONFormatAnchorSource)
-ANCHOR(PointerFlowAnalysisAnchorSource)
-ANCHOR(PointerFlowExtractorAnchorSource)
-ANCHOR(PointerFlowJSONFormatAnchorSource)
-ANCHOR(SSAFSourceTransformationAnchorSource)
-ANCHOR(UnsafeBufferUsageAnalysisAnchorSource)
-ANCHOR(UnsafeBufferUsageExtractorAnchorSource)
-ANCHOR(UnsafeBufferUsageJSONFormatAnchorSource)
-
-#undef ANCHOR
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h
deleted file mode 100644
index 5057f8ac4505f..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- ASTEntityMapping.h - AST to SSAF Entity mapping ----------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ASTENTITYMAPPING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ASTENTITYMAPPING_H
-
-#include "clang/AST/Decl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "llvm/ADT/StringRef.h"
-#include <optional>
-
-namespace clang::ssaf {
-
-/// Maps a declaration to an EntityName.
-///
-/// Supported declaration types for entity mapping:
-/// - Functions and methods
-/// - Global Variables
-/// - Function parameters
-/// - Struct/class/union type definitions
-/// - Struct/class/union fields
-///
-/// Implicit declarations and compiler builtins are not mapped.
-///
-/// \param D The declaration to map. Must not be null.
-///
-/// \return An EntityName if the declaration can be mapped, std::nullopt
-/// otherwise.
-std::optional<EntityName> getEntityName(const Decl *D);
-
-/// Maps return entity of a function to an EntityName.
-/// The returned name uniquely identifies the return value of function \param
-/// FD.
-///
-/// \param FD The function declaration. Must not be null.
-///
-/// \return An EntityName for the function's return entity.
-std::optional<EntityName> getEntityNameForReturn(const FunctionDecl *FD);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ASTENTITYMAPPING_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h
deleted file mode 100644
index ed02560004632..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//===- EntityLinker.h - Class for linking entities --------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the EntityLinker class that combines multiple TU summaries
-// into a unified LU summary by deduplicating entities and patching summaries.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYLINKER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYLINKER_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "llvm/Support/Error.h"
-#include "llvm/TargetParser/Triple.h"
-#include <map>
-#include <memory>
-#include <set>
-#include <vector>
-
-namespace clang::ssaf {
-
-class TUSummaryEncoding;
-
-class EntityLinker {
- LUSummaryEncoding Output;
- std::set<BuildNamespace> ProcessedTUNamespaces;
-
-public:
- /// Constructs an EntityLinker to link TU summaries into a LU summary.
- ///
- /// \param TargetTriple The target triple of the link unit. Every linked TU
- /// must report the same triple.
- /// \param LUNamespace The namespace identifying this link unit.
- EntityLinker(llvm::Triple TargetTriple, NestedBuildNamespace LUNamespace)
- : Output(std::move(TargetTriple), std::move(LUNamespace)) {}
-
- /// Links a TU summary into a LU summary.
- ///
- /// Deduplicates entities, patches entity ID references in the entity summary,
- /// and merges them into a single data store.
- ///
- /// \param Summary The TU summary to link. Ownership is transferred.
- /// \returns Error if the TU namespace has already been linked or if patching
- /// fails, success otherwise. Corrupted summary data (missing linkage
- /// information, duplicate entity IDs, etc.) triggers a fatal error.
- llvm::Error link(std::unique_ptr<TUSummaryEncoding> Summary);
-
- /// Returns the accumulated LU summary.
- ///
- /// \returns LU summary containing all the deduplicated and patched entity
- /// summaries.
- LUSummaryEncoding takeOutput() && { return std::move(Output); }
-
-private:
- /// Resolves a TU entity name to an LU entity name and ID.
- ///
- /// \param OldName The entity name in the TU namespace.
- /// \param Linkage The linkage determining namespace resolution strategy.
- /// \returns The resolved LU EntityId.
- EntityId resolveEntity(const EntityName &OldName,
- const EntityLinkage &Linkage,
- const NestedBuildNamespace &TUNamespace);
-
- /// Resolves each TU EntityId to its corresponding LU EntityId.
- ///
- /// \param Summary The TU summary whose entities are being resolved.
- /// \returns A map from TU EntityIds to their corresponding LU EntityIds.
- std::map<EntityId, EntityId> resolve(const TUSummaryEncoding &Summary);
-
- /// Merges all summary data from a TU summary into the LU Summary.
- ///
- /// \param Summary The TU summary whose data is being merged.
- /// \param EntityResolutionTable Map from TU EntityIds to LU EntityIds.
- /// \returns Pointers to each EntitySummaryEncoding successfully merged.
- std::vector<EntitySummaryEncoding *>
- merge(TUSummaryEncoding &Summary,
- const std::map<EntityId, EntityId> &EntityResolutionTable);
-
- /// Patches EntityId references in merged summary data.
- ///
- /// \param PatchTargets Vector of summary encodings that need patching.
- /// \param EntityResolutionTable Map from TU EntityIds to LU EntityIds.
- /// \returns Error if patching any encoding fails, success otherwise.
- llvm::Error patch(const std::vector<EntitySummaryEncoding *> &PatchTargets,
- const std::map<EntityId, EntityId> &EntityResolutionTable);
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYLINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h
deleted file mode 100644
index 461fd74c8cafe..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- EntitySummaryEncoding.h ----------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the EntitySummaryEncoding class, which represents
-// EntitySummary data in an encoded, format-specific form.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "llvm/Support/Error.h"
-#include <map>
-
-namespace clang::ssaf {
-
-/// Represents EntitySummary data in its serialized, format-specific encoding.
-///
-/// This abstract base class allows the entity linker to manipulate serialized
-/// entity summary data without knowing the exact schema of the EntitySummary
-/// subclass. The primary operation is patching EntityId references when
-/// entities are merged during linking.
-class EntitySummaryEncoding {
-public:
- virtual ~EntitySummaryEncoding() = default;
-
- /// Updates EntityId references in the encoded data.
- ///
- /// \param EntityResolutionTable Mapping from old EntityIds to new EntityIds.
- virtual llvm::Error
- patch(const std::map<EntityId, EntityId> &EntityResolutionTable) = 0;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h
deleted file mode 100644
index 0e042f783c501..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//===- LUSummary.h ----------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the LUSummary class, which represents a link unit summary
-// containing merged and deduplicated entity summaries from multiple TUs.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "llvm/TargetParser/Triple.h"
-#include <map>
-#include <memory>
-
-namespace clang::ssaf {
-
-/// Represents a link unit (LU) summary containing merged entity summaries.
-///
-/// LUSummary is the result of linking multiple translation unit summaries
-/// together. It contains deduplicated entities with their linkage information
-/// and the merged entity summaries.
-class LUSummary {
- friend class AnalysisDriver;
- friend class LUSummaryConsumer;
- friend class SerializationFormat;
- friend class TestFixture;
-
- /// Target triple of the link unit.
- llvm::Triple TargetTriple;
-
- NestedBuildNamespace LUNamespace;
-
- EntityIdTable IdTable;
-
- std::map<EntityId, EntityLinkage> LinkageTable;
-
- std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>
- Data;
-
-public:
- LUSummary(llvm::Triple TargetTriple, NestedBuildNamespace LUNamespace)
- : TargetTriple(std::move(TargetTriple)),
- LUNamespace(std::move(LUNamespace)) {}
-
- const NestedBuildNamespace &getNamespace() const { return LUNamespace; }
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h
deleted file mode 100644
index f7fcd903b5c20..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h
+++ /dev/null
@@ -1,64 +0,0 @@
-//===- LUSummaryEncoding.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the LUSummaryEncoding class, which represents a link unit
-// summary in its serialized, format-specific encoding.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "llvm/TargetParser/Triple.h"
-#include <map>
-#include <memory>
-
-namespace clang::ssaf {
-
-/// Represents a link unit summary in its serialized encoding.
-///
-/// LUSummaryEncoding holds the combined entity summary data from multiple
-/// translation units in a format-specific encoding. It is produced by the
-/// entity linker and contains deduplicated and patched entity summaries.
-class LUSummaryEncoding {
- friend class EntityLinker;
- friend class SerializationFormat;
- friend class TestFixture;
-
- // Target triple of the link unit.
- llvm::Triple TargetTriple;
-
- // The namespace identifying this link unit.
- NestedBuildNamespace LUNamespace;
-
- // Maps entity names to their unique identifiers within this link unit.
- EntityIdTable IdTable;
-
- // Maps entity IDs to their linkage properties.
- std::map<EntityId, EntityLinkage> LinkageTable;
-
- // Encoded summary data organized by summary type and entity ID.
- std::map<SummaryName,
- std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
- Data;
-
-public:
- LUSummaryEncoding(llvm::Triple TargetTriple, NestedBuildNamespace LUNamespace)
- : TargetTriple(std::move(TargetTriple)),
- LUNamespace(std::move(LUNamespace)) {}
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h
deleted file mode 100644
index 5cf3e8283874f..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h
+++ /dev/null
@@ -1,67 +0,0 @@
-//===- TUSummaryEncoding.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the TUSummaryEncoding class, which represents a
-// translation unit summary in its serialized, format-specific encoding.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "llvm/TargetParser/Triple.h"
-#include <map>
-#include <memory>
-
-namespace clang::ssaf {
-
-/// Represents a translation unit summary in its serialized encoding.
-///
-/// TUSummaryEncoding holds entity summary data in a format-specific encoding
-/// that can be manipulated by the entity linker without deserializing the
-/// full EntitySummary objects. This enables efficient entity ID patching
-/// during the linking process.
-class TUSummaryEncoding {
- friend class EntityLinker;
- friend class SerializationFormat;
- friend class TestFixture;
-
- // Target triple of the translation unit.
- llvm::Triple TargetTriple;
-
- // The namespace identifying this translation unit.
- BuildNamespace TUNamespace;
-
- // Maps entity names to their unique identifiers within this TU.
- EntityIdTable IdTable;
-
- // Maps entity IDs to their linkage properties (None, Internal, External).
- std::map<EntityId, EntityLinkage> LinkageTable;
-
- // Encoded summary data organized by summary type and entity ID.
- std::map<SummaryName,
- std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
- Data;
-
-public:
- TUSummaryEncoding(llvm::Triple TargetTriple, BuildNamespace TUNamespace)
- : TargetTriple(std::move(TargetTriple)),
- TUNamespace(std::move(TUNamespace)) {}
-
- const llvm::Triple &getTargetTriple() const { return TargetTriple; }
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h
deleted file mode 100644
index 16c6fd6fcb4ef..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h
+++ /dev/null
@@ -1,129 +0,0 @@
-//===- BuildNamespace.h -----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines BuildNamespace and NestedBuildNamespace classes that
-// represent build namespaces in the Scalable Static Analysis Framework.
-//
-// Build namespaces provide an abstraction for grouping program entities (such
-// as those in a shared library or compilation unit) to enable analysis of
-// software projects constructed from individual components.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_BUILDNAMESPACE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_BUILDNAMESPACE_H
-
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <optional>
-#include <string>
-#include <vector>
-
-namespace clang::ssaf {
-
-enum class BuildNamespaceKind : unsigned short { CompilationUnit, LinkUnit };
-
-/// Represents a single namespace in the build process.
-///
-/// A BuildNamespace groups program entities, such as those belonging to a
-/// compilation unit or link unit (e.g., a shared library). Each namespace has a
-/// kind (CompilationUnit or LinkUnit) and a unique identifier name within that
-/// kind.
-///
-/// BuildNamespaces can be composed into NestedBuildNamespace to represent
-/// hierarchical namespace structures that model how software is constructed
-/// from its components.
-class BuildNamespace {
- BuildNamespaceKind Kind;
- std::string Name;
-
- auto asTuple() const { return std::tie(Kind, Name); }
-
-public:
- BuildNamespace(BuildNamespaceKind Kind, llvm::StringRef Name)
- : Kind(Kind), Name(Name.str()) {}
-
- /// Creates a BuildNamespace representing a compilation unit.
- ///
- /// \param CompilationId The unique identifier for the compilation unit.
- /// \returns A BuildNamespace with CompilationUnit kind.
- static BuildNamespace makeCompilationUnit(llvm::StringRef CompilationId);
-
- bool operator==(const BuildNamespace &Other) const;
- bool operator!=(const BuildNamespace &Other) const;
- bool operator<(const BuildNamespace &Other) const;
-
- friend class EntityLinker;
- friend class SerializationFormat;
- friend class TestFixture;
- friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const BuildNamespace &BN);
-};
-
-/// Represents a hierarchical sequence of build namespaces.
-///
-/// A NestedBuildNamespace captures namespace qualification for program entities
-/// by maintaining an ordered sequence of BuildNamespace steps. This models how
-/// entities are organized through multiple steps of the build process, such as
-/// first being part of a compilation unit, then incorporated into a link unit.
-///
-/// For example, an entity might be qualified by a compilation unit namespace
-/// followed by a shared library namespace.
-class NestedBuildNamespace {
- std::vector<BuildNamespace> Namespaces;
-
-public:
- NestedBuildNamespace() = default;
-
- explicit NestedBuildNamespace(const std::vector<BuildNamespace> &Namespaces)
- : Namespaces(Namespaces) {}
-
- explicit NestedBuildNamespace(const BuildNamespace &N) {
- Namespaces.push_back(N);
- }
-
- /// Creates a NestedBuildNamespace representing a compilation unit.
- ///
- /// \param CompilationId The unique identifier for the compilation unit.
- /// \returns A NestedBuildNamespace containing a single CompilationUnit
- /// BuildNamespace.
- static NestedBuildNamespace
- makeCompilationUnit(llvm::StringRef CompilationId);
-
- /// Creates a new NestedBuildNamespace by appending additional namespace.
- ///
- /// \param Namespace The namespace to append.
- NestedBuildNamespace makeQualified(NestedBuildNamespace Namespace) const {
- auto Copy = *this;
- Copy.Namespaces.reserve(Copy.Namespaces.size() +
- Namespace.Namespaces.size());
- llvm::append_range(Copy.Namespaces, Namespace.Namespaces);
- return Copy;
- }
-
- bool empty() const;
-
- bool operator==(const NestedBuildNamespace &Other) const;
- bool operator!=(const NestedBuildNamespace &Other) const;
- bool operator<(const NestedBuildNamespace &Other) const;
-
- friend class SerializationFormat;
- friend class TestFixture;
- friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const NestedBuildNamespace &NBN);
-};
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, BuildNamespaceKind BNK);
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const BuildNamespace &BN);
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const NestedBuildNamespace &NBN);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_BUILDNAMESPACE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h
deleted file mode 100644
index 0da76e17c823e..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- EntityId.h -----------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the EntityId class, which provides a lightweight opaque
-// handle to entities in an EntityIdTable. EntityIds are index-based for
-// efficient comparison and lookup.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYID_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYID_H
-
-#include "llvm/Support/raw_ostream.h"
-#include <cstddef>
-
-namespace clang::ssaf {
-
-class EntityIdTable;
-
-/// Lightweight opaque handle representing an entity in an EntityIdTable.
-///
-/// EntityIds are created by EntityIdTable. Equality and ordering comparisons
-/// are well-defined for EntityIds created by the same EntityIdTable.
-///
-/// \see EntityIdTable
-class EntityId {
- friend class EntityIdTable;
- friend class SerializationFormat;
- friend class TestFixture;
- friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const EntityId &Id);
-
- size_t Index;
-
- explicit EntityId(size_t Index) : Index(Index) {}
-
- EntityId() = delete;
-
-public:
- bool operator==(const EntityId &Other) const { return Index == Other.Index; }
- bool operator<(const EntityId &Other) const { return Index < Other.Index; }
- bool operator!=(const EntityId &Other) const { return !(*this == Other); }
-};
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityId &Id);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYID_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h
deleted file mode 100644
index d74b871df3e16..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//===- EntityIdTable.h ------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYIDTABLE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYIDTABLE_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include <functional>
-#include <map>
-
-namespace clang::ssaf {
-
-/// Manages entity name interning and provides efficient EntityId handles.
-///
-/// The table maps each unique EntityName to exactly one EntityId.
-/// Entities are never removed.
-class EntityIdTable {
- friend class SerializationFormat;
- friend class TestFixture;
-
- std::map<EntityName, EntityId> Entities;
-
-public:
- EntityIdTable() = default;
-
- /// Creates or retrieves an EntityId for the given EntityName.
- ///
- /// If the entity already exists in the table, returns its existing Id.
- /// Otherwise, creates and returns a new Id. This operation is idempotent.
- EntityId getId(const EntityName &Name);
-
- /// Returns true if an entity with the given name exists in the table.
- bool contains(const EntityName &Name) const;
-
- /// Invokes the callback for each entity in the table.
- ///
- /// Iteration order is unspecified.
- void forEach(
- llvm::function_ref<void(const EntityName &, EntityId)> Callback) const;
-
- /// Returns the number of unique entities in the table.
- size_t count() const { return Entities.size(); }
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYIDTABLE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h
deleted file mode 100644
index 2efddffd9a29c..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//===- EntityLinkage.h ------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYLINKAGE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYLINKAGE_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace clang::ssaf {
-
-enum class EntityLinkageType {
- None, ///< local variables
- Internal, ///< static functions/variables, anonymous namespace
- External ///< globally visible across translation units (including parameters
- ///< of functions with external linkage)
-};
-
-/// Represents the linkage properties of an entity in the program model.
-///
-/// EntityLinkage captures whether an entity has no linkage, internal linkage,
-/// or external linkage, which determines its visibility and accessibility
-/// across translation units.
-class EntityLinkage {
- friend class SerializationFormat;
- friend class TestFixture;
-
-public:
- constexpr explicit EntityLinkage(EntityLinkageType L) : Linkage(L) {}
-
- EntityLinkageType getLinkage() const { return Linkage; }
-
- bool operator==(const EntityLinkage &Other) const;
- bool operator!=(const EntityLinkage &Other) const;
-
-private:
- EntityLinkageType Linkage;
-};
-
-/// Writes a string representation of the linkage type to the stream.
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EntityLinkageType Linkage);
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const EntityLinkage &Linkage);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYLINKAGE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h
deleted file mode 100644
index 853ac96209a86..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//===- EntityName.h ---------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYNAME_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYNAME_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <string>
-
-namespace clang::ssaf {
-/// Uniquely identifies an entity in a program.
-///
-/// EntityName provides a globally unique identifier for program entities that
-/// remains stable across compilation boundaries. This enables whole-program
-/// analysis to track and relate entities across separately compiled translation
-/// units.
-///
-/// Client code should not make assumptions about the implementation details,
-/// such as USRs.
-class EntityName {
- friend class EntityLinker;
- friend class SerializationFormat;
- friend class TestFixture;
- friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const EntityName &EN);
-
- std::string USR;
- llvm::SmallString<16> Suffix;
- NestedBuildNamespace Namespace;
-
- auto asTuple() const { return std::tie(USR, Suffix, Namespace); }
-
-public:
- /// Client code should not use this constructor directly.
- /// Use getEntityName and other functions in ASTEntityMapping.h to get
- /// entity names.
- EntityName(llvm::StringRef USR, llvm::StringRef Suffix,
- NestedBuildNamespace Namespace);
-
- bool operator==(const EntityName &Other) const;
- bool operator!=(const EntityName &Other) const;
- bool operator<(const EntityName &Other) const;
-
- /// Creates a new EntityName with additional build namespace qualification.
- ///
- /// \param Namespace The namespace steps to append to this entity's namespace.
- EntityName makeQualified(NestedBuildNamespace Namespace) const;
-};
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityName &EN);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_ENTITYNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def
deleted file mode 100644
index 44931026ba428..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- PrivateFieldNames.def ------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a list of non-static data members of the SSAF objects.
-// These are used for granting access for:
-// - SerializationFormat
-// - TestFixture
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef FIELD
-#define FIELD(CLASS, FIELD_NAME)
-#endif
-
-FIELD(BuildNamespace, Kind)
-FIELD(BuildNamespace, Name)
-FIELD(EntityId, Index)
-FIELD(EntityIdTable, Entities)
-FIELD(EntityLinkage, Linkage)
-FIELD(EntityName, Namespace)
-FIELD(EntityName, Suffix)
-FIELD(EntityName, USR)
-FIELD(LUSummary, TargetTriple)
-FIELD(LUSummary, Data)
-FIELD(LUSummary, IdTable)
-FIELD(LUSummary, LinkageTable)
-FIELD(LUSummary, LUNamespace)
-FIELD(LUSummaryEncoding, TargetTriple)
-FIELD(LUSummaryEncoding, Data)
-FIELD(LUSummaryEncoding, IdTable)
-FIELD(LUSummaryEncoding, LinkageTable)
-FIELD(LUSummaryEncoding, LUNamespace)
-FIELD(NestedBuildNamespace, Namespaces)
-FIELD(TUSummary, TargetTriple)
-FIELD(TUSummary, Data)
-FIELD(TUSummary, IdTable)
-FIELD(TUSummary, LinkageTable)
-FIELD(TUSummary, TUNamespace)
-FIELD(TUSummaryEncoding, TargetTriple)
-FIELD(TUSummaryEncoding, Data)
-FIELD(TUSummaryEncoding, IdTable)
-FIELD(TUSummaryEncoding, LinkageTable)
-FIELD(TUSummaryEncoding, TUNamespace)
-FIELD(WPASuite, Data)
-FIELD(WPASuite, IdTable)
-
-#undef FIELD
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h
deleted file mode 100644
index 99b5308e61a4e..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- SummaryName.h --------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_SUMMARYNAME_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_SUMMARYNAME_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <string>
-
-namespace clang::ssaf {
-
-/// Uniquely identifies an analysis summary.
-///
-/// This is the key to refer to an analysis or to name a builder to build an
-/// analysis.
-class SummaryName {
-public:
- explicit SummaryName(std::string Name) : Name(std::move(Name)) {}
-
- bool operator==(const SummaryName &Other) const { return Name == Other.Name; }
- bool operator!=(const SummaryName &Other) const { return !(*this == Other); }
- bool operator<(const SummaryName &Other) const { return Name < Other.Name; }
-
- /// Explicit conversion to the underlying string representation.
- llvm::StringRef str() const { return Name; }
-
-private:
- std::string Name;
- friend class TestFixture;
-};
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SummaryName &SN);
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODEL_SUMMARYNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h
deleted file mode 100644
index 7841240319af6..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h
+++ /dev/null
@@ -1,268 +0,0 @@
-//===- JSONFormat.h ---------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// JSON serialization format implementation.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
-#include "clang/Support/Compiler.h"
-#include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/Registry.h"
-
-#include <set>
-
-namespace clang::ssaf {
-
-class EntityIdTable;
-class EntitySummary;
-class SummaryName;
-
-class JSONFormat final : public SerializationFormat {
- using Array = llvm::json::Array;
- using Object = llvm::json::Object;
- using Value = llvm::json::Value;
-
- friend class JSONEntitySummaryEncoding;
-
-public:
- llvm::Expected<TUSummary> readTUSummary(llvm::StringRef Path) override;
-
- llvm::Error writeTUSummary(const TUSummary &Summary,
- llvm::StringRef Path) override;
-
- llvm::Expected<TUSummaryEncoding>
- readTUSummaryEncoding(llvm::StringRef Path) override;
-
- llvm::Error writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding,
- llvm::StringRef Path) override;
-
- llvm::Expected<LUSummary> readLUSummary(llvm::StringRef Path) override;
-
- llvm::Error writeLUSummary(const LUSummary &Summary,
- llvm::StringRef Path) override;
-
- llvm::Expected<Artifact> readArtifact(llvm::StringRef Path) override;
-
- llvm::Error writeArtifact(const Artifact &A, llvm::StringRef Path) override;
-
- llvm::Expected<ArtifactEncoding>
- readArtifactEncoding(llvm::StringRef Path) override;
-
- llvm::Error writeArtifactEncoding(const ArtifactEncoding &E,
- llvm::StringRef Path) override;
-
- llvm::Expected<LUSummaryEncoding>
- readLUSummaryEncoding(llvm::StringRef Path) override;
-
- llvm::Error writeLUSummaryEncoding(const LUSummaryEncoding &SummaryEncoding,
- llvm::StringRef Path) override;
-
- llvm::Expected<WPASuite> readWPASuite(llvm::StringRef Path) override;
-
- llvm::Error writeWPASuite(const WPASuite &Suite,
- llvm::StringRef Path) override;
-
- void forEachRegisteredAnalysis(
- llvm::function_ref<void(llvm::StringRef Name, llvm::StringRef Desc)>
- Callback) const override;
-
- using EntityIdToJSONFn = llvm::function_ref<Object(EntityId)>;
- using EntityIdFromJSONFn =
- llvm::function_ref<llvm::Expected<EntityId>(const Object &)>;
-
- using SerializerFn =
- llvm::function_ref<Object(const EntitySummary &, EntityIdToJSONFn)>;
- using DeserializerFn =
- llvm::function_ref<llvm::Expected<std::unique_ptr<EntitySummary>>(
- const Object &, EntityIdTable &, EntityIdFromJSONFn)>;
-
- using FormatInfo = FormatInfoEntry<SerializerFn, DeserializerFn>;
-
- using AnalysisResultSerializerFn =
- llvm::function_ref<Object(const AnalysisResult &, EntityIdToJSONFn)>;
- using AnalysisResultDeserializerFn =
- llvm::function_ref<llvm::Expected<std::unique_ptr<AnalysisResult>>(
- const Object &, EntityIdFromJSONFn)>;
-
- using AnalysisResultRegistry =
- SerializationFormat::AnalysisResultRegistryGenerator<
- JSONFormat, AnalysisResultSerializerFn, AnalysisResultDeserializerFn>;
-
-private:
- static std::map<SummaryName, FormatInfo> initFormatInfos();
- const std::map<SummaryName, FormatInfo> FormatInfos = initFormatInfos();
-
- /// Parses a TUSummary from an already-validated root JSON object. The
- /// caller is responsible for verifying the self-describing type field
- /// and for wrapping any returned error with file-path context.
- llvm::Expected<TUSummary> readTUSummaryFromObject(const Object &Root);
-
- /// Parses an LUSummary from an already-validated root JSON object. See
- /// \c readTUSummaryFromObject for caller responsibilities.
- llvm::Expected<LUSummary> readLUSummaryFromObject(const Object &Root);
-
- /// Parses a TUSummaryEncoding from an already-validated root JSON
- /// object. See \c readTUSummaryFromObject for caller responsibilities.
- llvm::Expected<TUSummaryEncoding>
- readTUSummaryEncodingFromObject(const Object &Root);
-
- /// Parses an LUSummaryEncoding from an already-validated root JSON
- /// object. See \c readTUSummaryFromObject for caller responsibilities.
- llvm::Expected<LUSummaryEncoding>
- readLUSummaryEncodingFromObject(const Object &Root);
-
- /// Parses a WPASuite from an already-validated root JSON object. See
- /// \c readTUSummaryFromObject for caller responsibilities.
- llvm::Expected<WPASuite> readWPASuiteFromObject(const Object &Root);
-
- EntityId entityIdFromJSON(const uint64_t EntityIdIndex) const;
- uint64_t entityIdToJSON(EntityId EI) const;
-
- static llvm::Expected<EntityId>
- entityIdFromJSONObject(const Object &EntityIdObject);
- static Object entityIdToJSONObject(EntityId EI);
-
- llvm::Expected<BuildNamespace>
- buildNamespaceFromJSON(const Object &BuildNamespaceObject) const;
- Object buildNamespaceToJSON(const BuildNamespace &BN) const;
-
- llvm::Expected<NestedBuildNamespace>
- nestedBuildNamespaceFromJSON(const Array &NestedBuildNamespaceArray) const;
- Array nestedBuildNamespaceToJSON(const NestedBuildNamespace &NBN) const;
-
- llvm::Expected<EntityName>
- tuEntityNameFromJSON(const Object &EntityNameObject) const;
- Object tuEntityNameToJSON(const EntityName &EN) const;
-
- llvm::Expected<EntityName>
- luEntityNameFromJSON(const Object &EntityNameObject) const;
- Object luEntityNameToJSON(const EntityName &EN) const;
-
- llvm::Expected<EntityLinkage>
- entityLinkageFromJSON(const Object &EntityLinkageObject) const;
- Object entityLinkageToJSON(const EntityLinkage &EL) const;
-
- llvm::Expected<std::pair<EntityName, EntityId>>
- tuEntityIdTableEntryFromJSON(const Object &EntityIdTableEntryObject) const;
- llvm::Expected<EntityIdTable>
- tuEntityIdTableFromJSON(const Array &EntityIdTableArray) const;
- Object tuEntityIdTableEntryToJSON(const EntityName &EN, EntityId EI) const;
- Array tuEntityIdTableToJSON(const EntityIdTable &IdTable) const;
-
- llvm::Expected<std::pair<EntityName, EntityId>>
- luEntityIdTableEntryFromJSON(const Object &EntityIdTableEntryObject) const;
- llvm::Expected<EntityIdTable>
- luEntityIdTableFromJSON(const Array &EntityIdTableArray) const;
- Object luEntityIdTableEntryToJSON(const EntityName &EN, EntityId EI) const;
- Array luEntityIdTableToJSON(const EntityIdTable &IdTable) const;
-
- llvm::Expected<std::pair<EntityId, EntityLinkage>>
- linkageTableEntryFromJSON(const Object &LinkageTableEntryObject) const;
- Object linkageTableEntryToJSON(EntityId EI, const EntityLinkage &EL) const;
-
- llvm::Expected<std::map<EntityId, EntityLinkage>>
- linkageTableFromJSON(const Array &LinkageTableArray,
- std::set<EntityId> ExpectedIds) const;
- Array linkageTableToJSON(
- const std::map<EntityId, EntityLinkage> &LinkageTable) const;
-
- llvm::Expected<std::unique_ptr<EntitySummary>>
- entitySummaryFromJSON(const SummaryName &SN,
- const Object &EntitySummaryObject,
- EntityIdTable &IdTable) const;
- llvm::Expected<Object> entitySummaryToJSON(const SummaryName &SN,
- const EntitySummary &ES) const;
-
- llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummary>>>
- entityDataMapEntryFromJSON(const Object &EntityDataMapEntryObject,
- const SummaryName &SN,
- EntityIdTable &IdTable) const;
- llvm::Expected<Object>
- entityDataMapEntryToJSON(const EntityId EI,
- const std::unique_ptr<EntitySummary> &EntitySummary,
- const SummaryName &SN) const;
- llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummary>>>
- entityDataMapFromJSON(const SummaryName &SN, const Array &EntityDataArray,
- EntityIdTable &IdTable) const;
- llvm::Expected<Array>
- entityDataMapToJSON(const SummaryName &SN,
- const std::map<EntityId, std::unique_ptr<EntitySummary>>
- &EntityDataMap) const;
-
- llvm::Expected<std::pair<SummaryName,
- std::map<EntityId, std::unique_ptr<EntitySummary>>>>
- summaryDataMapEntryFromJSON(const Object &SummaryDataObject,
- EntityIdTable &IdTable) const;
- llvm::Expected<Object> summaryDataMapEntryToJSON(
- const SummaryName &SN,
- const std::map<EntityId, std::unique_ptr<EntitySummary>> &SD) const;
-
- llvm::Expected<
- std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>>
- summaryDataMapFromJSON(const Array &SummaryDataArray,
- EntityIdTable &IdTable) const;
- llvm::Expected<Array> summaryDataMapToJSON(
- const std::map<SummaryName,
- std::map<EntityId, std::unique_ptr<EntitySummary>>>
- &SummaryDataMap) const;
-
- llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
- encodingDataMapEntryFromJSON(const Object &EntityDataMapEntryObject) const;
- Object encodingDataMapEntryToJSON(
- EntityId EI,
- const std::unique_ptr<EntitySummaryEncoding> &Encoding) const;
-
- llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
- encodingDataMapFromJSON(const Array &EntityDataArray) const;
- Array encodingDataMapToJSON(
- const std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>
- &EncodingDataMap) const;
-
- llvm::Expected<std::pair<
- SummaryName, std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>>
- encodingSummaryDataMapEntryFromJSON(
- const Object &SummaryDataMapEntryObject) const;
- Object encodingSummaryDataMapEntryToJSON(
- const SummaryName &SN,
- const std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>
- &EncodingMap) const;
-
- llvm::Expected<std::map<
- SummaryName, std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>>
- encodingSummaryDataMapFromJSON(const Array &SummaryDataArray) const;
- Array encodingSummaryDataMapToJSON(
- const std::map<SummaryName,
- std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
- &EncodingSummaryDataMap) const;
-
- llvm::Expected<std::pair<AnalysisName, std::unique_ptr<AnalysisResult>>>
- analysisResultMapEntryFromJSON(const Object &Entry) const;
- llvm::Expected<Object> analysisResultMapEntryToJSON(
- const AnalysisName &Name,
- const std::unique_ptr<AnalysisResult> &Result) const;
-
- llvm::Expected<std::map<AnalysisName, std::unique_ptr<AnalysisResult>>>
- analysisResultMapFromJSON(const Array &ResultsArray) const;
- llvm::Expected<Array> analysisResultMapToJSON(
- const std::map<AnalysisName, std::unique_ptr<AnalysisResult>> &Data)
- const;
-};
-
-} // namespace clang::ssaf
-
-LLVM_DECLARE_REGISTRY(llvm::Registry<clang::ssaf::JSONFormat::FormatInfo>)
-LLVM_DECLARE_REGISTRY(
- llvm::Registry<clang::ssaf::JSONFormat::AnalysisResultRegistry::Codec>)
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
deleted file mode 100644
index 621182a352bc7..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h
+++ /dev/null
@@ -1,266 +0,0 @@
-//===- SerializationFormat.h ------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Abstract SerializationFormat interface for reading and writing
-// TUSummary and LinkUnitResolution data.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-#include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/Registry.h"
-
-#include <variant>
-
-namespace clang::ssaf {
-
-/// Sum type returned by \c SerializationFormat::readArtifact, used when the
-/// caller does not know up-front which kind of top-level SSAF artifact a
-/// file contains. The active alternative is decided by the file's
-/// self-describing type field.
-using Artifact = std::variant<TUSummary, LUSummary, WPASuite>;
-
-/// Lazily-deserialized counterpart of \c Artifact: the same on-disk
-/// artifacts but with their per-entity summary payloads left as opaque
-/// format-specific encodings rather than fully resolved analysis results.
-using ArtifactEncoding = std::variant<TUSummaryEncoding, LUSummaryEncoding>;
-
-/// Abstract base class for serialization formats.
-class SerializationFormat {
-public:
- virtual ~SerializationFormat() = default;
-
- virtual llvm::Expected<TUSummary> readTUSummary(llvm::StringRef Path) = 0;
-
- virtual llvm::Error writeTUSummary(const TUSummary &Summary,
- llvm::StringRef Path) = 0;
-
- virtual llvm::Expected<TUSummaryEncoding>
- readTUSummaryEncoding(llvm::StringRef Path) = 0;
-
- virtual llvm::Error
- writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding,
- llvm::StringRef Path) = 0;
-
- virtual llvm::Expected<LUSummary> readLUSummary(llvm::StringRef Path) = 0;
-
- virtual llvm::Error writeLUSummary(const LUSummary &Summary,
- llvm::StringRef Path) = 0;
-
- /// Generic read entry point. Inspects the file's self-describing type
- /// field and dispatches to \c readTUSummary or \c readLUSummary
- /// accordingly. Returns an error if the type field is missing or names
- /// an unrecognized artifact kind.
- virtual llvm::Expected<Artifact> readArtifact(llvm::StringRef Path) = 0;
-
- /// Generic write entry point. Dispatches to \c writeTUSummary or
- /// \c writeLUSummary based on the active variant alternative.
- virtual llvm::Error writeArtifact(const Artifact &A,
- llvm::StringRef Path) = 0;
-
- /// Encoding-flavored counterpart of \c readArtifact. Inspects the
- /// self-describing type field and dispatches to
- /// \c readTUSummaryEncoding or \c readLUSummaryEncoding accordingly.
- virtual llvm::Expected<ArtifactEncoding>
- readArtifactEncoding(llvm::StringRef Path) = 0;
-
- /// Encoding-flavored counterpart of \c writeArtifact. Dispatches to
- /// \c writeTUSummaryEncoding or \c writeLUSummaryEncoding based on the
- /// active variant alternative.
- virtual llvm::Error writeArtifactEncoding(const ArtifactEncoding &E,
- llvm::StringRef Path) = 0;
-
- virtual llvm::Expected<LUSummaryEncoding>
- readLUSummaryEncoding(llvm::StringRef Path) = 0;
-
- virtual llvm::Error
- writeLUSummaryEncoding(const LUSummaryEncoding &SummaryEncoding,
- llvm::StringRef Path) = 0;
-
- virtual llvm::Expected<WPASuite> readWPASuite(llvm::StringRef Path) = 0;
-
- virtual llvm::Error writeWPASuite(const WPASuite &Suite,
- llvm::StringRef Path) = 0;
-
- /// Invokes \p Callback once for each analysis that has registered
- /// serialization support for this format.
- virtual void forEachRegisteredAnalysis(
- llvm::function_ref<void(llvm::StringRef Name, llvm::StringRef Desc)>
- Callback) const = 0;
-
-protected:
- // Helpers providing access to implementation details of basic data structures
- // for efficient serialization/deserialization.
-
- static EntityId makeEntityId(const size_t Index) { return EntityId(Index); }
-
- /// Constructs an empty WPASuite. Bypasses the private default constructor
- /// so that deserialization code can build a WPASuite incrementally.
- static WPASuite makeWPASuite() { return WPASuite(); }
-
-#define FIELD(CLASS, FIELD_NAME) \
- static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
- static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def"
-
- /// Per-format plugin registry for analysis result (de)serializers.
- ///
- /// Each concrete format (e.g. JSONFormat) instantiates this template once
- /// via a public \c using alias. Analysis authors register support with:
- ///
- /// \code
- /// static MyFormat::AnalysisResultRegistry::Add<MyAnalysisResult>
- /// Reg(serializeFn, deserializeFn);
- /// \endcode
- ///
- /// The serializer receives a \c const reference to \c MyAnalysisResult
- /// directly and the \c Add wrapper handles the downcast from \c
- /// AnalysisResult internally via virtual dispatch.
- ///
- /// \tparam FormatT Phantom type is needed to disambiguate \c llvm::Registry
- /// instantiations. \c llvm::Registry is keyed on the \c Entry type,
- /// so two formats sharing the same serializer/deserializer signatures
- /// would collide on the same registry without this parameter.
- template <class FormatT, class SerializerFn, class DeserializerFn>
- class AnalysisResultRegistryGenerator;
-
- template <class FormatT, class SerRet, class... SerArgs, class DesRet,
- class... DesArgs>
- class AnalysisResultRegistryGenerator<
- FormatT, llvm::function_ref<SerRet(const AnalysisResult &, SerArgs...)>,
- llvm::function_ref<DesRet(DesArgs...)>> {
-
- using DeserializerFn = DesRet (*)(DesArgs...);
-
- public:
- /// Abstract base type stored in \c llvm::Registry<Codec>.
- /// Subclasses override \c serialize() and \c deserialize() to
- /// dispatch to the plugin's concrete functions.
- ///
- /// There is one \c Codec type (and one \c llvm::Registry<Codec>) per
- /// format. All analysis-specific concrete subclasses for a given format
- /// register into that single registry. The \c FormatT phantom type
- /// parameter on the enclosing class ensures that different formats
- /// produce distinct \c Codec types and thus separate registries.
- struct Codec {
- virtual ~Codec() = default;
- virtual SerRet serialize(const AnalysisResult &, SerArgs...) const = 0;
- virtual DesRet deserialize(DesArgs...) const = 0;
- };
-
- template <class AnalysisResultT> struct Add {
- using TypedSerializerFn = SerRet (*)(const AnalysisResultT &, SerArgs...);
-
- static inline TypedSerializerFn SavedSerialize;
- static inline DeserializerFn SavedDeserialize;
-
- /// Takes the plugin's typed serializer and the deserializer, and
- /// inserts them into \c llvm::Registry<Codec>.
- Add(TypedSerializerFn TypedSerialize, DeserializerFn Deserialize) {
- /// Per-\c AnalysisResultT guard: each template instantiation gets
- /// its own \c static \c bool, so double-registration of the same
- /// analysis is caught even across translation units.
- static bool Registered = false;
- if (Registered) {
- ErrorBuilder::fatal("support is already registered for analysis: {0}",
- AnalysisResultT::analysisName());
- }
- Registered = true;
-
- /// The plugin's serializer and deserializer are captured in
- /// static inline members of the Add template so that the
- /// \c ConcreteCodec default constructor (required by \c llvm::Registry)
- /// can read them. They use raw function pointers to prevent dangling
- /// references to temporary stack variables during registration.
- ///
- /// Once read by the constructor, they are stored as instance members
- /// of \c ConcreteCodec rather than directly executed from the \c static
- /// \c inline class members. This prevents symbol visibility issues
- /// across shared library boundaries on Linux (where \c dlopen with \c
- /// RTLD_LOCAL can give the host and plugin separate copies of \c static
- /// \c inline members).
- SavedSerialize = TypedSerialize;
- SavedDeserialize = Deserialize;
-
- /// Concrete subclass of \c Codec for \c AnalysisResultT.
- /// The \c serialize() override performs the downcast from
- /// \c AnalysisResult to \c AnalysisResultT.
- struct ConcreteCodec final : Codec {
- TypedSerializerFn SerFn;
- DeserializerFn DesFn;
-
- ConcreteCodec() : SerFn(SavedSerialize), DesFn(SavedDeserialize) {}
-
- SerRet serialize(const AnalysisResult &Base,
- SerArgs... args) const override {
- return SerFn(static_cast<const AnalysisResultT &>(Base), args...);
- }
-
- DesRet deserialize(DesArgs... args) const override {
- return DesFn(args...);
- }
- };
-
- /// \c llvm::Registry stores the name as a \c StringRef, so the
- /// underlying string must be kept alive with a static declaration.
- static std::string NameStr =
- AnalysisResultT::analysisName().str().str();
-
- /// This performs the actual registration. It appends a factory for \c
- /// ConcreteCodec to the global \c llvm::Registry<Codec>. \c static
- /// ensures the `Registry::Add` object lives for the entire program,
- /// keeping its codec and node alive in the registry's linked list.
- [[maybe_unused]] static
- typename llvm::Registry<Codec>::template Add<ConcreteCodec>
- RegisterUsingCtorSideEffect(NameStr, "");
- }
- };
-
- /// Looks up the codec for \p Name by walking the registry list.
- static llvm::Expected<std::unique_ptr<Codec>>
- instantiate(const AnalysisName &Name) {
- for (const auto &E : llvm::Registry<Codec>::entries()) {
- if (E.getName() == Name.str()) {
- return E.instantiate();
- }
- }
- return ErrorBuilder::create(std::errc::invalid_argument,
- "no support registered for analysis: {0}",
- Name)
- .build();
- }
- };
-};
-
-template <class SerializerFn, class DeserializerFn> struct FormatInfoEntry {
- FormatInfoEntry(SummaryName ForSummary, SerializerFn Serialize,
- DeserializerFn Deserialize)
- : ForSummary(ForSummary), Serialize(Serialize), Deserialize(Deserialize) {
- }
- virtual ~FormatInfoEntry() = default;
-
- SummaryName ForSummary;
- SerializerFn Serialize;
- DeserializerFn Deserialize;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
deleted file mode 100644
index 664e9c6245546..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h
+++ /dev/null
@@ -1,89 +0,0 @@
-//===- SerializationFormatRegistry.h ----------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Registry for SerializationFormats, and some helper functions.
-//
-// To register some custom serialization format, you will need to add some
-// declarations and definitions.
-//
-// Insert this code to the header file:
-//
-// LLVM_DECLARE_REGISTRY(llvm::Registry<MyFormat::FormatInfo>)
-//
-// Insert this declaration to the MyFormat class:
-//
-// using FormatInfo = FormatInfoEntry<SerializerFn, DeserializerFn>;
-//
-// Insert this code to the cpp file:
-//
-// namespace clang::ssaf {
-// // NOLINTNEXTLINE(misc-use-internal-linkage)
-// volatile int MyFormatAnchorSource = 0;
-// } // namespace clang::ssaf
-// static SerializationFormatRegistry::Add<MyFormat>
-// RegisterFormat("MyFormat", "My awesome serialization format");
-// LLVM_DEFINE_REGISTRY(llvm::Registry<MyFormat::FormatInfo>)
-//
-// Then implement the formatter for the specific analysis and register the
-// format info for it:
-//
-// namespace {
-// using FormatInfo = MyFormat::FormatInfo;
-// struct MyAnalysisFormatInfo final : FormatInfo {
-// MyAnalysisFormatInfo() : FormatInfo{
-// SummaryName("MyAnalysis"),
-// serializeMyAnalysis,
-// deserializeMyAnalysis,
-// } {}
-// };
-// } // namespace
-//
-// static llvm::Registry<FormatInfo>::Add<MyAnalysisFormatInfo>
-// RegisterFormatInfo(
-// "MyAnalysisFormatInfo",
-// "The MyFormat format info implementation for MyAnalysis"
-// );
-//
-// Finally, extend the `AnchorSources` list in the force-linker header:
-// clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h:
-//
-// This anchor is used to force the linker to link the MyFormat registration.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
-#include "clang/Support/Compiler.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Registry.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace clang::ssaf {
-
-/// Check if a SerializationFormat was registered with a given name.
-bool isFormatRegistered(llvm::StringRef FormatName);
-
-/// Try to instantiate a SerializationFormat with a given name.
-/// This might return null if the construction of the desired
-/// SerializationFormat failed.
-/// It's a fatal error if there is no format registered with the name.
-std::unique_ptr<SerializationFormat> makeFormat(llvm::StringRef FormatName);
-
-/// Print the list of available serialization formats.
-void printAvailableFormats(llvm::raw_ostream &OS);
-
-// Registry for adding new SerializationFormat implementations.
-using SerializationFormatRegistry = llvm::Registry<SerializationFormat>;
-
-} // namespace clang::ssaf
-
-LLVM_DECLARE_REGISTRY(clang::ssaf::SerializationFormatRegistry)
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h
deleted file mode 100644
index b26e5fadc58c2..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h
+++ /dev/null
@@ -1,93 +0,0 @@
-//===- LUSummaryConsumer.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// LUSummaryConsumer constructs SummaryData objects by routing LUSummary entity
-// data to the corresponding SummaryDataBuilder objects.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/Error.h"
-#include <memory>
-#include <utility>
-
-namespace clang::ssaf {
-
-/// Consumes a LUSummary by dispatching its entity data to registered
-/// SummaryDataBuilders and returning the results in a SummaryDataStore.
-///
-/// Three consumption patterns are supported:
-/// - \c run() && — processes every analysis present in the
-/// LUSummary, silently skipping any whose data is
-/// absent or whose builder is not registered.
-/// Cannot fail, so it returns \c SummaryDataStore
-/// directly. Requires an rvalue consumer because
-/// this pattern exhausts all remaining data.
-/// - \c run(names) — processes a named subset; returns
-/// \c llvm::Expected<SummaryDataStore> and fails if
-/// any requested name has no data in the LUSummary
-/// or no registered builder.
-/// - \c run<DataTs...>() — type-safe variant of \c run(names) with the
-/// same error semantics and return type.
-///
-/// All patterns consume the underlying LUSummary data, so each analysis can
-/// only be retrieved once across all run() calls.
-class LUSummaryConsumer final {
-public:
- explicit LUSummaryConsumer(std::unique_ptr<LUSummary> LU)
- : LU(std::move(LU)) {}
-
- /// Processes all registered analyses in LUSummary and returns the results.
- /// Silently skips analyses with no data or no registered builder.
- ///
- /// Requires an rvalue consumer (call as \c std::move(Consumer).run()) because
- /// this pattern exhausts all remaining LUSummary data.
- [[nodiscard]] SummaryDataStore run() &&;
-
- /// Processes the named analyses and returns the results.
- ///
- /// Returns an error if any name has no data in the LUSummary or no
- /// registered builder.
- [[nodiscard]] llvm::Expected<SummaryDataStore>
- run(llvm::ArrayRef<SummaryName> Names);
-
- /// Processes analyses for each of the given types and returns the results.
- ///
- /// Returns an error if any type has no data in the LUSummary or no
- /// registered builder.
- template <typename... DataTs>
- [[nodiscard]] llvm::Expected<SummaryDataStore> run() {
- return run({DataTs::summaryName()...});
- }
-
-private:
- std::unique_ptr<LUSummary> LU;
-
- /// Iterator into LUSummary::Data — the map from SummaryName to entity data.
- using LUDataIterator = decltype(std::declval<LUSummary &>().Data)::iterator;
-
- /// Core build implementation. Instantiates the registered builder for the
- /// analysis at \p It, delivers all entities, finalizes, and returns the
- /// built data. Returns an error if no builder is registered. Erases the
- /// LUSummary entry on success.
- llvm::Expected<std::unique_ptr<SummaryData>> build(LUDataIterator It);
-
- /// Looks up \p SN in the LUSummary and delegates to the iterator overload.
- /// Returns an error if no data for \p SN exists or no builder is registered.
- llvm::Expected<std::unique_ptr<SummaryData>> build(const SummaryName &SN);
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h
deleted file mode 100644
index 83386a684181e..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h
+++ /dev/null
@@ -1,28 +0,0 @@
-//===- SummaryData.h --------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Base class for all whole-program analysis data built from
-// LUSummary data. Carries no query API — all analysis-specific methods live
-// on concrete subclasses.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATA_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATA_H
-
-namespace clang::ssaf {
-
-/// Base class for whole-program analysis data.
-class SummaryData {
-public:
- virtual ~SummaryData() = default;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATA_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h
deleted file mode 100644
index 343e98d46ce39..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h
+++ /dev/null
@@ -1,97 +0,0 @@
-//===- SummaryDataBuilder.h -------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines SummaryDataBuilderBase (abstract base known to the
-// registry and LUSummaryConsumer) and the typed intermediate template
-// SummaryDataBuilder<DataT, SummaryT> that concrete builders inherit from.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include <memory>
-
-namespace clang::ssaf {
-
-class LUSummaryConsumer;
-
-/// Abstract base class for all summary data builders.
-///
-/// Known to the registry and LUSummaryConsumer. Receives entities one at a
-/// time via \c addSummary(), is finalized via \c finalize(), and transfers
-/// ownership of the built data via \c takeData().
-class SummaryDataBuilderBase {
- friend class LUSummaryConsumer;
-
-public:
- virtual ~SummaryDataBuilderBase() = default;
-
-private:
- /// Called once per entity belonging to this builder's analysis.
- /// Takes ownership of the summary data.
- virtual void addSummary(EntityId Id,
- std::unique_ptr<EntitySummary> Summary) = 0;
-
- /// Called after all entities have been added.
- virtual void finalize() {}
-
- /// Transfers ownership of the built data. Called by LUSummaryConsumer after
- /// finalize(). The rvalue ref-qualifier enforces single use — the builder
- /// cannot be accessed after this call.
- virtual std::unique_ptr<SummaryData> takeData() && = 0;
-};
-
-/// Typed intermediate template that concrete builders inherit from.
-/// Concrete builders must implement the typed
-/// \c addSummary(EntityId, unique_ptr<SummaryT>) overload, and may override
-/// \c finalize() for any post-processing needed after all entities are added.
-template <typename DataT, typename SummaryT>
-class SummaryDataBuilder : public SummaryDataBuilderBase {
- static_assert(std::is_base_of_v<SummaryData, DataT>,
- "DataT must derive from SummaryData");
- static_assert(HasSummaryName_v<DataT>,
- "DataT must have a static summaryName() method");
- static_assert(std::is_base_of_v<EntitySummary, SummaryT>,
- "SummaryT must derive from EntitySummary");
-
- std::unique_ptr<DataT> Data;
-
-public:
- SummaryDataBuilder() : Data(std::make_unique<DataT>()) {}
-
- /// Returns the SummaryName of the data this builder produces.
- /// Used by SummaryDataBuilderRegistry::Add to derive the registry entry name.
- static SummaryName summaryName() { return DataT::summaryName(); }
-
-protected:
- /// Typed customization point — concrete builders override this.
- virtual void addSummary(EntityId Id, std::unique_ptr<SummaryT> Summary) = 0;
-
- DataT &getData() & { return *Data; }
-
-private:
- std::unique_ptr<SummaryData> takeData() && override {
- return std::move(Data);
- }
-
- /// Seals the base overload, downcasts, and dispatches to the typed overload.
- void addSummary(EntityId Id, std::unique_ptr<EntitySummary> Summary) final {
- addSummary(Id, std::unique_ptr<SummaryT>(
- static_cast<SummaryT *>(Summary.release())));
- }
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h
deleted file mode 100644
index a153eff950534..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h
+++ /dev/null
@@ -1,74 +0,0 @@
-//===- SummaryDataBuilderRegistry.h -----------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Registry for SummaryDataBuilders.
-//
-// To register a builder, add a static Add<BuilderT> in the builder's
-// translation unit:
-//
-// static SummaryDataBuilderRegistry::Add<MyDataBuilder>
-// Registered("Data builder for MyAnalysis");
-//
-// The registry entry name is derived automatically from
-// MyDataBuilder::summaryName(), which returns MyData::summaryName().
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilder.h"
-#include "llvm/Support/Registry.h"
-#include <memory>
-#include <string>
-
-LLVM_DECLARE_REGISTRY(llvm::Registry<clang::ssaf::SummaryDataBuilderBase>)
-
-namespace clang::ssaf {
-
-/// Registry for SummaryDataBuilder implementations.
-///
-/// Provides an Add helper that derives the registry entry name from
-/// BuilderT::summaryName(), eliminating the possibility of registering a
-/// builder under the wrong name.
-class SummaryDataBuilderRegistry {
- using RegistryT = llvm::Registry<SummaryDataBuilderBase>;
-
- SummaryDataBuilderRegistry() = delete;
-
-public:
- /// Registers \p BuilderT under the name returned by
- /// \c BuilderT::summaryName(). Only a description is required.
- ///
- /// \c Add objects must be declared \c static at namespace scope — they
- /// register an entry in a global linked list on construction and are
- /// not copyable or movable.
- template <typename BuilderT> struct Add {
- explicit Add(llvm::StringRef Desc)
- : Name(BuilderT::summaryName().str().str()), Node(Name, Desc) {}
-
- Add(const Add &) = delete;
- Add &operator=(const Add &) = delete;
-
- private:
- std::string Name;
- RegistryT::Add<BuilderT> Node;
- };
-
- /// Returns true if a builder is registered under \p Name.
- static bool contains(llvm::StringRef Name);
-
- /// Instantiates the builder registered under \p Name, or returns nullptr
- /// if no such builder is registered.
- static std::unique_ptr<SummaryDataBuilderBase>
- instantiate(llvm::StringRef Name);
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h
deleted file mode 100644
index 3261085f8d5a2..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataStore.h
+++ /dev/null
@@ -1,115 +0,0 @@
-//===- SummaryDataStore.h ---------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Owns a collection of SummaryData objects keyed by SummaryName.
-// Produced by LUSummaryConsumer::run() variants.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryData.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "llvm/Support/Error.h"
-#include <map>
-#include <memory>
-
-namespace clang::ssaf {
-
-class LUSummaryConsumer;
-
-/// Owns a collection of SummaryData objects keyed by SummaryName.
-/// Produced by LUSummaryConsumer::run() variants.
-class SummaryDataStore {
- friend class LUSummaryConsumer;
-
- std::map<SummaryName, std::unique_ptr<SummaryData>> Data;
-
-public:
- /// Returns true if data for \p Name is stored.
- [[nodiscard]] bool contains(const SummaryName &Name) const {
- return Data.find(Name) != Data.end();
- }
-
- /// Returns true if data for \p DataT is stored.
- template <typename DataT> [[nodiscard]] bool contains() const {
- static_assert(std::is_base_of_v<SummaryData, DataT>,
- "DataT must derive from SummaryData");
- static_assert(HasSummaryName_v<DataT>,
- "DataT must have a static summaryName() method");
-
- return contains(DataT::summaryName());
- }
-
- /// Returns a reference to the data for \p DataT, or an error if
- /// no data for \p DataT is stored.
- template <typename DataT> [[nodiscard]] llvm::Expected<DataT &> get() {
- static_assert(std::is_base_of_v<SummaryData, DataT>,
- "DataT must derive from SummaryData");
- static_assert(HasSummaryName_v<DataT>,
- "DataT must have a static summaryName() method");
-
- auto Result = get(DataT::summaryName());
- if (!Result) {
- return Result.takeError();
- }
- return static_cast<DataT &>(*Result);
- }
-
- /// Returns a reference to the data for \p Name, or an error if
- /// no data for \p Name is stored.
- [[nodiscard]] llvm::Expected<SummaryData &> get(const SummaryName &Name) {
- auto It = Data.find(Name);
- if (It == Data.end()) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- "no data for analysis '{0}' in store",
- Name.str())
- .build();
- }
- return *It->second;
- }
-
- /// Transfers ownership of the data for \p DataT to the caller, or returns
- /// an error if no data for \p DataT is stored.
- template <typename DataT>
- [[nodiscard]] llvm::Expected<std::unique_ptr<DataT>> take() {
- static_assert(std::is_base_of_v<SummaryData, DataT>,
- "DataT must derive from SummaryData");
- static_assert(HasSummaryName_v<DataT>,
- "DataT must have a static summaryName() method");
-
- auto Result = take(DataT::summaryName());
- if (!Result) {
- return Result.takeError();
- }
- return std::unique_ptr<DataT>(static_cast<DataT *>(Result->release()));
- }
-
- /// Transfers ownership of the data for \p Name to the caller, or returns
- /// an error if no data for \p Name is stored.
- [[nodiscard]] llvm::Expected<std::unique_ptr<SummaryData>>
- take(const SummaryName &Name) {
- auto It = Data.find(Name);
- if (It == Data.end()) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- "no data for analysis '{0}' in store",
- Name.str())
- .build();
- }
- auto Ptr = std::move(It->second);
- Data.erase(It);
- return std::move(Ptr);
- }
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h
deleted file mode 100644
index c6bf6b6fcd4bb..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataTraits.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- SummaryDataTraits.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Type traits for SummaryData subclasses.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include <type_traits>
-
-namespace clang::ssaf {
-
-/// Type trait that checks whether \p T has a static \c summaryName() method
-/// returning \c SummaryName. Used to enforce the convention on SummaryData
-/// subclasses at instantiation time.
-///
-/// The expression \c T::summaryName() is only well-formed for static methods —
-/// calling a non-static member without an object is ill-formed and causes the
-/// partial specialization to be discarded via SFINAE, so non-static overloads
-/// are correctly rejected.
-template <typename T, typename = void>
-struct HasSummaryName : std::false_type {};
-
-template <typename T>
-struct HasSummaryName<T, std::void_t<decltype(T::summaryName())>>
- : std::is_same<decltype(T::summaryName()), SummaryName> {};
-
-template <typename T>
-inline constexpr bool HasSummaryName_v = HasSummaryName<T>::value;
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h
deleted file mode 100644
index 2cce23766b026..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h
+++ /dev/null
@@ -1,210 +0,0 @@
-//===- ErrorBuilder.h - Fluent API for contextual errors --------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the ErrorBuilder class, which provides a fluent API for
-// constructing contextual error messages with layered context information.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_ERRORBUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_ERRORBUILDER_H
-
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FormatVariadic.h"
-#include <optional>
-#include <string>
-#include <system_error>
-#include <vector>
-
-namespace clang::ssaf {
-
-/// Fluent API for constructing contextual errors.
-///
-/// ErrorBuilder allows building error messages with layered context
-/// information. Context is added innermost to outermost, and the final
-/// error message presents the context in reverse order (outermost first).
-///
-/// Example usage:
-/// \code
-/// return ErrorBuilder::create(std::errc::invalid_argument,
-/// "invalid value {0}", value)
-/// .context("processing field '{0}'", fieldName)
-/// .context("reading configuration")
-/// .build();
-/// \endcode
-class ErrorBuilder {
- std::error_code Code;
- std::vector<std::string> ContextStack;
-
- explicit ErrorBuilder(std::error_code EC) : Code(EC) {}
-
- void pushContext(std::string Msg) {
- if (!Msg.empty()) {
- ContextStack.push_back(std::move(Msg));
- }
- }
-
- template <typename... Args>
- static std::string formatErrorMessage(const char *Fmt, Args &&...ArgVals) {
- return llvm::formatv(Fmt, std::forward<Args>(ArgVals)...).str();
- }
-
- template <typename... Args>
- void addFormattedContext(const char *Fmt, Args &&...ArgVals) {
- pushContext(formatErrorMessage(Fmt, std::forward<Args>(ArgVals)...));
- }
-
-public:
- /// Create an ErrorBuilder with an error code and formatted message.
- ///
- /// \param EC The error code for this error.
- /// \param Fmt Format string for the error message (using llvm::formatv).
- /// \param ArgVals Arguments for the format string.
- /// \returns A new ErrorBuilder with the initial error message.
- ///
- /// Example:
- /// \code
- /// return ErrorBuilder::create(std::errc::invalid_argument,
- /// "invalid value: {0}", 42)
- /// .build();
- /// \endcode
- template <typename... Args>
- static ErrorBuilder create(std::error_code EC, const char *Fmt,
- Args &&...ArgVals) {
- ErrorBuilder Builder(EC);
- Builder.addFormattedContext(Fmt, std::forward<Args>(ArgVals)...);
- return Builder;
- }
-
- /// Convenience overload that accepts std::errc instead of std::error_code.
- ///
- /// \param EC The error condition for this error.
- /// \param Fmt Format string for the error message.
- /// \param ArgVals Arguments for the format string.
- /// \returns A new ErrorBuilder with the initial error message.
- template <typename... Args>
- static ErrorBuilder create(std::errc EC, const char *Fmt, Args &&...ArgVals) {
- return create(std::make_error_code(EC), Fmt,
- std::forward<Args>(ArgVals)...);
- }
-
- /// Wrap an existing error and optionally add context.
- ///
- /// Extracts the error code and message(s) from the given error. If multiple
- /// errors are joined (via llvm::joinErrors), their messages are combined
- /// using " + " separator.
- ///
- /// \param E The error to wrap. Must be a failure (cannot be success).
- /// \returns A new ErrorBuilder containing the wrapped error information.
- ///
- /// \pre E must evaluate to true (i.e., must be a failure). Wrapping
- /// Error::success() is a programming error and will trigger an
- /// assertion failure in debug builds.
- ///
- /// Example:
- /// \code
- /// if (auto Err = foo())
- /// return ErrorBuilder::wrap(std::move(Err))
- /// .context("while processing file")
- /// .build();
- /// \endcode
- static ErrorBuilder wrap(llvm::Error E);
-
- /// Add context information as a plain string.
- ///
- /// Empty strings are ignored and not added to the context stack.
- ///
- /// \param Msg Context message to add. Must be a null-terminated string.
- /// \returns Reference to this ErrorBuilder for method chaining.
- ///
- /// Example:
- /// \code
- /// return ErrorBuilder::create(...)
- /// .context("reading configuration file")
- /// .build();
- /// \endcode
- ErrorBuilder &context(const char *Msg);
-
- /// Add context information with formatted string.
- ///
- /// Uses llvm::formatv for formatting. Empty messages (after formatting)
- /// are ignored and not added to the context stack.
- ///
- /// \param Fmt Format string (using llvm::formatv syntax).
- /// \param ArgVals Arguments for the format string.
- /// \returns Reference to this ErrorBuilder for method chaining.
- ///
- /// Example:
- /// \code
- /// return ErrorBuilder::create(...)
- /// .context("processing field '{0}'", fieldName)
- /// .context("at line {0}, column {1}", line, col)
- /// .build();
- /// \endcode
- template <typename... Args>
- ErrorBuilder &context(const char *Fmt, Args &&...ArgVals) {
- addFormattedContext(Fmt, std::forward<Args>(ArgVals)...);
- return *this;
- }
-
- /// Build and return the final error.
- ///
- /// Constructs an llvm::Error with all accumulated context. The context
- /// is presented in reverse order: most recent context first, original
- /// error message last. Each context layer is separated by a newline.
- ///
- /// \returns An llvm::Error containing the error code and formatted message.
- /// Even if no context was added (empty context stack), an error
- /// with the stored error code is returned.
- ///
- /// \pre The ErrorBuilder must have been created via \c create() or \c wrap().
- /// Constructing an ErrorBuilder directly is not supported.
- ///
- /// Example output:
- /// \code
- /// ErrorBuilder::create(errc::invalid_argument, "value is 42")
- /// .context("processing field 'age'")
- /// .context("reading config")
- /// .build();
- ///
- /// // Produces:
- /// // "reading config
- /// // processing field 'age'
- /// // value is 42"
- /// \endcode
- llvm::Error build() const;
-
- /// Report a fatal error with formatted message and terminate execution.
- ///
- /// Combines llvm::formatv and llvm::report_fatal_error. This is a static
- /// utility method for reporting unrecoverable errors that indicate bugs
- /// or corrupted data.
- ///
- /// \param Fmt Format string for the error message (using llvm::formatv).
- /// \param ArgVals Arguments for the format string.
- ///
- /// \pre \p Fmt must be a valid llvm::formatv format string with the correct
- /// number and types of arguments. An invalid format string is undefined
- /// behaviour.
- ///
- /// Example:
- /// \code
- /// ErrorBuilder::fatal("Entity {0} with {1} linkage already exists",
- /// entityId, linkageType);
- /// \endcode
- template <typename... Args>
- [[noreturn]] static void fatal(const char *Fmt, Args &&...ArgVals) {
- llvm::report_fatal_error(llvm::StringRef(formatErrorMessage(
- Fmt, std::forward<Args>(ArgVals)...)),
- false);
- }
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_ERRORBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h
deleted file mode 100644
index 437152d43f425..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h
+++ /dev/null
@@ -1,93 +0,0 @@
-//===- FormatProviders.h - llvm::formatv support for SSAF types -*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file provides llvm::format_provider specialisations for SSAF model
-// types, enabling them to be used directly with llvm::formatv and ErrorBuilder.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_FORMATPROVIDERS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_FORMATPROVIDERS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "llvm/Support/FormatProviders.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-
-template <> struct format_provider<clang::ssaf::EntityId> {
- static void format(const clang::ssaf::EntityId &Val, raw_ostream &OS,
- StringRef Style) {
- OS << Val;
- }
-};
-
-template <> struct format_provider<clang::ssaf::EntityLinkageType> {
- static void format(clang::ssaf::EntityLinkageType Val, raw_ostream &OS,
- StringRef Style) {
- OS << Val;
- }
-};
-
-template <> struct format_provider<clang::ssaf::EntityLinkage> {
- static void format(clang::ssaf::EntityLinkage Val, raw_ostream &OS,
- StringRef Style) {
- OS << Val;
- }
-};
-
-template <> struct format_provider<clang::ssaf::BuildNamespaceKind> {
- static void format(clang::ssaf::BuildNamespaceKind Val, raw_ostream &OS,
- StringRef Style) {
- OS << Val;
- }
-};
-
-template <> struct format_provider<clang::ssaf::BuildNamespace> {
- static void format(const clang::ssaf::BuildNamespace &Val, raw_ostream &OS,
- StringRef Style) {
- OS << Val;
- }
-};
-
-template <> struct format_provider<clang::ssaf::NestedBuildNamespace> {
- static void format(const clang::ssaf::NestedBuildNamespace &Val,
- raw_ostream &OS, StringRef Style) {
- OS << Val;
- }
-};
-
-template <> struct format_provider<clang::ssaf::EntityName> {
- static void format(const clang::ssaf::EntityName &Val, raw_ostream &OS,
- StringRef Style) {
- OS << Val;
- }
-};
-
-template <> struct format_provider<clang::ssaf::SummaryName> {
- static void format(const clang::ssaf::SummaryName &Val, raw_ostream &OS,
- StringRef Style) {
- OS << Val;
- }
-};
-
-template <> struct format_provider<clang::ssaf::AnalysisName> {
- static void format(const clang::ssaf::AnalysisName &Val, raw_ostream &OS,
- StringRef Style) {
- OS << Val;
- }
-};
-
-} // namespace llvm
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_SUPPORT_FORMATPROVIDERS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h
deleted file mode 100644
index e6c8a4716eaf2..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//===- EntitySummary.h ------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_ENTITYSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_ENTITYSUMMARY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include <type_traits>
-
-namespace clang::ssaf {
-
-/// Base class for analysis-specific summary data.
-class EntitySummary {
-public:
- virtual ~EntitySummary() = default;
- virtual SummaryName getSummaryName() const = 0;
-};
-
-template <typename Derived>
-using DerivesFromEntitySummary =
- std::enable_if_t<std::is_base_of_v<EntitySummary, Derived>>;
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_ENTITYSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
deleted file mode 100644
index f0ef920a719c8..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h
+++ /dev/null
@@ -1,56 +0,0 @@
-//===- ExtractorRegistry.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Registry for TUSummaryExtractors, and some helper functions.
-// To register some custom extractor, insert this code:
-//
-// namespace clang::ssaf {
-// // NOLINTNEXTLINE(misc-use-internal-linkage)
-// volatile int MyExtractorAnchorSource = 0;
-// } // namespace clang::ssaf
-// static TUSummaryExtractorRegistry::Add<MyExtractor>
-// X("MyExtractor", "My awesome extractor");
-//
-// Finally, extend the `AnchorSources` list in the force-linker header:
-// clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h:
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
-#include "clang/Support/Compiler.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Registry.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace clang::ssaf {
-
-/// Check if a TUSummaryExtractor was registered with a given name.
-bool isTUSummaryExtractorRegistered(llvm::StringRef SummaryName);
-
-/// Try to instantiate a TUSummaryExtractor with a given name.
-/// This might return null if the construction of the desired TUSummaryExtractor
-/// failed.
-/// It's a fatal error if there is no extractor registered with the name.
-std::unique_ptr<TUSummaryExtractor>
-makeTUSummaryExtractor(llvm::StringRef SummaryName, TUSummaryBuilder &Builder);
-
-/// Print the list of available TUSummaryExtractors.
-void printAvailableTUSummaryExtractors(llvm::raw_ostream &OS);
-
-// Registry for adding new TUSummaryExtractor implementations.
-using TUSummaryExtractorRegistry =
- llvm::Registry<TUSummaryExtractor, TUSummaryBuilder &>;
-
-} // namespace clang::ssaf
-
-LLVM_DECLARE_REGISTRY(clang::ssaf::TUSummaryExtractorRegistry)
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h
deleted file mode 100644
index c5cadce439ba9..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//===- TUSummary.h ----------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "llvm/TargetParser/Triple.h"
-#include <map>
-#include <memory>
-
-namespace clang::ssaf {
-
-/// Data extracted for a given translation unit and for a given set of analyses.
-class TUSummary {
- /// Target triple of the translation unit.
- llvm::Triple TargetTriple;
-
- /// Identifies the translation unit.
- BuildNamespace TUNamespace;
-
- EntityIdTable IdTable;
-
- std::map<EntityId, EntityLinkage> LinkageTable;
-
- std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>
- Data;
-
-public:
- TUSummary(llvm::Triple TargetTriple, BuildNamespace TUNamespace)
- : TargetTriple(std::move(TargetTriple)),
- TUNamespace(std::move(TUNamespace)) {}
-
- friend class SerializationFormat;
- friend class TestFixture;
- friend class TUSummaryBuilder;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
deleted file mode 100644
index 38bd60718ed9c..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h
+++ /dev/null
@@ -1,81 +0,0 @@
-//===- TUSummaryBuilder.h ---------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include <memory>
-#include <utility>
-
-namespace clang::ssaf {
-
-class EntityName;
-class SSAFOptions;
-class TUSummary;
-
-class TUSummaryBuilder {
-public:
- TUSummaryBuilder(TUSummary &Summary, const SSAFOptions &Options)
- : Summary(Summary), Options(Options) {}
-
- EntityId addEntity(const EntityName &EN, EntityLinkageType Linkage);
-
- /// Associate the \p Data \c EntitySummary with the \p Entity.
- /// This consumes the \p Data only if \p Entity wasn't associated yet with the
- /// same kind of \c EntitySummary.
- /// \returns a pointer to the \c EntitySummary and whether it inserted or not.
- template <typename ConcreteEntitySummary,
- DerivesFromEntitySummary<ConcreteEntitySummary> * = nullptr>
- std::pair<EntitySummary *, bool>
- addSummary(EntityId Entity, std::unique_ptr<ConcreteEntitySummary> &&Data);
-
- /// \returns the \c SSAFOptions of this builder.
- const SSAFOptions &getOptions() const { return Options; }
-
-private:
- TUSummary &Summary;
- const SSAFOptions &Options;
-
- std::pair<EntitySummary *, bool>
- addSummaryImpl(EntityId Entity, std::unique_ptr<EntitySummary> &&Data);
-};
-
-// Why is this a template?
-//
-// We use template here to avoid an implicit conversion from
-// `std::unique_ptr<ConcreteEntitySummary>` to `std::unique_ptr<EntitySummary>`
-// because constructing that implicit temporary would unconditionally "consume"
-// the Data. This would make it impossible to recover from the call-site the
-// Data you pass in even if no insertion happens.
-template <typename ConcreteEntitySummary,
- DerivesFromEntitySummary<ConcreteEntitySummary> *>
-std::pair<EntitySummary *, bool>
-TUSummaryBuilder::addSummary(EntityId Entity,
- std::unique_ptr<ConcreteEntitySummary> &&Data) {
- // Prepare a unique_ptr of the base type to avoid implicit conversions at the
- // call-site.
- std::unique_ptr<EntitySummary> TypeErasedData = std::move(Data);
-
- // This only moves (consumes) TypeErasedData if insertion happened.
- // Otherwise it doesn't touch the `TypeErasedData`.
- auto [It, Inserted] = addSummaryImpl(Entity, std::move(TypeErasedData));
-
- // Move it back on failure to keep the `Data` unconsumed.
- if (!Inserted) {
- Data = std::unique_ptr<ConcreteEntitySummary>(
- static_cast<ConcreteEntitySummary *>(TypeErasedData.release()));
- }
- return {It, Inserted};
-}
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
deleted file mode 100644
index b943748873821..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//===- TUSummaryExtractor.h -------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
-
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/Decl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include <optional>
-
-namespace clang::ssaf {
-class SSAFOptions;
-class TUSummaryBuilder;
-
-class TUSummaryExtractor : public ASTConsumer {
-public:
- explicit TUSummaryExtractor(TUSummaryBuilder &Builder)
- : SummaryBuilder(Builder) {}
-
- /// Creates EntityName from the Decl, registers the entity, and sets its
- /// linkage atomically.
- /// \returns the EntityId, or std::nullopt if EntityName creation fails.
- std::optional<EntityId> addEntity(const NamedDecl *D);
-
- /// Creates EntityName for the return value of \p FD, registers the entity,
- /// and sets its linkage atomically.
- /// \returns the EntityId, or std::nullopt if EntityName creation fails.
- std::optional<EntityId> addEntityForReturn(const FunctionDecl *FD);
-
- /// \returns the \c SSAFOptions of the builder.
- const SSAFOptions &getOptions() const;
-
-protected:
- TUSummaryBuilder &SummaryBuilder;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h
deleted file mode 100644
index 1a9a5de76ffab..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h
+++ /dev/null
@@ -1,60 +0,0 @@
-//===- AnalysisBase.h -------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Minimal common base for SummaryAnalysisBase and DerivedAnalysisBase.
-// Carries the identity (getAnalysisName()) and dependency list
-// (getDependencyNames()) shared by every analysis regardless of kind.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include <vector>
-
-namespace clang::ssaf {
-
-class AnalysisDriver;
-class AnalysisResult;
-class DerivedAnalysisBase;
-class SummaryAnalysisBase;
-
-/// Minimal common base for both analysis kinds.
-///
-/// Not subclassed directly -- use SummaryAnalysis<...> or
-/// DerivedAnalysis<...> instead.
-class AnalysisBase {
- friend class AnalysisDriver;
- friend class DerivedAnalysisBase;
- friend class SummaryAnalysisBase;
-
- enum class Kind { Summary, Derived };
- Kind TheKind;
-
-protected:
- explicit AnalysisBase(Kind K) : TheKind(K) {}
-
-public:
- virtual ~AnalysisBase() = default;
-
- /// Name of this analysis. Equal to ResultT::analysisName() in both typed
- /// intermediates.
- virtual AnalysisName getAnalysisName() const = 0;
-
- /// AnalysisNames of all AnalysisResult dependencies.
- virtual const std::vector<AnalysisName> &getDependencyNames() const = 0;
-
- /// Transfers ownership of the built result. Called once after finalize().
- /// The rvalue ref-qualifier enforces single use.
- virtual std::unique_ptr<AnalysisResult> takeResult() && = 0;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h
deleted file mode 100644
index 156d8e806bd0f..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//===- AnalysisDriver.h -----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Central orchestrator for whole-program analysis. Takes ownership of an
-// LUSummary, drives all registered analyses in topological dependency order,
-// and returns a WPASuite.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/Error.h"
-#include <memory>
-#include <vector>
-
-namespace clang::ssaf {
-
-class AnalysisBase;
-class DerivedAnalysisBase;
-class SummaryAnalysisBase;
-
-/// Orchestrates whole-program analysis over an LUSummary.
-///
-/// Three run() patterns are supported:
-/// - run() && -- all registered analyses in topological dependency
-/// order. Returns an error if any registered analysis
-/// has no matching entity data in the LUSummary.
-/// Requires an rvalue driver because this exhausts the
-/// LUSummary.
-/// - run(names) -- named subset plus transitive dependencies; returns
-/// Expected and fails if any listed name has no
-/// registered analysis or missing entity data.
-/// - run<ResultTs..> -- type-safe variant of run(names).
-class AnalysisDriver final {
-public:
- explicit AnalysisDriver(std::unique_ptr<LUSummary> LU);
-
- /// Runs all registered analyses in topological dependency order.
- /// Returns an error if any registered analysis has no matching entity data
- /// in the LUSummary.
- ///
- /// Requires an rvalue driver (std::move(Driver).run()) because this
- /// exhausts all remaining LUSummary data.
- [[nodiscard]] llvm::Expected<WPASuite> run() &&;
-
- /// Runs only the named analyses (plus their transitive dependencies).
- ///
- /// Returns an error if any listed AnalysisName has no registered analysis
- /// or if a required SummaryAnalysis has no matching entity data in the
- /// LUSummary. The EntityIdTable is copied (not moved) so the driver remains
- /// usable for subsequent calls.
- [[nodiscard]] llvm::Expected<WPASuite>
- run(llvm::ArrayRef<AnalysisName> Names) const;
-
- /// Type-safe variant of run(names). Derives names from
- /// ResultTs::analysisName().
- template <typename... ResultTs>
- [[nodiscard]] llvm::Expected<WPASuite> run() const {
- return run({ResultTs::analysisName()...});
- }
-
-private:
- std::unique_ptr<LUSummary> LU;
-
- /// Instantiates all analyses reachable from \p Roots (plus transitive
- /// dependencies) and returns them in topological order via a single DFS.
- /// Reports an error on unregistered names or cycles.
- static llvm::Expected<std::vector<std::unique_ptr<AnalysisBase>>>
- toposort(llvm::ArrayRef<AnalysisName> Roots);
-
- /// Executes a topologically-sorted analysis list and returns a WPASuite.
- /// \p IdTable is moved into the returned WPASuite.
- llvm::Expected<WPASuite>
- execute(EntityIdTable IdTable,
- llvm::ArrayRef<std::unique_ptr<AnalysisBase>> Sorted) const;
-
- llvm::Error executeSummaryAnalysis(SummaryAnalysisBase &Summary,
- WPASuite &Suite) const;
-
- llvm::Error executeDerivedAnalysis(DerivedAnalysisBase &Derived,
- WPASuite &Suite) const;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h
deleted file mode 100644
index 32f76e73b14e0..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===- AnalysisName.h -------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Strong typedef identifying a whole-program analysis and its result type.
-// Distinct from SummaryName, which identifies per-entity EntitySummary types.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <string>
-
-namespace clang::ssaf {
-
-/// Uniquely identifies a whole-program analysis and the AnalysisResult it
-/// produces. Used as the key in WPASuite and AnalysisRegistry.
-///
-/// Distinct from SummaryName, which is used by EntitySummary types for routing
-/// through the LUSummary.
-class AnalysisName {
-public:
- explicit AnalysisName(std::string Name) : Name(std::move(Name)) {}
-
- bool operator==(const AnalysisName &Other) const {
- return Name == Other.Name;
- }
- bool operator!=(const AnalysisName &Other) const { return !(*this == Other); }
- bool operator<(const AnalysisName &Other) const { return Name < Other.Name; }
-
- /// Explicit conversion to the underlying string representation.
- llvm::StringRef str() const { return Name; }
-
-private:
- std::string Name;
-};
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const AnalysisName &AN);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
deleted file mode 100644
index f3e0327227889..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h
+++ /dev/null
@@ -1,111 +0,0 @@
-//===- AnalysisRegistry.h ---------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Unified registry for both SummaryAnalysis and DerivedAnalysis subclasses.
-//
-// To register an analysis, add a static Add<AnalysisT> and an anchor source
-// in its translation unit, then add the anchor source to the `AnchorSources`
-// list in the relevant force-linker header:
-//
-// // MyAnalysis.cpp
-// static AnalysisRegistry::Add<MyAnalysis>
-// Registered("One-line description of MyAnalysis");
-//
-// namespace clang::ssaf {
-// // NOLINTNEXTLINE(misc-use-internal-linkage)
-// volatile int MyAnalysisAnchorSource = 0;
-// } // namespace clang::ssaf
-//
-// // Extend SSAFBuiltinForceLinker.h (or the relevant force-linker header)
-//
-// The registry entry name is derived automatically from
-// MyAnalysis::analysisName(), so name-mismatch bugs are impossible.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/Registry.h"
-#include <memory>
-#include <string>
-#include <vector>
-
-LLVM_DECLARE_REGISTRY(llvm::Registry<clang::ssaf::AnalysisBase>)
-
-namespace clang::ssaf {
-
-/// Unified registry for SummaryAnalysis and DerivedAnalysis implementations.
-///
-/// Internally uses a single llvm::Registry<AnalysisBase>. The correct kind
-/// is carried by the AnalysisBase::TheKind tag set in each subclass
-/// constructor.
-class AnalysisRegistry {
- using RegistryT = llvm::Registry<AnalysisBase>;
-
- AnalysisRegistry() = delete;
-
-public:
- /// Registers AnalysisT with the unified registry.
- ///
- /// The registry entry name is derived automatically from
- /// AnalysisT::ResultType::analysisName(), so name-mismatch bugs are
- /// impossible.
- ///
- /// Add objects must be declared static at namespace scope.
- template <typename AnalysisT> struct Add {
- static_assert(std::is_base_of_v<SummaryAnalysisBase, AnalysisT> ||
- std::is_base_of_v<DerivedAnalysisBase, AnalysisT>,
- "AnalysisT must derive from SummaryAnalysis<...> or "
- "DerivedAnalysis<...>");
-
- explicit Add(llvm::StringRef Desc)
- : Name(AnalysisT::ResultType::analysisName().str().str()),
- Node(Name, Desc) {
- if (contains(AnalysisT::ResultType::analysisName())) {
- ErrorBuilder::fatal("duplicate analysis registration for '{0}'", Name);
- }
- getAnalysisNames().push_back(AnalysisT::ResultType::analysisName());
- }
-
- Add(const Add &) = delete;
- Add &operator=(const Add &) = delete;
-
- private:
- std::string Name;
- RegistryT::Add<AnalysisT> Node;
- };
-
- /// Returns true if an analysis is registered under \p Name.
- static bool contains(const AnalysisName &Name);
-
- /// Returns the names of all registered analyses.
- static const std::vector<AnalysisName> &names();
-
- /// Instantiates the analysis registered under \p Name, or returns an error
- /// if no such analysis is registered.
- static llvm::Expected<std::unique_ptr<AnalysisBase>>
- instantiate(const AnalysisName &Name);
-
-private:
- /// Returns the global list of registered analysis names.
- ///
- /// Uses a function-local static to avoid static initialization order
- /// fiasco: Add<T> objects in other translation units may push names before
- /// a plain static data member could be constructed.
- static std::vector<AnalysisName> &getAnalysisNames();
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h
deleted file mode 100644
index 07d1f0549a9ee..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h
+++ /dev/null
@@ -1,30 +0,0 @@
-//===- AnalysisResult.h -----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Base class for all whole-program analysis results produced by AnalysisDriver.
-// Concrete subclasses carry a static analysisName().
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
-
-namespace clang::ssaf {
-
-/// Base class for whole-program analysis results.
-///
-/// Concrete subclasses must provide:
-/// static AnalysisName analysisName();
-class AnalysisResult {
-public:
- virtual ~AnalysisResult() = default;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h
deleted file mode 100644
index 78df3b35648c2..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- AnalysisTraits.h -----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Type traits for AnalysisResult subclasses.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include <type_traits>
-
-namespace clang::ssaf {
-
-/// Type trait that checks whether \p T has a static \c analysisName() method
-/// returning \c AnalysisName. Used to enforce the convention on AnalysisResult
-/// subclasses and analysis classes at instantiation time.
-template <typename T, typename = void>
-struct HasAnalysisName : std::false_type {};
-
-template <typename T>
-struct HasAnalysisName<T, std::void_t<decltype(T::analysisName())>>
- : std::is_same<decltype(T::analysisName()), AnalysisName> {};
-
-template <typename T>
-inline constexpr bool HasAnalysisName_v = HasAnalysisName<T>::value;
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h
deleted file mode 100644
index ff9470e0a2284..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h
+++ /dev/null
@@ -1,133 +0,0 @@
-//===- DerivedAnalysis.h ----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines DerivedAnalysisBase (type-erased base known to AnalysisDriver) and
-// the typed intermediate DerivedAnalysis<ResultT, DepResultTs...> that
-// concrete analyses inherit from.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h"
-#include "llvm/Support/Error.h"
-#include <map>
-#include <memory>
-#include <vector>
-
-namespace clang::ssaf {
-
-class AnalysisDriver;
-class AnalysisRegistry;
-
-/// Type-erased base for derived analyses. Known to AnalysisDriver.
-///
-/// Not subclassed directly -- use DerivedAnalysis<ResultT, DepResultTs...>.
-/// A derived analysis consumes previously produced AnalysisResult objects
-/// and computes a new one via an initialize/step/finalize lifecycle.
-class DerivedAnalysisBase : public AnalysisBase {
- friend class AnalysisDriver;
-
-protected:
- DerivedAnalysisBase() : AnalysisBase(AnalysisBase::Kind::Derived) {}
-
-private:
- /// Called once with the dependency results before the step() loop.
- ///
- /// \param DepResults Immutable results of all declared dependencies, keyed
- /// by AnalysisName. Guaranteed to contain every name
- /// returned by dependencyNames().
- virtual llvm::Error initialize(
- const std::map<AnalysisName, const AnalysisResult *> &DepResults) = 0;
-
- /// Performs one pass.
- /// Returns true if another pass is needed; false when converged.
- virtual llvm::Expected<bool> step() = 0;
-
- /// Called after the step() loop converges. Default is a no-op.
- virtual llvm::Error finalize() { return llvm::Error::success(); }
-};
-
-/// Typed intermediate that concrete derived analyses inherit from.
-///
-/// Concrete analyses must implement:
-/// llvm::Error initialize(const DepResultTs &...) override;
-/// llvm::Expected<bool> step() override;
-/// and may override finalize().
-///
-/// Dependencies are fixed for the lifetime of the analysis: initialize()
-/// binds them once, step() is called until it returns false, and
-/// finalize() post-processes after convergence.
-template <typename ResultT, typename... DepResultTs>
-class DerivedAnalysis : public DerivedAnalysisBase {
- static_assert(std::is_base_of_v<AnalysisResult, ResultT>,
- "ResultT must derive from AnalysisResult");
- static_assert(HasAnalysisName_v<ResultT>,
- "ResultT must have a static analysisName() method");
- static_assert((std::is_base_of_v<AnalysisResult, DepResultTs> && ...),
- "Every DepResultT must derive from AnalysisResult");
- static_assert((HasAnalysisName_v<DepResultTs> && ...),
- "Every DepResultT must have a static analysisName() method");
-
- friend class AnalysisRegistry;
- using ResultType = ResultT;
-
- std::unique_ptr<ResultT> Result = std::make_unique<ResultT>();
-
-public:
- /// Used by AnalysisRegistry::Add to derive the registry entry name.
- AnalysisName getAnalysisName() const final { return ResultT::analysisName(); }
-
- const std::vector<AnalysisName> &getDependencyNames() const final {
- static const std::vector<AnalysisName> Names = {
- DepResultTs::analysisName()...};
- return Names;
- }
-
- /// Called once with the fixed dependency results before the step() loop.
- virtual llvm::Error initialize(const DepResultTs &...) = 0;
-
-protected:
- /// Read-only access to the result being built.
- const ResultT &getResult() const & { return *Result; }
-
- /// Mutable access to the result being built.
- ResultT &getResult() & { return *Result; }
-
-private:
- /// Seals the type-erased base overload, downcasts, and dispatches to the
- /// typed initialize(). All dependencies are guaranteed present by the driver.
- llvm::Error
- initialize(const std::map<AnalysisName, const AnalysisResult *> &Map) final {
- auto lookup = [&Map](const AnalysisName &Name) -> const AnalysisResult * {
- auto It = Map.find(Name);
- if (It == Map.end()) {
- ErrorBuilder::fatal("dependency '{0}' missing from DepResults map; "
- "dependency graph is not topologically sorted",
- Name);
- }
- return It->second;
- };
- return initialize(*static_cast<const DepResultTs *>(
- lookup(DepResultTs::analysisName()))...);
- }
-
- /// Type-erased result extraction for the driver.
- std::unique_ptr<AnalysisResult> takeResult() && final {
- return std::move(Result);
- }
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h
deleted file mode 100644
index 5b7c2c9b6b8c2..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h
+++ /dev/null
@@ -1,121 +0,0 @@
-//===- SummaryAnalysis.h ----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines SummaryAnalysisBase (type-erased base known to AnalysisDriver) and
-// the typed intermediate SummaryAnalysis<ResultT, EntitySummaryT> that
-// concrete analyses inherit from.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisBase.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h"
-#include "llvm/Support/Error.h"
-#include <memory>
-
-namespace clang::ssaf {
-
-class AnalysisDriver;
-class AnalysisRegistry;
-
-/// Type-erased base for summary analyses. Known to AnalysisDriver.
-///
-/// Not subclassed directly -- use SummaryAnalysis<ResultT, EntitySummaryT>.
-/// A summary analysis processes per-entity EntitySummary objects from the
-/// LUSummary one at a time, accumulating whole-program data into an
-/// AnalysisResult.
-class SummaryAnalysisBase : public AnalysisBase {
- friend class AnalysisDriver;
-
-protected:
- SummaryAnalysisBase() : AnalysisBase(AnalysisBase::Kind::Summary) {}
-
-public:
- /// SummaryName of the EntitySummary type this analysis consumes.
- /// Used by the driver to route entities from the LUSummary.
- virtual SummaryName getSummaryName() const = 0;
-
-private:
- /// Called once before any add() calls. Default is a no-op.
- virtual llvm::Error initialize() { return llvm::Error::success(); }
-
- /// Called once per matching entity. The driver retains ownership of the
- /// summary; multiple SummaryAnalysis instances may receive the same entity.
- virtual llvm::Error add(EntityId Id, const EntitySummary &Summary) = 0;
-
- /// Called after all entities have been processed. Default is a no-op.
- virtual llvm::Error finalize() { return llvm::Error::success(); }
-};
-
-/// Typed intermediate that concrete summary analyses inherit from.
-///
-/// Concrete analyses must implement:
-/// llvm::Error add(EntityId Id, const EntitySummaryT &Summary) override;
-/// and may override initialize() and finalize().
-///
-/// The result being built is accessible via getResult() const & (read-only) and
-/// getResult() & (mutable) within the analysis implementation.
-template <typename ResultT, typename EntitySummaryT>
-class SummaryAnalysis : public SummaryAnalysisBase {
- static_assert(std::is_base_of_v<AnalysisResult, ResultT>,
- "ResultT must derive from AnalysisResult");
- static_assert(HasAnalysisName_v<ResultT>,
- "ResultT must have a static analysisName() method");
- static_assert(std::is_base_of_v<EntitySummary, EntitySummaryT>,
- "EntitySummaryT must derive from EntitySummary");
-
- friend class AnalysisRegistry;
- using ResultType = ResultT;
-
- std::unique_ptr<ResultT> Result = std::make_unique<ResultT>();
-
-public:
- /// Used by AnalysisRegistry::Add to derive the registry entry name.
- AnalysisName getAnalysisName() const final { return ResultT::analysisName(); }
-
- SummaryName getSummaryName() const final {
- return EntitySummaryT::summaryName();
- }
-
- const std::vector<AnalysisName> &getDependencyNames() const final {
- static const std::vector<AnalysisName> Empty;
- return Empty;
- }
-
- /// Called once per matching entity. Implement to accumulate data.
- virtual llvm::Error add(EntityId Id, const EntitySummaryT &Summary) = 0;
-
-protected:
- /// Read-only access to the result being built.
- const ResultT &getResult() const & { return *Result; }
-
- /// Mutable access to the result being built.
- ResultT &getResult() & { return *Result; }
-
-private:
- /// Seals the type-erased base overload, downcasts, and dispatches to the
- /// typed add().
- llvm::Error add(EntityId Id, const EntitySummary &Summary) final {
- return add(Id, static_cast<const EntitySummaryT &>(Summary));
- }
-
- /// Type-erased result extraction for the driver.
- std::unique_ptr<AnalysisResult> takeResult() && final {
- return std::move(Result);
- }
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h
deleted file mode 100644
index 8e7693b78d485..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h
+++ /dev/null
@@ -1,99 +0,0 @@
-//===- WPASuite.h -----------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// The value returned by AnalysisDriver::run(). Bundles the EntityIdTable
-// with the analysis results keyed by AnalysisName.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisTraits.h"
-#include "llvm/Support/Error.h"
-#include <map>
-#include <memory>
-
-namespace clang::ssaf {
-
-class AnalysisDriver;
-class SerializationFormat;
-class TestFixture;
-
-/// Bundles the EntityIdTable (moved from the LUSummary) and the analysis
-/// results produced by one AnalysisDriver::run() call, keyed by AnalysisName.
-///
-/// This is the natural unit of persistence: entity names and analysis results
-/// are self-contained in one object.
-class WPASuite {
- friend class AnalysisDriver;
- friend class SerializationFormat;
- friend class TestFixture;
-
- EntityIdTable IdTable;
- std::map<AnalysisName, std::unique_ptr<AnalysisResult>> Data;
-
- WPASuite() = default;
-
-public:
- /// Returns the EntityIdTable that maps EntityId values to their symbolic
- /// names.
- const EntityIdTable &getIdTable() const { return IdTable; }
-
- /// Returns true if a result for \p ResultT is present.
- template <typename ResultT> [[nodiscard]] bool contains() const {
- static_assert(std::is_base_of_v<AnalysisResult, ResultT>,
- "ResultT must derive from AnalysisResult");
- static_assert(HasAnalysisName_v<ResultT>,
- "ResultT must have a static analysisName() method");
-
- return contains(ResultT::analysisName());
- }
-
- /// Returns true if a result for \p Name is present.
- [[nodiscard]] bool contains(AnalysisName Name) const {
- return Data.find(Name) != Data.end();
- }
-
- /// Returns a const reference to the result for \p ResultT, or an error if
- /// absent.
- template <typename ResultT>
- [[nodiscard]] llvm::Expected<const ResultT &> get() const {
- static_assert(std::is_base_of_v<AnalysisResult, ResultT>,
- "ResultT must derive from AnalysisResult");
- static_assert(HasAnalysisName_v<ResultT>,
- "ResultT must have a static analysisName() method");
-
- auto Result = get(ResultT::analysisName());
- if (!Result) {
- return Result.takeError();
- }
- return static_cast<const ResultT &>(*Result);
- }
-
- /// Returns a const reference to the result for \p Name, or an error if
- /// absent.
- [[nodiscard]] llvm::Expected<const AnalysisResult &>
- get(AnalysisName Name) const {
- auto It = Data.find(Name);
- if (It == Data.end()) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- "no result for '{0}' in WPASuite", Name)
- .build();
- }
- return *It->second;
- }
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h b/clang/include/clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h
deleted file mode 100644
index fe5d75149914e..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- TUSummaryExtractorFrontendAction.h -----------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
-
-#include "clang/Frontend/FrontendAction.h"
-#include <memory>
-
-namespace clang::ssaf {
-
-/// Wraps the existing \c FrontendAction and injects the extractor
-/// \c ASTConsumers into the pipeline after the ASTConsumers of the wrapped
-/// action.
-class TUSummaryExtractorFrontendAction final : public WrapperFrontendAction {
-public:
- explicit TUSummaryExtractorFrontendAction(
- std::unique_ptr<FrontendAction> WrappedAction);
- ~TUSummaryExtractorFrontendAction();
-
-protected:
- std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) override;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
deleted file mode 100644
index 354379645a8de..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- SSAFBuiltinForceLinker.h ---------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file pulls in all built-in SSAF extractor and format registrations
-/// by referencing their anchor symbols, preventing the static linker from
-/// discarding the containing object files.
-///
-/// Include this header (with IWYU pragma: keep) in any translation unit that
-/// must guarantee these registrations are active — typically the entry point
-/// of a binary that uses clangScalableStaticAnalysisFrameworkCore.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
-
-namespace clang::ssaf {
-
-#define ANCHOR(NAME) extern volatile int NAME;
-#include "BuiltinAnchorSources.def"
-
-// Force the linker to link in the built-in SSAF registrations.
-[[maybe_unused]] static const int BuiltinAnchorDestination = [] {
- int AnchorSources[]{
-#define ANCHOR(NAME) NAME,
-#include "BuiltinAnchorSources.def"
- };
-
- int SomeUse = 0;
- for (int V : AnchorSources)
- SomeUse |= V;
- return SomeUse;
-}();
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFBUILTINFORCELINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h b/clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h
deleted file mode 100644
index 204a504c36435..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- SSAFForceLinker.h ----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file pulls in all built-in SSAF extractor and format registrations
-/// by referencing their anchor symbols, preventing the static linker from
-/// discarding the containing object files.
-///
-/// Include this header (with IWYU pragma: keep) in any translation unit that
-/// must guarantee these registrations are active — typically the entry point
-/// of a binary that uses clangScalableStaticAnalysisFrameworkCore.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFFORCELINKER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFFORCELINKER_H
-
-#include "SSAFBuiltinForceLinker.h" // IWYU pragma: keep
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SSAFFORCELINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/SourceEditEmitter.h b/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/SourceEditEmitter.h
deleted file mode 100644
index e96c9846a35f2..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/SourceEditEmitter.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//===- SourceEditEmitter.h --------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Abstract accumulator for source edits.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_SOURCEEDITEMITTER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_SOURCEEDITEMITTER_H
-
-#include "clang/Tooling/Core/Replacement.h"
-
-namespace clang::ssaf {
-
-class SourceEditEmitter {
-public:
- virtual ~SourceEditEmitter() = default;
-
- virtual void addReplacement(clang::tooling::Replacement R) = 0;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_SOURCEEDITEMITTER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/Transformation.h b/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/Transformation.h
deleted file mode 100644
index 5553b7796b1ad..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/Transformation.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===- Transformation.h -----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Abstract base class for source transformations. A Transformation is an
-// ASTConsumer that consumes a previously computed WPASuite.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_TRANSFORMATION_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_TRANSFORMATION_H
-
-#include "clang/AST/ASTConsumer.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-#include "clang/ScalableStaticAnalysisFramework/SourceTransformation/SourceEditEmitter.h"
-#include "clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationReportEmitter.h"
-
-namespace clang::ssaf {
-
-class Transformation : public clang::ASTConsumer {
-public:
- Transformation(const WPASuite &Suite, SourceEditEmitter &Edits,
- TransformationReportEmitter &Report)
- : Suite(Suite), Edits(Edits), Report(Report) {}
-
-protected:
- const WPASuite &Suite;
- SourceEditEmitter &Edits;
- TransformationReportEmitter &Report;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_TRANSFORMATION_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationRegistry.h b/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationRegistry.h
deleted file mode 100644
index 231a810f60f26..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationRegistry.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//===- TransformationRegistry.h ---------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Registry for Transformations, and some helper functions.
-// To register a transformation, insert this code:
-//
-// namespace clang::ssaf {
-// // NOLINTNEXTLINE(misc-use-internal-linkage)
-// volatile int MyTransformationAnchorSource = 0;
-// } // namespace clang::ssaf
-// static TransformationRegistry::Add<MyTransformation>
-// X("MyTransformation", "My awesome transformation");
-//
-// For a statically-linked transformation also extend the `AnchorSources`
-// list in
-// clang/include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h
-// (plugin-loaded transformations do not need an anchor — the dynamic loader
-// runs every global ctor on load).
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_TRANSFORMATIONREGISTRY_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_TRANSFORMATIONREGISTRY_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-#include "clang/ScalableStaticAnalysisFramework/SourceTransformation/SourceEditEmitter.h"
-#include "clang/ScalableStaticAnalysisFramework/SourceTransformation/Transformation.h"
-#include "clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationReportEmitter.h"
-#include "clang/Support/Compiler.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Registry.h"
-#include "llvm/Support/raw_ostream.h"
-#include <memory>
-
-namespace clang::ssaf {
-
-/// Check if a Transformation was registered with a given name.
-bool isTransformationRegistered(llvm::StringRef Name);
-
-/// Try to instantiate a Transformation with a given name.
-/// This might return null if the construction of the desired Transformation
-/// failed.
-/// It's a fatal error if there is no transformation registered with the name.
-std::unique_ptr<Transformation>
-makeTransformation(llvm::StringRef Name, const WPASuite &Suite,
- SourceEditEmitter &Edits,
- TransformationReportEmitter &Report);
-
-/// Print the list of available Transformations.
-void printAvailableTransformations(llvm::raw_ostream &OS);
-
-// Registry for adding new Transformation implementations.
-using TransformationRegistry =
- llvm::Registry<Transformation, const WPASuite &, SourceEditEmitter &,
- TransformationReportEmitter &>;
-
-} // namespace clang::ssaf
-
-LLVM_DECLARE_REGISTRY(clang::ssaf::TransformationRegistry)
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_TRANSFORMATIONREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationReportEmitter.h b/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationReportEmitter.h
deleted file mode 100644
index de57dd5a3952b..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationReportEmitter.h
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- TransformationReportEmitter.h ----------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Abstract accumulator for the transformation report.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_TRANSFORMATIONREPORTEMITTER_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_TRANSFORMATIONREPORTEMITTER_H
-
-#include "clang/Basic/Sarif.h"
-#include "clang/Basic/SourceLocation.h"
-#include "llvm/ADT/StringRef.h"
-
-namespace clang::ssaf {
-
-class TransformationReportEmitter {
-public:
- virtual ~TransformationReportEmitter() = default;
-
- virtual void addResult(llvm::StringRef RuleId, clang::SarifResultLevel Level,
- clang::CharSourceRange Range,
- llvm::StringRef Message) = 0;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_SOURCETRANSFORMATION_TRANSFORMATIONREPORTEMITTER_H
diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h b/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
deleted file mode 100644
index f7ee5c28ffe89..0000000000000
--- a/clang/include/clang/ScalableStaticAnalysisFramework/Tool/Utils.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//===- Utils.h - Shared utilities for SSAF tools ----------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Shared error-handling, format-registry cache, and summary-file abstraction
-// used by clang-ssaf tools.
-//
-// All declarations live in the clang::ssaf namespace.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
-#define LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FormatVariadic.h"
-#include <string>
-
-namespace clang::ssaf {
-
-//===----------------------------------------------------------------------===//
-// Tool Identity
-//===----------------------------------------------------------------------===//
-
-/// Returns the name of the running tool, as set by initTool().
-llvm::StringRef getToolName();
-
-//===----------------------------------------------------------------------===//
-// Diagnostic Utilities
-//===----------------------------------------------------------------------===//
-
-[[noreturn]] void fail(const char *Msg);
-
-template <typename... Ts>
-[[noreturn]] inline void fail(const char *Fmt, Ts &&...Args) {
- std::string Message = llvm::formatv(Fmt, std::forward<Ts>(Args)...);
- fail(Message.data());
-}
-
-[[noreturn]] void fail(llvm::Error Err);
-
-//===----------------------------------------------------------------------===//
-// Plugin Loading
-//===----------------------------------------------------------------------===//
-
-void loadPlugins(llvm::ArrayRef<std::string> Paths);
-
-//===----------------------------------------------------------------------===//
-// Initialization
-//===----------------------------------------------------------------------===//
-
-/// Sets ToolName, ToolVersion, and the version printer, hides unrelated
-/// command-line options, and parses arguments. Must be called after InitLLVM.
-void initTool(int argc, const char **argv, llvm::StringRef Version,
- llvm::cl::OptionCategory &Category, llvm::StringRef ToolHeading);
-
-//===----------------------------------------------------------------------===//
-// Data Structures
-//===----------------------------------------------------------------------===//
-
-struct FormatFile {
- std::string Path;
- SerializationFormat *Format = nullptr;
-
- /// Validates an input path and returns a FormatFile.
- ///
- /// Checks that the path exists and is a regular file, then resolves the
- /// serialization format from the file extension. Read permission is not
- /// checked here because llvm::sys::fs::AccessMode does not support Read; read
- /// errors are caught when the file is opened during deserialization.
- ///
- /// Calls fail() and exits on any validation error.
- static FormatFile fromInputPath(llvm::StringRef Path);
-
- /// Validates an output path and returns a FormatFile.
- ///
- /// Checks that the output file does not already exist, that the parent
- /// directory exists and is writable, then resolves the serialization format
- /// from the file extension.
- ///
- /// Calls fail() and exits on any validation error.
- static FormatFile fromOutputPath(llvm::StringRef Path);
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_TOOL_UTILS_H
diff --git a/clang/include/module.modulemap b/clang/include/module.modulemap
index d3f616b3fd636..b8a9184980259 100644
--- a/clang/include/module.modulemap
+++ b/clang/include/module.modulemap
@@ -147,12 +147,12 @@ module Clang_Options { requires cplusplus umbrella "clang/Options" module * { ex
module Clang_Parse { requires cplusplus umbrella "clang/Parse" module * { export * } }
module Clang_Rewrite { requires cplusplus umbrella "clang/Rewrite/Core" module * { export * } }
module Clang_RewriteFrontend { requires cplusplus umbrella "clang/Rewrite/Frontend" module * { export * } }
-module Clang_ScalableStaticAnalysisFramework {
+module Clang_ScalableStaticAnalysis {
requires cplusplus
- umbrella "clang/ScalableStaticAnalysisFramework"
+ umbrella "clang/ScalableStaticAnalysis"
- textual header "clang/ScalableStaticAnalysisFramework/BuiltinAnchorSources.def"
- textual header "clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def"
+ textual header "clang/ScalableStaticAnalysis/BuiltinAnchorSources.def"
+ textual header "clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def"
module * { export * }
}
diff --git a/clang/lib/CMakeLists.txt b/clang/lib/CMakeLists.txt
index d9d1e4630a416..dee31cb3f166e 100644
--- a/clang/lib/CMakeLists.txt
+++ b/clang/lib/CMakeLists.txt
@@ -23,7 +23,7 @@ add_subdirectory(DirectoryWatcher)
add_subdirectory(Index)
add_subdirectory(IndexSerialization)
add_subdirectory(InstallAPI)
-add_subdirectory(ScalableStaticAnalysisFramework)
+add_subdirectory(ScalableStaticAnalysis)
add_subdirectory(StaticAnalyzer)
add_subdirectory(Format)
if(CLANG_INCLUDE_TESTS)
diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index cd410899c450f..cba616bb32e92 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -112,10 +112,10 @@ add_clang_library(clangDriver
clangBasic
clangDependencyScanning
clangFrontend
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkFrontend
- clangScalableStaticAnalysisFrameworkSourceTransformation
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisFrontend
+ clangScalableStaticAnalysisSourceTransformation
clangSerialization
clangLex
clangOptions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index ea06235de5c1f..40953c0013f62 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -70,9 +70,9 @@
#include "clang/Driver/Types.h"
#include "clang/Options/OptionUtils.h"
#include "clang/Options/Options.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/ScopeExit.h"
diff --git a/clang/lib/FrontendTool/CMakeLists.txt b/clang/lib/FrontendTool/CMakeLists.txt
index 543aa06090ec8..2e9ce83d25fe1 100644
--- a/clang/lib/FrontendTool/CMakeLists.txt
+++ b/clang/lib/FrontendTool/CMakeLists.txt
@@ -4,10 +4,10 @@ set(LLVM_LINK_COMPONENTS
)
set(link_libs
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkFrontend
- clangScalableStaticAnalysisFrameworkSourceTransformation
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisFrontend
+ clangScalableStaticAnalysisSourceTransformation
clangBasic
clangCodeGen
clangDriver
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index 997200619e599..a206770c8490f 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -24,8 +24,8 @@
#include "clang/FrontendTool/Utils.h"
#include "clang/Options/Options.h"
#include "clang/Rewrite/Frontend/FrontendActions.h"
-#include "clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h"
-#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
+#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
#include "clang/StaticAnalyzer/Frontend/AnalyzerHelpFlags.h"
#include "clang/StaticAnalyzer/Frontend/FrontendActions.h"
#include "llvm/Option/OptTable.h"
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
deleted file mode 100644
index 2bd7c925fc5b9..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CMakeLists.txt
+++ /dev/null
@@ -1,28 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Support
- TargetParser
- )
-
-add_clang_library(clangScalableStaticAnalysisFrameworkAnalyses
- CallGraph/CallGraphExtractor.cpp
- CallGraph/CallGraphJSONFormat.cpp
- EntityPointerLevel/EntityPointerLevel.cpp
- EntityPointerLevel/EntityPointerLevelFormat.cpp
- PointerFlow/PointerFlow.cpp
- PointerFlow/PointerFlowAnalysis.cpp
- PointerFlow/PointerFlowExtractor.cpp
- PointerFlow/PointerFlowFormat.cpp
- SSAFAnalysesCommon.cpp
- UnsafeBufferUsage/UnsafeBufferUsage.cpp
- UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
- UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
- UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
-
- LINK_LIBS
- clangAST
- clangAnalysis
- clangBasic
- clangScalableStaticAnalysisFrameworkCore
-
- DEPENDS
- )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
deleted file mode 100644
index 6dfb66a283674..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractor.cpp
+++ /dev/null
@@ -1,108 +0,0 @@
-//===- CallGraphExtractor.cpp - Call Graph Summary Extractor --------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/Analysis/AnalysisDeclContext.h"
-#include "clang/Analysis/CallGraph.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "llvm/ADT/STLExtras.h"
-#include <memory>
-
-using namespace clang;
-using namespace ssaf;
-
-namespace {
-class CallGraphExtractor final : public TUSummaryExtractor {
-public:
- using TUSummaryExtractor::TUSummaryExtractor;
-
-private:
- void HandleTranslationUnit(ASTContext &Ctx) override;
-
- void handleCallGraphNode(const ASTContext &Ctx, const CallGraphNode *N);
-};
-} // namespace
-
-void CallGraphExtractor::HandleTranslationUnit(ASTContext &Ctx) {
- CallGraph CG;
- CG.addToCallGraph(
- const_cast<TranslationUnitDecl *>(Ctx.getTranslationUnitDecl()));
-
- for (const auto &N : llvm::make_second_range(CG)) {
- if (N && N->getDecl() && N->getDefinition())
- handleCallGraphNode(Ctx, N.get());
- }
-}
-
-void CallGraphExtractor::handleCallGraphNode(const ASTContext &Ctx,
- const CallGraphNode *N) {
- const FunctionDecl *Definition = N->getDefinition();
-
- // FIXME: `clang::CallGraph` does not create entries for primary templates.
- assert(!Definition->isTemplated());
-
- auto CallerId = addEntity(Definition);
- if (!CallerId)
- return;
-
- auto FnSummary = std::make_unique<CallGraphSummary>();
-
- PresumedLoc Loc =
- Ctx.getSourceManager().getPresumedLoc(Definition->getLocation());
- FnSummary->Definition.File = Loc.getFilename();
- FnSummary->Definition.Line = Loc.getLine();
- FnSummary->Definition.Column = Loc.getColumn();
- FnSummary->PrettyName = AnalysisDeclContext::getFunctionName(Definition);
-
- for (const auto &Record : N->callees()) {
- const Decl *CalleeDecl = Record.Callee->getDecl();
-
- // FIXME: `clang::CallGraph` does not consider indirect calls, thus this is
- // never null.
- assert(CalleeDecl);
-
- // `clang::CallGraph` resolves ObjCMessageExprs (including property
- // dot-syntax) to their ObjCMethodDecls and adds them as callees — see
- // `CGBuilder::VisitObjCMessageExpr` in clang/lib/Analysis/CallGraph.cpp.
- // ObjC dispatch is dynamic, so recording these as direct callees would be
- // misleading; skip them until we model ObjC properly.
- if (isa<ObjCMethodDecl>(CalleeDecl))
- continue;
-
- // FIXME: `clang::CallGraph` does not create entries for primary templates.
- assert(!CalleeDecl->isTemplated());
-
- auto CalleeId = addEntity(cast<NamedDecl>(CalleeDecl));
- if (!CalleeId)
- continue;
-
- if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(CalleeDecl);
- MD && MD->isVirtual()) {
- FnSummary->VirtualCallees.insert(*CalleeId);
- continue;
- }
- FnSummary->DirectCallees.insert(*CalleeId);
- }
-
- SummaryBuilder.addSummary(*CallerId, std::move(FnSummary));
-}
-
-static TUSummaryExtractorRegistry::Add<CallGraphExtractor>
- RegisterExtractor(CallGraphSummary::Name,
- "Extracts static call-graph information");
-
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int CallGraphExtractorAnchorSource = 0;
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
deleted file mode 100644
index 6f2414280bfaa..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphJSONFormat.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-//===- CallGraphJSONFormat.cpp --------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/JSON.h"
-#include <memory>
-
-using namespace llvm;
-using namespace clang;
-using namespace ssaf;
-
-static const char *FailedToReadObjectAtField =
- "failed to read {0} from field '{1}': expected JSON {2}";
-static const char *FailedToReadObjectAtIndex =
- "failed to read {0} from index '{1}': expected JSON {2}";
-static const char *ReadingFromField = "reading {0} from field '{1}'";
-static const char *ReadingFromIndex = "reading {0} from index '{1}'";
-
-static json::Object serialize(const EntitySummary &Summary,
- JSONFormat::EntityIdToJSONFn ToJSON) {
- const auto &S = static_cast<const CallGraphSummary &>(Summary);
-
- json::Array DirectCalleesArray;
- DirectCalleesArray.reserve(S.DirectCallees.size());
- append_range(DirectCalleesArray, map_range(S.DirectCallees, ToJSON));
-
- json::Array VirtualCalleesArray;
- VirtualCalleesArray.reserve(S.VirtualCallees.size());
- append_range(VirtualCalleesArray, map_range(S.VirtualCallees, ToJSON));
-
- return json::Object{
- {"pretty_name", json::Value(S.PrettyName)},
- {"direct_callees", std::move(DirectCalleesArray)},
- {"virtual_callees", std::move(VirtualCalleesArray)},
- {"def",
- json::Object{
- {"file", json::Value(S.Definition.File)},
- {"line", json::Value(S.Definition.Line)},
- {"col", json::Value(S.Definition.Column)},
- }},
- };
-}
-
-static Expected<std::unique_ptr<EntitySummary>>
-deserialize(const json::Object &Obj, EntityIdTable &IdTable,
- JSONFormat::EntityIdFromJSONFn FromJSON) {
- auto Result = std::make_unique<CallGraphSummary>();
-
- auto PrettyName = Obj.getString("pretty_name");
- if (!PrettyName) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- FailedToReadObjectAtField, "PrettyName",
- "pretty_name", "string")
- .build();
- }
- Result->PrettyName = PrettyName->str();
-
- const json::Array *CalleesArray = Obj.getArray("direct_callees");
- if (!CalleesArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- FailedToReadObjectAtField, "DirectCallees",
- "direct_callees", "array")
- .build();
- }
- for (const auto &[Index, Value] : llvm::enumerate(*CalleesArray)) {
- const json::Object *CalleeObj = Value.getAsObject();
- if (!CalleeObj) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- FailedToReadObjectAtIndex, "EntityId", Index,
- "object")
- .context(ReadingFromField, "DirectCallees", "direct_callees")
- .build();
- }
- auto ExpectedId = FromJSON(*CalleeObj);
- if (!ExpectedId) {
- return ErrorBuilder::wrap(ExpectedId.takeError())
- .context(ReadingFromIndex, "EntityId", Index)
- .context(ReadingFromField, "DirectCallees", "direct_callees")
- .build();
- }
- Result->DirectCallees.insert(*ExpectedId);
- }
-
- const json::Array *VirtualCalleesArray = Obj.getArray("virtual_callees");
- if (!VirtualCalleesArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- FailedToReadObjectAtField, "VirtualCallees",
- "virtual_callees", "array")
- .build();
- }
- for (const auto &[Index, Value] : llvm::enumerate(*VirtualCalleesArray)) {
- const json::Object *CalleeObj = Value.getAsObject();
- if (!CalleeObj) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- FailedToReadObjectAtIndex, "EntityId", Index,
- "object")
- .context(ReadingFromField, "VirtualCallees", "virtual_callees")
- .build();
- }
- auto ExpectedId = FromJSON(*CalleeObj);
- if (!ExpectedId) {
- return ErrorBuilder::wrap(ExpectedId.takeError())
- .context(ReadingFromIndex, "EntityId", Index)
- .context(ReadingFromField, "VirtualCallees", "virtual_callees")
- .build();
- }
- Result->VirtualCallees.insert(*ExpectedId);
- }
-
- const json::Object *DefObj = Obj.getObject("def");
- if (!DefObj) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- FailedToReadObjectAtField, "SourceLocation",
- "def", "object")
- .build();
- }
- auto File = DefObj->getString("file");
- if (!File) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- FailedToReadObjectAtField, "File", "file",
- "string")
- .context(ReadingFromField, "SourceLocation", "def")
- .build();
- }
- auto Line = DefObj->getInteger("line");
- if (!Line) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- FailedToReadObjectAtField, "Line", "line",
- "number")
- .context(ReadingFromField, "SourceLocation", "def")
- .build();
- }
- auto Col = DefObj->getInteger("col");
- if (!Col) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- FailedToReadObjectAtField, "Column", "col",
- "number")
- .context(ReadingFromField, "SourceLocation", "def")
- .build();
- }
- Result->Definition = {
- File->str(),
- static_cast<unsigned>(*Line),
- static_cast<unsigned>(*Col),
- };
-
- return std::move(Result);
-}
-
-namespace {
-struct CallGraphJSONFormatInfo final : JSONFormat::FormatInfo {
- CallGraphJSONFormatInfo()
- : JSONFormat::FormatInfo(SummaryName(CallGraphSummary::Name.str()),
- serialize, deserialize) {}
-};
-} // namespace
-
-static llvm::Registry<JSONFormat::FormatInfo>::Add<CallGraphJSONFormatInfo>
- RegisterFormatInfo(CallGraphSummary::Name,
- "JSON Format info for CallGraph summary");
-
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int CallGraphJSONFormatAnchorSource = 0;
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
deleted file mode 100644
index 758009be1f49b..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
+++ /dev/null
@@ -1,366 +0,0 @@
-//===- EntityPointerLevel.cpp -----------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "SSAFAnalysesCommon.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
-#include <optional>
-
-using namespace clang;
-using namespace ssaf;
-
-namespace clang::ssaf {
-// Translate a pointer type expression 'E' to a (set of) EntityPointerLevel(s)
-// associated with the declared type of the base address of `E`. If the base
-// address of `E` is not associated with an entity, the translation result is an
-// empty set.
-//
-// The translation is a process of traversing into the pointer 'E' until its
-// base address can be represented by an entity, with the number of dereferences
-// tracked by incrementing the pointer level. Naturally, taking address of, as
-// the inverse operation of dereference, is tracked by decrementing the pointer
-// level.
-//
-// For example, suppose there are pointers and arrays declared as
-// int *ptr, **p1, **p2;
-// int arr[10][10];
-// , the translation of expressions involving these base addresses will be:
-// Translate(ptr + 5) -> {(ptr, 1)}
-// Translate(arr[5]) -> {(arr, 2)}
-// Translate(cond ? p1[5] : p2) -> {(p1, 2), (p2, 1)}
-// Translate(&arr[5]) -> {(arr, 1)}
-class EntityPointerLevelTranslator
- : ConstStmtVisitor<EntityPointerLevelTranslator,
- Expected<EntityPointerLevelSet>> {
- friend class StmtVisitorBase;
-
- // Fallback method for all unsupported expression kind:
- Expected<EntityPointerLevelSet> fallback(const Stmt *S) {
- // Report an error/warning (at least in debug mode) for any unsupported kind
- // of pointer/array typed expression, because we want to understand every
- // pointer/array expression. But for non-pointer/array typed expressions, we
- // could silently ignore unsupported kinds. This translator visits
- // non-pointer/array typed expressions because of address-of expressions.
- if (const Expr *E = dyn_cast<Expr>(S); E && hasPtrOrArrType(E))
- return makeErrAtNode(Ctx, E,
- "attempt to translate %s to EntityPointerLevels",
- E->getStmtClassName());
- return EntityPointerLevelSet{};
- }
-
- Expected<EntityPointerLevel>
- createEntityPointerLevelFor(const NamedDecl *ND) {
- std::optional<EntityId> Id = Extractor.addEntity(ND);
- if (!Id)
- return makeErrAtNode(Ctx, ND, "failed to create EntityId for %s",
- ND->getDeclKindName());
- return EntityPointerLevel{buildEntityPointerLevel(*Id, 1)};
- }
-
- Expected<EntityPointerLevel>
- createEntityPointerLevelForReturn(const FunctionDecl *FD) {
- std::optional<EntityId> Id = Extractor.addEntityForReturn(FD);
- if (!Id) {
- return makeErrAtNode(Ctx, FD, "failed to create EntityId for function %s",
- cast<NamedDecl>(FD)->getNameAsString().c_str());
- }
- return EntityPointerLevel{buildEntityPointerLevel(*Id, 1)};
- }
-
- // The common helper function for Translate(*base):
- // Translate(*base) -> Translate(base) with .pointerLevel + 1
- Expected<EntityPointerLevelSet> translateDereferencePointer(const Expr *Ptr) {
- assert(hasPtrOrArrType(Ptr));
-
- Expected<EntityPointerLevelSet> SubResult = Visit(Ptr);
- if (!SubResult)
- return SubResult.takeError();
-
- auto Incremented = llvm::map_range(*SubResult, incrementPointerLevel);
- return EntityPointerLevelSet{Incremented.begin(), Incremented.end()};
- }
-
- TUSummaryExtractor &Extractor;
- ASTContext &Ctx;
-
-public:
- EntityPointerLevelTranslator(TUSummaryExtractor &Extractor, ASTContext &Ctx)
- : Extractor(Extractor), Ctx(Ctx) {}
-
- Expected<EntityPointerLevelSet> translate(const Expr *E) { return Visit(E); }
- Expected<EntityPointerLevel> translate(const NamedDecl *D, bool IsRet) {
- if (!IsRet)
- return createEntityPointerLevelFor(D);
-
- if (const auto *FD = dyn_cast<FunctionDecl>(D))
- return createEntityPointerLevelForReturn(FD);
-
- return makeErrAtNode(Ctx, D, "attempt to get entity for return of %s",
- D->getDeclKindName());
- }
-
- static EntityPointerLevel incrementPointerLevel(const EntityPointerLevel &E) {
- return EntityPointerLevel({E.getEntity(), E.getPointerLevel() + 1});
- }
-
- static EntityPointerLevel decrementPointerLevel(const EntityPointerLevel &E) {
- assert(E.getPointerLevel() > 0);
- return EntityPointerLevel({E.getEntity(), E.getPointerLevel() - 1});
- }
-
-private:
- Expected<EntityPointerLevelSet> VisitStmt(const Stmt *E) {
- return fallback(E);
- }
-
- // Translate(base + x) -> Translate(base)
- // Translate(x + base) -> Translate(base)
- // Translate(base - x) -> Translate(base)
- // Translate(base {+=, -=, =} x) -> Translate(base)
- // Translate(x, base) -> Translate(base)
- Expected<EntityPointerLevelSet> VisitBinaryOperator(const BinaryOperator *E) {
- switch (E->getOpcode()) {
- case clang::BO_Add:
- if (hasPtrOrArrType(E->getLHS()))
- return Visit(E->getLHS());
- return Visit(E->getRHS());
- case clang::BO_Sub:
- case clang::BO_AddAssign:
- case clang::BO_SubAssign:
- case clang::BO_Assign:
- return Visit(E->getLHS());
- case clang::BO_Comma:
- return Visit(E->getRHS());
- default:
- return fallback(E);
- }
- }
-
- // Translate({++, --}base) -> Translate(base)
- // Translate(base{++, --}) -> Translate(base)
- // Translate(*base) -> Translate(base) with .pointerLevel += 1
- // Translate(&base) -> {}, if Translate(base) is {}
- // -> Translate(base) with .pointerLevel -= 1
- // Translate(+base) -> Translate(base)
- Expected<EntityPointerLevelSet> VisitUnaryOperator(const UnaryOperator *E) {
- switch (E->getOpcode()) {
- case clang::UO_PostInc:
- case clang::UO_PostDec:
- case clang::UO_PreInc:
- case clang::UO_PreDec:
- return Visit(E->getSubExpr());
- case clang::UO_AddrOf: {
- Expected<EntityPointerLevelSet> SubResult = Visit(E->getSubExpr());
- if (!SubResult)
- return SubResult.takeError();
-
- auto Decremented = llvm::map_range(*SubResult, decrementPointerLevel);
- return EntityPointerLevelSet{Decremented.begin(), Decremented.end()};
- }
- case clang::UO_Deref:
- return translateDereferencePointer(E->getSubExpr());
- case clang::UO_Plus:
- return Visit(E->getSubExpr());
- default:
- return fallback(E);
- }
- }
-
- // Translate((T*)base) -> Translate(base) if base has pointer type
- // -> {} otherwise
- Expected<EntityPointerLevelSet> VisitCastExpr(const CastExpr *E) {
- if (hasPtrOrArrType(E->getSubExpr()))
- return Visit(E->getSubExpr());
- return EntityPointerLevelSet{};
- }
-
- // Translate(f(...)) -> {} if it is an indirect call
- // -> {(f_return, 1)}, otherwise
- Expected<EntityPointerLevelSet> VisitCallExpr(const CallExpr *E) {
- if (auto *FD = E->getDirectCallee()) {
- if (auto ReturnId = Extractor.addEntityForReturn(FD))
- return EntityPointerLevelSet{buildEntityPointerLevel(*ReturnId, 1)};
- }
- return EntityPointerLevelSet{};
- }
-
- // Translate(base[x]) -> Translate(*base)
- Expected<EntityPointerLevelSet>
- VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
- return translateDereferencePointer(E->getBase());
- }
-
- // Translate(cond ? base1 : base2) := Translate(base1) U Translate(base2)
- Expected<EntityPointerLevelSet>
- VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
- Expected<EntityPointerLevelSet> ReT = Visit(E->getTrueExpr());
- Expected<EntityPointerLevelSet> ReF = Visit(E->getFalseExpr());
-
- if (ReT && ReF) {
- ReT->insert(ReF->begin(), ReF->end());
- return ReT;
- }
- if (!ReF && !ReT)
- return llvm::joinErrors(ReT.takeError(), ReF.takeError());
- if (!ReF)
- return ReF.takeError();
- return ReT.takeError();
- }
-
- Expected<EntityPointerLevelSet> VisitParenExpr(const ParenExpr *E) {
- return Visit(E->getSubExpr());
- }
-
- // Translate("string-literal") -> {} // no entity involved
- Expected<EntityPointerLevelSet> VisitStringLiteral(const StringLiteral *E) {
- return EntityPointerLevelSet{};
- }
-
- // Translate(predefined-expr) -> {} // treated the same as string literals
- Expected<EntityPointerLevelSet> VisitPredefinedExpr(const PredefinedExpr *E) {
- return EntityPointerLevelSet{};
- }
-
- // Translate(integer-literal) -> {} // no entity involved
- Expected<EntityPointerLevelSet> VisitIntegerLiteral(const IntegerLiteral *E) {
- return EntityPointerLevelSet{};
- }
-
- // Translate(DRE) -> {(Decl, 1)}
- Expected<EntityPointerLevelSet> VisitDeclRefExpr(const DeclRefExpr *E) {
- auto Res = createEntityPointerLevelFor(E->getDecl());
- if (!Res)
- return Res.takeError();
- return EntityPointerLevelSet{*Res};
- }
-
- // Translate({., ->}f) -> {(MemberDecl, 1)}
- Expected<EntityPointerLevelSet> VisitMemberExpr(const MemberExpr *E) {
- auto Res = createEntityPointerLevelFor(E->getMemberDecl());
- if (!Res)
- return Res.takeError();
- return EntityPointerLevelSet{*Res};
- }
-
- // Unwrap CXXDefaultArgExpr
- Expected<EntityPointerLevelSet>
- VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {
- return Visit(E->getExpr());
- }
-
- // Unwrap OpaqueValueExpr
- Expected<EntityPointerLevelSet>
- VisitOpaqueValueExpr(const OpaqueValueExpr *S) {
- return Visit(S->getSourceExpr());
- }
-
- // Unwrap ExprWithCleanups
- Expected<EntityPointerLevelSet>
- VisitExprWithCleanups(const ExprWithCleanups *S) {
- return Visit(S->getSubExpr());
- }
-
- // Unwrap MaterializeTemporaryExpr
- Expected<EntityPointerLevelSet>
- VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
- return Visit(S->getSubExpr());
- }
-
- // Unwrap CXXDefaultInitExpr
- Expected<EntityPointerLevelSet>
- VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
- return Visit(E->getExpr());
- }
-
- // Translate(`nullptr`) -> {}
- Expected<EntityPointerLevelSet>
- VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *S) {
- return EntityPointerLevelSet{};
- }
-
- // Translate(`this`) -> {}
- Expected<EntityPointerLevelSet> VisitCXXThisExpr(const CXXThisExpr *S) {
- return EntityPointerLevelSet{};
- }
-
- // Translate(`new`/`new [*]`) -> {}
- Expected<EntityPointerLevelSet> VisitCXXNewExpr(const CXXNewExpr *S) {
- return EntityPointerLevelSet{};
- }
-
- // ImplicitValueInitExpr, for raw pointer type,
- // evaluates to a compile-time constant zero (or null). So no EPL in the
- // result.
- Expected<EntityPointerLevelSet>
- VisitImplicitValueInitExpr(const ImplicitValueInitExpr *S) {
- return EntityPointerLevelSet{};
- }
-
- // The InitListExpr must be an empty or singleton list that
- // initializes a pointer scalar. Other cases are unexpected thus an error.
- Expected<EntityPointerLevelSet> VisitInitListExpr(const InitListExpr *E) {
- if (E->getNumInits() < 1)
- return EntityPointerLevelSet{};
- if (E->getType()->isPointerType())
- return Visit(E->getInit(0));
- return llvm::createStringError(
- "Cannot translate an InitListExpr to EntityPointerLevels if it is not "
- "an empty or singleton list that initializes a pointer scalar");
- }
-
- // Clang may default initializes an array with a CXXConstructExpr. Fallback on
- // other cases, if they exist.
- // When a CXXConstructExpr has an array type, clang is initializing an array
- // of class-type objects with default values. In this case, no entity is
- // associated with the initializer.
- Expected<EntityPointerLevelSet>
- VisitCXXConstructExpr(const CXXConstructExpr *E) {
- if (E->getType()->isArrayType()) {
- return EntityPointerLevelSet{};
- }
- return fallback(E);
- }
-
- // No entity is associated with a CXXScalarValueInitExpr:
- Expected<EntityPointerLevelSet>
- VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
- return EntityPointerLevelSet{};
- }
-};
-} // namespace clang::ssaf
-
-Expected<EntityPointerLevelSet>
-clang::ssaf::translateEntityPointerLevel(const Expr *E, ASTContext &Ctx,
- TUSummaryExtractor &Extractor) {
- EntityPointerLevelTranslator Translator(Extractor, Ctx);
-
- return Translator.translate(E);
-}
-
-/// Create an EntityPointerLevel from a ValueDecl of a pointer type.
-Expected<EntityPointerLevel> clang::ssaf::createEntityPointerLevel(
- const NamedDecl *ND, TUSummaryExtractor &Extractor, bool IsFunRet) {
- EntityPointerLevelTranslator Translator(Extractor, ND->getASTContext());
-
- return Translator.translate(ND, IsFunRet);
-}
-
-EntityPointerLevel
-clang::ssaf::incrementPointerLevel(const EntityPointerLevel &E) {
- return EntityPointerLevelTranslator::incrementPointerLevel(E);
-}
-
-EntityPointerLevel clang::ssaf::buildEntityPointerLevel(EntityId Id,
- unsigned PtrLv) {
- return EntityPointerLevel({Id, PtrLv});
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.cpp
deleted file mode 100644
index 7de4a63aff5f0..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-//===- EntityPointerLevelFormat.cpp ---------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
-#include "SSAFAnalysesCommon.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/JSON.h"
-
-using namespace clang;
-using namespace ssaf;
-
-// Writes an EntityPointerLevel as
-// Array [
-// Object { "@" : [entity-id]},
-// [pointer-level-integer]
-// ]
-llvm::json::Value clang::ssaf::entityPointerLevelToJSON(
- const EntityPointerLevel &EPL, JSONFormat::EntityIdToJSONFn EntityId2JSON) {
- return llvm::json::Array{EntityId2JSON(EPL.getEntity()),
- llvm::json::Value(EPL.getPointerLevel())};
-}
-
-llvm::Expected<EntityPointerLevel> clang::ssaf::entityPointerLevelFromJSON(
- const llvm::json::Value &EPLData,
- JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
- auto *AsArr = EPLData.getAsArray();
-
- if (!AsArr || AsArr->size() != 2)
- return makeSawButExpectedError(
- EPLData, "an array with exactly two elements representing "
- "EntityId and PointerLevel, respectively");
-
- auto *EntityIdObj = (*AsArr)[0].getAsObject();
-
- if (!EntityIdObj)
- return makeSawButExpectedError((*AsArr)[0],
- "an object representing EntityId");
-
- llvm::Expected<EntityId> Id = EntityIdFromJSON(*EntityIdObj);
-
- if (!Id)
- return Id.takeError();
-
- std::optional<uint64_t> PtrLv = (*AsArr)[1].getAsInteger();
-
- if (!PtrLv)
- return makeSawButExpectedError((*AsArr)[1],
- "an integer representing PointerLevel");
-
- return buildEntityPointerLevel(*Id, *PtrLv);
-}
-
-llvm::json::Array clang::ssaf::entityPointerLevelSetToJSON(
- llvm::iterator_range<EntityPointerLevelSet::const_iterator> EPLs,
- JSONFormat::EntityIdToJSONFn EntityId2JSON) {
- llvm::json::Array Result;
-
- for (const auto &EPL : EPLs)
- Result.push_back(entityPointerLevelToJSON(EPL, EntityId2JSON));
- return Result;
-}
-
-Expected<EntityPointerLevelSet> clang::ssaf::entityPointerLevelSetFromJSON(
- const llvm::json::Array &EPLsData,
- JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
- EntityPointerLevelSet EPLs;
-
- for (const auto &EltData : EPLsData) {
- llvm::Expected<EntityPointerLevel> EPL =
- entityPointerLevelFromJSON(EltData, EntityIdFromJSON);
-
- if (!EPL)
- return EPL.takeError();
- EPLs.insert(*EPL);
- }
- return EPLs;
-}
-
-llvm::json::Array clang::ssaf::entityPointerLevelMapToJSON(
- const std::map<EntityId, EntityPointerLevelSet> &Map,
- JSONFormat::EntityIdToJSONFn IdToJSON) {
- llvm::json::Array Content;
-
- for (const auto &[Id, EPLs] : Map) {
- Content.push_back(IdToJSON(Id));
- Content.push_back(entityPointerLevelSetToJSON(EPLs, IdToJSON));
- }
- return Content;
-}
-
-Expected<std::map<EntityId, EntityPointerLevelSet>>
-clang::ssaf::entityPointerLevelMapFromJSON(
- const llvm::json::Array &Content,
- JSONFormat::EntityIdFromJSONFn IdFromJSON) {
- if (Content.size() % 2 != 0)
- return makeSawButExpectedError(Content,
- "an even number of elements, got %lu",
- static_cast<size_t>(Content.size()));
-
- std::map<EntityId, EntityPointerLevelSet> Result;
-
- for (size_t I = 0; I < Content.size(); I += 2) {
- const llvm::json::Object *IdData = Content[I].getAsObject();
-
- if (!IdData)
- return makeSawButExpectedError(Content[I],
- "an object representing EntityId");
-
- auto Id = IdFromJSON(*IdData);
-
- if (!Id)
- return Id.takeError();
-
- const llvm::json::Array *EPLsData = Content[I + 1].getAsArray();
-
- if (!EPLsData)
- return makeSawButExpectedError(
- Content[I + 1], "an array representing EntityPointerLevelSet");
-
- auto EPLs = entityPointerLevelSetFromJSON(*EPLsData, IdFromJSON);
-
- if (!EPLs)
- return EPLs.takeError();
- Result[*Id] = std::move(*EPLs);
- }
- return Result;
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.cpp
deleted file mode 100644
index fe28d9ae4efce..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//===- PointerFlow.cpp ----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
-
-using namespace clang;
-using namespace ssaf;
-
-ssaf::PointerFlowEntitySummary
-ssaf::buildPointerFlowEntitySummary(EdgeSet Edges) {
- return PointerFlowEntitySummary(std::move(Edges));
-}
-
-llvm::iterator_range<EdgeSet::const_iterator>
-ssaf::getEdges(const PointerFlowEntitySummary &Sum) {
- return Sum.Edges;
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
deleted file mode 100644
index de8490601cccc..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-//===- PointerFlowAnalysis.cpp - WPA for PointerFlow ----------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h"
-#include "SSAFAnalysesCommon.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
-#include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/JSON.h"
-#include <memory>
-
-using namespace clang::ssaf;
-using namespace llvm;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// PointerFlowAnalysis---converts PointerFlowEntitySummary(s) in an LUSummary to
-// a PointerFlowAnalysisResult
-//===----------------------------------------------------------------------===//
-
-// Serialized as a flat array of alternating [EntityId, EdgesArray, ...] pairs.
-json::Object
-serializePointerFlowAnalysisResult(const PointerFlowAnalysisResult &R,
- JSONFormat::EntityIdToJSONFn IdToJSON) {
- json::Array Content;
-
- for (const auto &[Id, EntityEdges] : R.Edges) {
- Content.push_back(IdToJSON(Id));
- Content.push_back(json::Value(edgeSetToJSON(EntityEdges, IdToJSON)));
- }
-
- json::Object Result;
-
- Result[PointerFlowAnalysisResultName] = std::move(Content);
- return Result;
-}
-
-Expected<std::unique_ptr<AnalysisResult>> deserializePointerFlowAnalysisResult(
- const json::Object &Obj, JSONFormat::EntityIdFromJSONFn IdFromJSON) {
- const json::Array *Content = Obj.getArray(PointerFlowAnalysisResultName);
-
- if (!Content)
- return makeSawButExpectedError(Obj, "an object with a key %s",
- PointerFlowAnalysisResultName.data());
-
- if (Content->size() % 2 != 0)
- return makeSawButExpectedError(*Content,
- "an even number of elements, got %lu",
- static_cast<size_t>(Content->size()));
-
- std::map<EntityId, EdgeSet> Edges;
-
- for (size_t I = 0; I < Content->size(); I += 2) {
- const json::Object *IdData = (*Content)[I].getAsObject();
-
- if (!IdData)
- return makeSawButExpectedError((*Content)[I],
- "an object representing EntityId");
-
- auto Id = IdFromJSON(*IdData);
-
- if (!Id)
- return Id.takeError();
-
- const json::Array *EdgesData = (*Content)[I + 1].getAsArray();
-
- if (!EdgesData)
- return makeSawButExpectedError((*Content)[I + 1],
- "an array of arrays representing EdgeSet");
-
- auto EntityEdges = edgeSetFromJSON(*EdgesData, IdFromJSON);
-
- if (!EntityEdges)
- return EntityEdges.takeError();
- Edges[*Id] = std::move(*EntityEdges);
- }
-
- auto Ret = std::make_unique<PointerFlowAnalysisResult>();
-
- Ret->Edges = std::move(Edges);
- return Ret;
-}
-
-JSONFormat::AnalysisResultRegistry::Add<PointerFlowAnalysisResult>
- RegisterPointerFlowResultForJSON(serializePointerFlowAnalysisResult,
- deserializePointerFlowAnalysisResult);
-
-class PointerFlowAnalysis final
- : public SummaryAnalysis<PointerFlowAnalysisResult,
- PointerFlowEntitySummary> {
-public:
- llvm::Error add(EntityId Id,
- const PointerFlowEntitySummary &Summary) override {
- auto EdgesOfEntity = getEdges(Summary);
-
- getResult().Edges[Id] = EdgeSet(EdgesOfEntity.begin(), EdgesOfEntity.end());
- return llvm::Error::success();
- }
-};
-
-AnalysisRegistry::Add<PointerFlowAnalysis>
- RegisterPointerFlowAnalysis("Whole-program pointer flow analysis");
-
-} // namespace
-
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int PointerFlowAnalysisAnchorSource = 0;
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
deleted file mode 100644
index ef5932c52a6c3..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowExtractor.cpp
+++ /dev/null
@@ -1,372 +0,0 @@
-//===- PointerFlowExtractor.cpp -------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "SSAFAnalysesCommon.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTTypeTraits.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/Stmt.h"
-#include "clang/AST/TypeBase.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"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/ADT/Sequence.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Error.h"
-#include <memory>
-#include <optional>
-
-namespace clang::ssaf {
-extern PointerFlowEntitySummary buildPointerFlowEntitySummary(EdgeSet Edges);
-} // namespace clang::ssaf
-
-namespace {
-using namespace clang;
-using namespace ssaf;
-
-class PointerFlowMatcher {
-public:
- EdgeSet Results;
- ASTContext &Ctx;
- TUSummaryExtractor &Extractor;
-
- PointerFlowMatcher(ASTContext &Ctx, TUSummaryExtractor &Extractor)
- : Ctx(Ctx), Extractor(Extractor) {}
-
- llvm::Error matches(const DynTypedNode &DynNode, const NamedDecl *RootDecl);
-
- llvm::Error matchesInitializerList(const ValueDecl *Base,
- const Expr *InitExpr,
- unsigned ArrayElementIndirectLevel = 0);
-
- llvm::Error matchesStmt(const Stmt *S, const NamedDecl *RootDecl);
-
- llvm::Error matchesDecl(const Decl *D, const NamedDecl *RootDecl);
-
-private:
- std::function<EntityId(const EntityName &)> AddEntity;
-
- Expected<EntityPointerLevelSet> toEPL(const NamedDecl *N,
- bool IsRet = false) const;
-
- Expected<EntityPointerLevelSet> toEPL(const Expr *N) const;
-
- llvm::Error addEdges(Expected<EntityPointerLevelSet> &&LHS,
- Expected<EntityPointerLevelSet> &&RHS);
-
- template <typename ParmsProvider, typename ArgsProvider>
- llvm::Error matchesArgsWithParams(unsigned ArgIdxStart, ParmsProvider *PP,
- ArgsProvider *AP) {
- unsigned ArgIdx = ArgIdxStart;
-
- for (unsigned ParmIdx = 0;
- ParmIdx < PP->getNumParams() && ArgIdx < AP->getNumArgs();
- ++ArgIdx, ++ParmIdx) {
- if (const ParmVarDecl *PD = PP->getParamDecl(ParmIdx);
- PD && hasPtrOrArrType(PD)) {
- if (auto Err = addEdges(toEPL(PD), toEPL(AP->getArg(ArgIdx))))
- return Err;
- }
- }
- return llvm::Error::success();
- }
-};
-
-Expected<EntityPointerLevelSet> PointerFlowMatcher::toEPL(const NamedDecl *N,
- bool IsRet) const {
- auto Ret = createEntityPointerLevel(N, Extractor, IsRet);
-
- if (Ret)
- return EntityPointerLevelSet{*Ret};
- return Ret.takeError();
-}
-
-Expected<EntityPointerLevelSet> PointerFlowMatcher::toEPL(const Expr *N) const {
- return translateEntityPointerLevel(N, Ctx, Extractor);
-}
-
-llvm::Error
-PointerFlowMatcher::addEdges(Expected<EntityPointerLevelSet> &&LHS,
- Expected<EntityPointerLevelSet> &&RHS) {
- if (!LHS && !RHS)
- return llvm::joinErrors(LHS.takeError(), RHS.takeError());
- if (!LHS)
- return LHS.takeError();
- if (!RHS)
- return RHS.takeError();
- if (RHS->empty())
- return llvm::Error::success();
- for (auto L : *LHS)
- Results[L].insert(RHS->begin(), RHS->end());
- return llvm::Error::success();
-}
-
-/// Match and extract pointer flow.
-/// The extraction function 'XF' can be described by the following rules:
-///
-/// XF(l = r) := add edge "toEPL(l) -> toEPL(r))"
-/// XF(foo(a, b, ...)) := XF(Param_1 = a), XF(Param_2 = b), ...
-/// XF(return e;) := XF(FunRet = e), where 'FunRet' is the return
-/// entity of the enclosing
-/// function
-/// XF(ctor(a, ...) : x1(y1), ... {...})
-/// := XF(Param_1 = a), ...,
-/// XF(x1 = y1), ...,
-/// ctor's body will be visited separately.
-/// XF(T var = e) := XF(var = e)
-/// XF(T var = init-list) := see \ref
-/// PointerFlowMatcher::matchInitializerList
-llvm::Error PointerFlowMatcher::matches(const DynTypedNode &DynNode,
- const NamedDecl *RootDecl) {
- if (const Stmt *S = DynNode.get<Stmt>())
- return matchesStmt(S, RootDecl);
- if (const Decl *D = DynNode.get<Decl>())
- return matchesDecl(D, RootDecl);
- return llvm::Error::success();
-}
-
-llvm::Error PointerFlowMatcher::matchesStmt(const Stmt *S,
- const NamedDecl *RootDecl) {
- // Match 'p = q' whenever it has pointer or array type:
- if (const auto *BO = dyn_cast<BinaryOperator>(S);
- BO && BO->getOpcode() == BO_Assign && hasPtrOrArrType(BO)) {
- return addEdges(toEPL(BO->getLHS()), toEPL(BO->getRHS()));
- }
-
- // Match arg-to-param passing (in CallExpr) for any pointer type argument:
- if (const auto *CE = dyn_cast<CallExpr>(S)) {
- const FunctionDecl *FD = CE->getDirectCallee();
-
- if (!FD)
- return llvm::Error::success();
-
- unsigned ArgIdx = 0;
-
- if (isa<CXXOperatorCallExpr>(CE))
- if (auto *MD = dyn_cast<CXXMethodDecl>(FD);
- MD && !MD->isExplicitObjectMemberFunction())
- ArgIdx = 1;
- return matchesArgsWithParams(ArgIdx, FD, CE);
- }
- // Match arg-to-param passing (in CXXConstructExpr) for any pointer type
- // argument:
- if (const auto *CCE = dyn_cast<CXXConstructExpr>(S)) {
- return matchesArgsWithParams(/*ArgIdxStart=*/0, CCE->getConstructor(), CCE);
- }
- if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
- const Expr *RetExpr = RS->getRetValue();
- if (!RetExpr || !hasPtrOrArrType(RetExpr))
- return llvm::Error::success();
- return addEdges(toEPL(RootDecl, true), toEPL(RetExpr));
- }
- return llvm::Error::success();
-}
-
-llvm::Error PointerFlowMatcher::matchesDecl(const Decl *D,
- const NamedDecl *RootDecl) {
- const Expr *InitExpr = nullptr;
-
- if (const auto *VD = dyn_cast<ValueDecl>(D)) {
- if (const auto *Var = dyn_cast<VarDecl>(VD))
- InitExpr = Var->getInit();
- if (const auto *Fd = dyn_cast<FieldDecl>(VD))
- InitExpr = Fd->getInClassInitializer();
-
- // Match initializer-list:
- if (auto *InitLst = dyn_cast_or_null<InitListExpr>(InitExpr))
- return matchesInitializerList(VD, InitLst);
-
- // Match initializers to variables/fields of a pointer type:
- if (InitExpr && hasPtrOrArrType(VD))
- return addEdges(toEPL(VD), toEPL(InitExpr));
- }
-
- // Match C++ constructor member-initializers:
- if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D)) {
- for (auto *E : CtorD->inits()) {
- if (E->isDelegatingInitializer())
- return matches(DynTypedNode::create(*E->getInit()), RootDecl);
- if (const FieldDecl *FD = E->getMember(); FD && hasPtrOrArrType(FD)) {
- if (auto Err = addEdges(toEPL(E->getMember()), toEPL(E->getInit())))
- return Err;
- }
- }
- }
- return llvm::Error::success();
-}
-
-// Helper function for matchInitializerList that handles record:
-llvm::Error matchInitializerListForRecordDecl(PointerFlowMatcher &Matcher,
- const RecordDecl *RecordTy,
- const InitListExpr *ILE) {
- if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RecordTy))
- if (CXXRD->getNumBases() != 0) {
- // FIXME: support this:
- return makeErrAtNode(
- Matcher.Ctx, ILE,
- "attempt to create pointer assignment edges between "
- "CXXRecordDecls with base classes and initializer-lists");
- }
- // Handle union:
- if (RecordTy->isUnion()) {
- auto *InitField = ILE->getInitializedFieldInUnion();
-
- if (!InitField || ILE->inits().empty())
- return llvm::Error::success();
- return Matcher.matchesInitializerList(InitField, ILE->getInit(0));
- }
- // Handle struct/class:
- ILE = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm();
-
- auto FieldIter = RecordTy->field_begin();
-
- assert(RecordTy->getNumFields() >= ILE->getNumInits());
- for (auto *Init : ILE->inits())
- if (auto Err = Matcher.matchesInitializerList(*(FieldIter++), Init))
- return Err;
- return llvm::Error::success();
-}
-
-// Helper function for matchInitializerList that handles array:
-llvm::Error matchInitializerListForArray(PointerFlowMatcher &Matcher,
- const ValueDecl *Array,
- const InitListExpr *ILE,
- unsigned ArrayIndirectLevel = 0) {
- for (auto *E : ILE->inits())
- if (auto Err =
- Matcher.matchesInitializerList(Array, E, ArrayIndirectLevel + 1))
- return Err;
- return llvm::Error::success();
-}
-
-/// Match initializer lists of the form 'Var = {a, b, c, ...}':
-///
-/// If 'Var' is a struct/union:
-/// XF(Var = {a, b, c, ...}) := XF(Var.field_1 = a)
-/// XF(Var.field_2 = b)
-/// ...
-/// If 'Var' is an array:
-/// XF(Var = {a, b, c, ...}) := XF(*Var = a)
-/// XF(*Var = b)
-/// ...
-///
-/// The process is recursive: 'a', 'b', 'c', ... may themselves be
-/// initializer lists. We therefore use \p ArrayElementIndirectLevel to keep
-/// track of the pointer level the left-hand side.
-llvm::Error
-PointerFlowMatcher::matchesInitializerList(const ValueDecl *Base,
- const Expr *InitExpr,
- unsigned ArrayElementIndirectLevel) {
- const InitListExpr *ILE = dyn_cast<InitListExpr>(InitExpr);
-
- if (!ILE) {
- if (!hasPtrOrArrType(InitExpr))
- return llvm::Error::success();
-
- auto BaseEPL = toEPL(Base);
-
- if (!BaseEPL)
- return BaseEPL.takeError();
-
- // Apply ArrayElementIndirectLevel to BaseEPL
- auto R = llvm::map_range(*BaseEPL, [&ArrayElementIndirectLevel](
- const EntityPointerLevel &EPL) {
- EntityPointerLevel Result = EPL;
- for ([[maybe_unused]] auto Ignored : llvm::seq(ArrayElementIndirectLevel))
- Result = incrementPointerLevel(Result);
- return Result;
- });
- return addEdges(EntityPointerLevelSet{R.begin(), R.end()}, toEPL(InitExpr));
- }
- // Note that `Base`'s type is NOT the real LHS type when
- // ArrayElementIndirectLevel > 0:
- QualType Type = InitExpr->getType();
-
- if (auto *RD = Type->getAsRecordDecl())
- return matchInitializerListForRecordDecl(*this, RD, ILE);
- if (Type->isArrayType())
- return matchInitializerListForArray(*this, Base, ILE,
- ArrayElementIndirectLevel);
-
- // Must be the case of using a initializer-list for a scalar.
- // The initializer-list can be either singleton or empty:
- if (ILE->getNumInits() == 0)
- return llvm::Error::success();
- return matchesInitializerList(Base, ILE->getInit(0));
-}
-
-class PointerFlowTUSummaryExtractor : public TUSummaryExtractor {
-public:
- using TUSummaryExtractor::TUSummaryExtractor;
-
- /// \return a non-null unique pointer to a PointerFlowEntitySummary
- std::unique_ptr<PointerFlowEntitySummary>
- extractEntitySummary(const NamedDecl *Contributor, ASTContext &Ctx,
- TUSummaryExtractor &Extractor) {
- PointerFlowMatcher Matcher(Ctx, Extractor);
- auto MatchAction = [&Matcher, &Contributor](const DynTypedNode &Node) {
- auto Err = Matcher.matches(Node, Contributor);
-
- if (Err)
- logWarningFromError(std::move(Err));
- };
-
- findMatchesIn(Contributor, MatchAction);
- return std::make_unique<PointerFlowEntitySummary>(
- buildPointerFlowEntitySummary(std::move(Matcher.Results)));
- }
-
- void HandleTranslationUnit(ASTContext &Ctx) override {
- std::vector<const NamedDecl *> Contributors;
-
- findContributors(Ctx, 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
- // instantiations.
- if (CD->isTemplated())
- continue;
-
- auto EntitySummary = extractEntitySummary(CD, Ctx, *this);
-
- assert(EntitySummary);
- if (EntitySummary->empty())
- continue;
-
- std::optional<EntityId> ContributorId = addEntity(CD);
- if (!ContributorId) {
- logWarningFromError(makeEntityNameErr(Ctx, CD));
- continue;
- }
-
- [[maybe_unused]] auto [_, InsertionSucceeded] =
- SummaryBuilder.addSummary(*ContributorId, std::move(EntitySummary));
-
- assert(InsertionSucceeded && "duplicated contributor extraction");
- }
- }
-};
-} // namespace
-
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int PointerFlowExtractorAnchorSource = 0;
-} // namespace clang::ssaf
-
-static TUSummaryExtractorRegistry::Add<PointerFlowTUSummaryExtractor>
- RegisterExtractor(PointerFlowEntitySummary::Name,
- "Extract pointer flow information");
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
deleted file mode 100644
index 146a815e0e55d..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-//===- PointerFlowFormat.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowFormat.h"
-#include "SSAFAnalysesCommon.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "llvm/ADT/iterator_range.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/JSON.h"
-
-using namespace clang;
-using namespace ssaf;
-using Object = llvm::json::Object;
-using Array = llvm::json::Array;
-using Value = llvm::json::Value;
-
-ssaf::PointerFlowEntitySummary
-ssaf::buildPointerFlowEntitySummary(EdgeSet Edges);
-
-llvm::iterator_range<EdgeSet::const_iterator>
-ssaf::getEdges(const PointerFlowEntitySummary &Sum);
-
-namespace {
-constexpr const char *const PointerFlowKey = "PointerFlow";
-} // namespace
-
-// Writes an EdgeSet as an array of arrays of EntityPointerLevels:
-// [
-// [ [src-node], [dest-node], [dest-node], ...],
-// [ [src-node], [dest-node], [dest-node], ...],
-// ...
-// ]
-Array clang::ssaf::edgeSetToJSON(
- llvm::iterator_range<EdgeSet::const_iterator> Edges,
- JSONFormat::EntityIdToJSONFn EntityId2JSON) {
- Array EdgesData;
-
- for (const auto &[LHS, RHSSet] : Edges) {
- Array EdgeEntry;
- EdgeEntry.push_back(entityPointerLevelToJSON(LHS, EntityId2JSON));
- for (const auto &RHS : RHSSet)
- EdgeEntry.push_back(entityPointerLevelToJSON(RHS, EntityId2JSON));
- EdgesData.push_back(Value(std::move(EdgeEntry)));
- }
- return EdgesData;
-}
-
-llvm::Expected<EdgeSet>
-clang::ssaf::edgeSetFromJSON(const Array &EdgesData,
- JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
- EdgeSet Edges;
-
- for (const auto &EdgesEntryData : EdgesData) {
- const auto *EPLArray = EdgesEntryData.getAsArray();
-
- if (!EPLArray || EPLArray->size() <= 1)
- return makeSawButExpectedError(
- EdgesEntryData, "a JSON array of EntityPointerLevels with a size "
- "greater than 1: [src, dest, dest, ...]");
-
- auto SrcEPL =
- entityPointerLevelFromJSON(*EPLArray->begin(), EntityIdFromJSON);
-
- if (!SrcEPL)
- return SrcEPL.takeError();
- for (const auto &EPLData :
- llvm::make_range(EPLArray->begin() + 1, EPLArray->end())) {
- auto EPL = entityPointerLevelFromJSON(EPLData, EntityIdFromJSON);
- if (!EPL)
- return EPL.takeError();
- Edges[*SrcEPL].insert(*EPL);
- }
- }
- return Edges;
-}
-
-static llvm::json::Object
-summaryToJSON(const EntitySummary &ES,
- JSONFormat::EntityIdToJSONFn EntityId2JSON) {
- Object Data;
- Data[PointerFlowKey] = Value(
- edgeSetToJSON(getEdges(static_cast<const PointerFlowEntitySummary &>(ES)),
- EntityId2JSON));
- return Data;
-}
-
-static llvm::Expected<std::unique_ptr<EntitySummary>>
-summaryFromJSON(const Object &Data, EntityIdTable &,
- JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
- const Value *EdgesData = Data.get(PointerFlowKey);
-
- if (!EdgesData)
- return makeSawButExpectedError(
- Object(Data), "a JSON object with the key: %s", PointerFlowKey);
-
- const auto *EdgesDataAsArr = EdgesData->getAsArray();
-
- if (!EdgesDataAsArr)
- return makeSawButExpectedError(
- *EdgesData, "a JSON array of array of EntityPointerLevels");
-
- auto Edges = edgeSetFromJSON(*EdgesDataAsArr, EntityIdFromJSON);
-
- if (!Edges)
- return Edges.takeError();
- return std::make_unique<PointerFlowEntitySummary>(
- buildPointerFlowEntitySummary(std::move(*Edges)));
-}
-
-namespace {
-struct PointerFlowJSONFormatInfo final : JSONFormat::FormatInfo {
- PointerFlowJSONFormatInfo()
- : JSONFormat::FormatInfo(PointerFlowEntitySummary::summaryName(),
- summaryToJSON, summaryFromJSON) {}
-};
-} // namespace
-
-static llvm::Registry<JSONFormat::FormatInfo>::Add<PointerFlowJSONFormatInfo>
- RegisterPointerFlowJSONFormatInfo(
- "PointerFlow", "JSON Format info for PointerFlowEntitySummary");
-
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int PointerFlowJSONFormatAnchorSource = 0;
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
deleted file mode 100644
index 660bc424fb32f..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-//===- SSAFAnalysesCommon.cpp ---------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "SSAFAnalysesCommon.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/DynamicRecursiveASTVisitor.h"
-#include "clang/AST/ExprCXX.h"
-#include <set>
-
-using namespace clang;
-
-std::string ssaf::describeJSONValue(const llvm::json::Value &V) {
- return llvm::formatv("{0:2}", V).str();
-}
-
-std::string ssaf::describeJSONValue(const llvm::json::Array &A) {
- return llvm::formatv("array of size {0}", A.size()).str();
-}
-
-std::string ssaf::describeJSONValue(const llvm::json::Object &O) {
- return llvm::formatv("an object of {0} key(s)", O.size()).str();
-}
-
-namespace {
-// Traverses the AST and finds contributors.
-class ContributorFinder : public DynamicRecursiveASTVisitor {
-public:
- std::set<const NamedDecl *> Contributors;
-
- ContributorFinder() {
- ShouldVisitTemplateInstantiations = true;
- ShouldVisitImplicitCode = false;
- }
-
- bool VisitFunctionDecl(FunctionDecl *D) override {
- Contributors.insert(D);
- return true;
- }
-
- bool VisitRecordDecl(RecordDecl *D) override {
- Contributors.insert(D);
- return true;
- }
-
- bool VisitVarDecl(VarDecl *D) override {
- DeclContext *DC = D->getDeclContext();
-
- // Collects Decl for global variables or static data members:
- if (DC->isFileContext() || D->isStaticDataMember())
- Contributors.insert(D);
- return true;
- }
-
- bool VisitLambdaExpr(LambdaExpr *L) override {
- // TraverseLambdaExpr directly visits the body stmt, skipping the
- // CXXMethodDecl, which is a contributor that needs to be collected.
- VisitFunctionDecl(L->getCallOperator());
- return true;
- }
-};
-
-/// An AST visitor that skips the root node's strict-descendants that are
-/// callable Decls and record Decls, because those are separate contributors.
-///
-/// Clients need to implement their own "MatchAction", which is a function that
-/// takes a `DynTypedNode`, decides if the node matches and performs any further
-/// callback actions.
-/// ContributorFactFinder takes a reference to a "MatchAction". It does not own
-/// the "MatchAction", which is usually stateful and may own containers.
-class ContributorFactFinder : public DynamicRecursiveASTVisitor {
- llvm::function_ref<void(const DynTypedNode &)> MatchActionRef;
- const NamedDecl *RootDecl = nullptr;
-
- template <typename NodeTy> void match(const NodeTy &Node) {
- MatchActionRef(DynTypedNode::create(Node));
- }
-
-public:
- ContributorFactFinder(
- llvm::function_ref<void(const DynTypedNode &)> MatchActionRef)
- : MatchActionRef(MatchActionRef) {
- ShouldVisitTemplateInstantiations = true;
- ShouldVisitImplicitCode = false;
- }
-
- // The entry point:
- void findMatches(const NamedDecl *Contributor) {
- RootDecl = Contributor;
- TraverseDecl(const_cast<NamedDecl *>(Contributor));
- }
-
- bool TraverseDecl(Decl *Node) override {
- if (!Node)
- return true;
- // To skip callables:
- if (Node != RootDecl &&
- isa<FunctionDecl, BlockDecl, ObjCMethodDecl, RecordDecl>(Node))
- return true;
- match(*Node);
- return DynamicRecursiveASTVisitor::TraverseDecl(Node);
- }
-
- bool TraverseStmt(Stmt *Node) override {
- if (!Node)
- return true;
- match(*Node);
- return DynamicRecursiveASTVisitor::TraverseStmt(Node);
- }
-
- bool TraverseLambdaExpr(LambdaExpr *L) override {
- // TODO: lambda captures of pointer variables (by copy or by reference)
- // are currently not tracked. Each capture initializes an implicit closure
- // field from the captured variable, which constitutes a pointer assignment
- // edge that should be recorded here.
- return true; // Skip lambda as it is a callable.
- }
-};
-} // namespace
-
-void ssaf::findContributors(ASTContext &Ctx,
- std::vector<const NamedDecl *> &Contributors) {
- ContributorFinder Finder;
- Finder.TraverseAST(Ctx);
- Contributors.insert(Contributors.end(), Finder.Contributors.begin(),
- Finder.Contributors.end());
-}
-
-void ssaf::findMatchesIn(
- const NamedDecl *Contributor,
- llvm::function_ref<void(const DynTypedNode &)> MatchActionRef) {
- ContributorFactFinder{MatchActionRef}.findMatches(Contributor);
-}
-
-llvm::Error clang::ssaf::makeEntityNameErr(clang::ASTContext &Ctx,
- const clang::NamedDecl *D) {
- return makeErrAtNode(Ctx, D, "failed to create entity name for %s",
- D->getNameAsString().data());
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h b/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
deleted file mode 100644
index 38c37e7103b73..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/SSAFAnalysesCommon.h
+++ /dev/null
@@ -1,82 +0,0 @@
-//===- SSAFAnalysesCommon.h -------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Common code in SSAF analyses implementations
-//
-//===----------------------------------------------------------------------===//
-#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/Debug.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace clang::ssaf {
-///\return a short descriptions of a json::Value
-std::string describeJSONValue(const llvm::json::Value &V);
-///\return a short descriptions of a json::Array
-std::string describeJSONValue(const llvm::json::Array &A);
-///\return a short descriptions of a json::Object
-std::string describeJSONValue(const llvm::json::Object &O);
-
-template <typename NodeTy, typename... Ts>
-llvm::Error makeErrAtNode(clang::ASTContext &Ctx, const NodeTy *N,
- llvm::StringRef Fmt, const Ts &...Args) {
- std::string LocStr = N->getBeginLoc().printToString(Ctx.getSourceManager());
- return llvm::createStringError((Fmt + " at %s").str().c_str(), Args...,
- LocStr.c_str());
-}
-
-template <typename JSONTy, typename... Ts>
-llvm::Error makeSawButExpectedError(const JSONTy &Saw, llvm::StringRef Expected,
- const Ts &...ExpectedArgs) {
- std::string Fmt = ("saw %s but expected " + Expected).str();
- std::string SawStr = describeJSONValue(Saw);
-
- return llvm::createStringError(Fmt.c_str(), SawStr.c_str(), ExpectedArgs...);
-}
-
-///\return true iff expression `E` has pointer or array type.
-inline bool hasPtrOrArrType(const Expr *E) {
- return llvm::isa<clang::PointerType, clang::ArrayType>(
- E->getType().getCanonicalType());
-}
-
-///\return true iff Decl `D` has (reference-to) pointer or array type.
-inline bool hasPtrOrArrType(const ValueDecl *D) {
- return llvm::isa<clang::PointerType, clang::ArrayType>(
- D->getType().getNonReferenceType().getCanonicalType());
-}
-
-llvm::Error makeEntityNameErr(clang::ASTContext &Ctx,
- const clang::NamedDecl *D);
-
-/// Log a warning from an llvm::Error
-inline void logWarningFromError(llvm::Error Err) {
- DEBUG_WITH_TYPE("ssaf-analyses", llvm::errs() << Err);
- llvm::consumeError(std::move(Err));
-}
-
-/// Find all contributors in an AST.
-void findContributors(ASTContext &Ctx,
- std::vector<const NamedDecl *> &Contributors);
-
-/// Perform "MatchAction" on each Stmt and Decl belonging to the `Contributor`.
-/// \param Contributor
-/// \param MatchActionRef a reference (view) to a "MatchAction"
-void findMatchesIn(
- const NamedDecl *Contributor,
- llvm::function_ref<void(const DynTypedNode &)> MatchActionRef);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_SCALABLESTATICANALYSISFRAMEWORK_ANALYSES_SSAFANALYSESCOMMON_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
deleted file mode 100644
index 86545762c0121..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-//===- UnsafeBufferUsage.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-
-using namespace clang;
-using namespace ssaf;
-
-UnsafeBufferUsageEntitySummary
-ssaf::buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers) {
- return UnsafeBufferUsageEntitySummary(std::move(UnsafeBuffers));
-}
-
-llvm::iterator_range<EntityPointerLevelSet::const_iterator>
-ssaf::getUnsafeBuffers(const UnsafeBufferUsageEntitySummary &S) {
- return llvm::make_range(S.UnsafeBuffers.begin(), S.UnsafeBuffers.end());
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
deleted file mode 100644
index 6ca8c5176d21b..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
+++ /dev/null
@@ -1,250 +0,0 @@
-//===- UnsafeBufferUsageAnalysis.cpp - WPA for UnsafeBufferUsage ----------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-// UnsafeBufferUsageAnalysis is a noop analysis.
-//
-// UnsafeBufferUsageAnalysisResult is a map from EntityIds to
-// EntityPointerLevelSets
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h"
-#include "SSAFAnalysesCommon.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/JSON.h"
-#include <memory>
-
-using namespace clang::ssaf;
-using namespace llvm;
-
-namespace {
-
-json::Object serializeUnsafeBufferUsageAnalysisResult(
- const UnsafeBufferUsageAnalysisResult &R,
- JSONFormat::EntityIdToJSONFn IdToJSON) {
- json::Object Result;
-
- Result[UnsafeBufferUsageAnalysisResultName] =
- entityPointerLevelMapToJSON(R.UnsafeBuffers, IdToJSON);
- return Result;
-}
-
-Expected<std::unique_ptr<AnalysisResult>>
-deserializeUnsafeBufferUsageAnalysisResult(
- const json::Object &Obj, JSONFormat::EntityIdFromJSONFn IdFromJSON) {
- const json::Array *Content =
- Obj.getArray(UnsafeBufferUsageAnalysisResultName);
-
- if (!Content)
- return makeSawButExpectedError(Obj, "an object with a key %s",
- UnsafeBufferUsageAnalysisResultName.data());
-
- auto UnsafeBuffers = entityPointerLevelMapFromJSON(*Content, IdFromJSON);
-
- if (!UnsafeBuffers)
- return UnsafeBuffers.takeError();
-
- auto Ret = std::make_unique<UnsafeBufferUsageAnalysisResult>();
-
- Ret->UnsafeBuffers = std::move(*UnsafeBuffers);
- return Ret;
-}
-
-JSONFormat::AnalysisResultRegistry::Add<UnsafeBufferUsageAnalysisResult>
- RegisterUnsafeBufferUsageResultForJSON(
- serializeUnsafeBufferUsageAnalysisResult,
- deserializeUnsafeBufferUsageAnalysisResult);
-
-class UnsafeBufferUsageAnalysis final
- : public SummaryAnalysis<UnsafeBufferUsageAnalysisResult,
- UnsafeBufferUsageEntitySummary> {
-public:
- llvm::Error add(EntityId Id,
- const UnsafeBufferUsageEntitySummary &Summary) override {
- auto UnsafeBuffersOfEntity = getUnsafeBuffers(Summary);
-
- getResult().UnsafeBuffers[Id] = EntityPointerLevelSet(
- UnsafeBuffersOfEntity.begin(), UnsafeBuffersOfEntity.end());
- return llvm::Error::success();
- }
-};
-
-AnalysisRegistry::Add<UnsafeBufferUsageAnalysis>
- RegisterUnsafeBufferUsageAnalysis(
- "Whole-program unsafe buffer usage analysis");
-
-//===----------------------------------------------------------------------===//
-// UnsafeBufferReachableAnalysis---computes reachable unsafe buffer nodes
-//===----------------------------------------------------------------------===//
-
-json::Object serializeUnsafeBufferReachableAnalysisResult(
- const UnsafeBufferReachableAnalysisResult &R,
- JSONFormat::EntityIdToJSONFn IdToJSON) {
- json::Object Result;
-
- Result[UnsafeBufferReachableAnalysisResultName] =
- entityPointerLevelMapToJSON(R.Reachables, IdToJSON);
- return Result;
-}
-
-Expected<std::unique_ptr<AnalysisResult>>
-deserializeUnsafeBufferReachableAnalysisResult(
- const json::Object &Obj, JSONFormat::EntityIdFromJSONFn IdFromJSON) {
- const json::Array *Content =
- Obj.getArray(UnsafeBufferReachableAnalysisResultName);
-
- if (!Content)
- return makeSawButExpectedError(
- Obj, "an object with a key %s",
- UnsafeBufferReachableAnalysisResultName.data());
-
- auto Reachables = entityPointerLevelMapFromJSON(*Content, IdFromJSON);
-
- if (!Reachables)
- return Reachables.takeError();
-
- auto Ret = std::make_unique<UnsafeBufferReachableAnalysisResult>();
-
- Ret->Reachables = std::move(*Reachables);
- return Ret;
-}
-
-JSONFormat::AnalysisResultRegistry::Add<UnsafeBufferReachableAnalysisResult>
- RegisterUnsafeBufferReachableResultForJSON(
- serializeUnsafeBufferReachableAnalysisResult,
- deserializeUnsafeBufferReachableAnalysisResult);
-
-/// Computes all the reachable "nodes" (pointers) in a pointer flow graph from a
-/// provided starter node set. Specifically, the starter set is the unsafe
-/// pointers found by `UnsafeBufferUsageAnalysis`.
-class UnsafeBufferReachableAnalysis
- : public DerivedAnalysis<UnsafeBufferReachableAnalysisResult,
- PointerFlowAnalysisResult,
- UnsafeBufferUsageAnalysisResult> {
-
- /// BoundsPropagationGraph adds bounds propagation semantics to the
- /// pointer-flow graph, which represents the set of static pointer assignment
- /// sites collected from the source code. Consider the following example:
- ///
- /// void f(int ***p, int **q) {
- /// *p = q;
- /// (**p)[5] = 0;
- /// }
- ///
- /// There is one static pointer assignment thus one pointer-flow edge: (p, 2)
- /// -> (q, 1). In terms of bounds propagation, this assignment implies that if
- /// 'p' at pointer level 2 requires bounds, 'q' at pointer level 1 must also
- /// have them. Furthermore, this relationship propagates to deeper indirection
- /// levels: if 'p' at level 3 requires bounds, so does 'q' at level 2.
- ///
- /// In the example above, `(**p)` requires bounds (due to the array index),
- /// and therefore `*q` must require bounds as well.
- ///
- /// To generalize the idea, the BoundsPropagationGraph is defined as a super
- /// graph of the input pointer-flow graph by:
- ///
- /// For each edge (src, i) -> (dest, j) in the pointer-flow graph, the
- /// BoundsPropagationGraph has a finite set of edges
- /// {(src, i + d) -> (dest, j + d) | 0 <= d < UB}, where UB is an upper
- /// bound based on the maximum pointer level the pointer type can have.
- struct BoundsPropagationGraph {
- private:
- const std::map<EntityPointerLevel, EntityPointerLevelSet> &PointerFlows;
-
- public:
- BoundsPropagationGraph(const EdgeSet &PointerFlows)
- : PointerFlows(PointerFlows) {}
-
- /// Returns the EntityPointerLevelSet that are reachable from \p Src by
- /// one edge in the BoundsPropagationGraph.
- EntityPointerLevelSet getDestNodes(const EntityPointerLevel &Src) const {
- unsigned SrcPtrLv = Src.getPointerLevel();
- EntityPointerLevelSet Result;
-
- for (unsigned P = 1; P <= SrcPtrLv; ++P) {
- auto I = PointerFlows.find(buildEntityPointerLevel(Src.getEntity(), P));
-
- if (I != PointerFlows.end()) {
- unsigned Delta = SrcPtrLv - P;
- for (const auto &EPL : I->second)
- Result.insert(buildEntityPointerLevel(
- EPL.getEntity(), EPL.getPointerLevel() + Delta));
- }
- }
- return Result;
- }
- };
-
- std::map<EntityId, BoundsPropagationGraph> BPG;
-
- // Use pointers for efficiency. EPLs are in tree-based containers that only
- // grow. So pointers to them are stable.
- using EPLPtr = const EntityPointerLevel *;
-
- // Find all outgoing edges from `EPL` in the `Graph`, insert their
- // destination nodes into `Reachables`, and add newly discovered nodes to
- // `Worklist`:
- void updateReachablesWithOutgoings(EPLPtr EPL,
- std::vector<EPLPtr> &WorkList) {
- for (auto &[Id, SubGraph] : BPG) {
- auto R = SubGraph.getDestNodes(*EPL);
-
- for (const auto &Dst : R) {
- auto [It, Inserted] = getResult().Reachables[Id].insert(Dst);
- if (Inserted)
- WorkList.push_back(&*It);
- }
- }
- }
-
-public:
- llvm::Error
- initialize(const PointerFlowAnalysisResult &PtrFlowGraph,
- const UnsafeBufferUsageAnalysisResult &Starter) override {
- for (auto &[Id, SubGraph] : PtrFlowGraph.Edges)
- BPG.try_emplace(Id, BoundsPropagationGraph(SubGraph));
- assert(getResult().Reachables.empty());
- getResult().Reachables.insert(Starter.begin(), Starter.end());
- return llvm::Error::success();
- }
-
- llvm::Expected<bool> step() override {
- auto &Reachables = getResult().Reachables;
- // Simple DFS:
- std::vector<EPLPtr> Worklist;
-
- for (auto &[Id, EPLs] : Reachables)
- for (auto &EPL : EPLs)
- Worklist.push_back(&EPL);
-
- while (!Worklist.empty()) {
- EPLPtr Node = Worklist.back();
- Worklist.pop_back();
-
- updateReachablesWithOutgoings(Node, Worklist);
- }
- // This is not an iterative algorithm so stop iteration by retruning false:
- return false;
- }
-};
-
-AnalysisRegistry::Add<UnsafeBufferReachableAnalysis>
- RegisterUnsafeBufferReachableAnalysis(
- "Reachable pointers from unsafe buffer usage in pointer flow graph");
-
-} // namespace
-
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int UnsafeBufferUsageAnalysisAnchorSource = 0;
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
deleted file mode 100644
index f4067e5f315ff..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+++ /dev/null
@@ -1,110 +0,0 @@
-//===- UnsafeBufferUsageExtractor.cpp -------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "SSAFAnalysesCommon.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/DynamicRecursiveASTVisitor.h"
-#include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/ErrorHandling.h"
-
-using namespace clang;
-using namespace ssaf;
-
-namespace clang::ssaf {
-class UnsafeBufferUsageTUSummaryExtractor : public TUSummaryExtractor {
-public:
- UnsafeBufferUsageTUSummaryExtractor(TUSummaryBuilder &Builder)
- : TUSummaryExtractor(Builder) {}
-
- /// \return a non-null unique pointer to a UnsafeBufferUsageEntitySummary
- std::unique_ptr<UnsafeBufferUsageEntitySummary>
- extractEntitySummary(const NamedDecl *Contributor, ASTContext &Ctx);
- void HandleTranslationUnit(ASTContext &Ctx) override;
-};
-} // namespace clang::ssaf
-
-std::unique_ptr<UnsafeBufferUsageEntitySummary>
-clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::extractEntitySummary(
- const NamedDecl *Contributor, ASTContext &Ctx) {
- std::set<const Expr *> UnsafePointers;
-
- auto MatchAction = [&UnsafePointers, &Ctx](const DynTypedNode &Node) {
- matchUnsafePointers(Node, Ctx, UnsafePointers);
- };
- findMatchesIn(Contributor, MatchAction);
-
- EntityPointerLevelSet Results;
-
- for (const Expr *Ptr : UnsafePointers) {
- Expected<EntityPointerLevelSet> Translation =
- translateEntityPointerLevel(Ptr, Ctx, *this);
-
- if (Translation) {
- // Filter out those temporary invalid EntityPointerLevels associated
- // with `&E` pointers. They need no transformation of entities:
- auto FilteredTranslation = llvm::make_filter_range(
- *Translation, [](const EntityPointerLevel &E) -> bool {
- return E.getPointerLevel() > 0;
- });
- Results.insert(FilteredTranslation.begin(), FilteredTranslation.end());
- continue;
- }
- logWarningFromError(Translation.takeError());
- }
-
- return std::make_unique<UnsafeBufferUsageEntitySummary>(
- UnsafeBufferUsageEntitySummary(std::move(Results)));
-}
-
-void clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
- ASTContext &Ctx) {
- std::vector<const NamedDecl *> Contributors;
-
- findContributors(Ctx, 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
- // instantiations.
- if (CD->isTemplated())
- continue;
-
- auto EntitySummary = extractEntitySummary(CD, Ctx);
-
- assert(EntitySummary);
- if (EntitySummary->empty())
- continue;
-
- auto ContributorId = addEntity(CD);
-
- if (!ContributorId) {
- logWarningFromError(makeEntityNameErr(Ctx, CD));
- continue;
- }
-
- [[maybe_unused]] auto [Ignored, InsertionSucceeded] =
- SummaryBuilder.addSummary(*ContributorId, std::move(EntitySummary));
-
- assert(InsertionSucceeded && "duplicated contributor extraction");
- }
-}
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int UnsafeBufferUsageExtractorAnchorSource = 0;
-} // namespace clang::ssaf
-
-static clang::ssaf::TUSummaryExtractorRegistry::Add<
- UnsafeBufferUsageTUSummaryExtractor>
- RegisterExtractor(UnsafeBufferUsageEntitySummary::Name,
- "Extract unsafe buffer pointers");
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp b/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
deleted file mode 100644
index ff6ab3886941d..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//===- UnsafeBufferUsageFormat.cpp ----------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "SSAFAnalysesCommon.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/JSON.h"
-
-using namespace clang;
-using namespace ssaf;
-using Array = llvm::json::Array;
-using Object = llvm::json::Object;
-
-static constexpr llvm::StringLiteral SummarySerializationKey = "UnsafeBuffers";
-
-extern UnsafeBufferUsageEntitySummary
-ssaf::buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers);
-
-extern llvm::iterator_range<EntityPointerLevelSet::const_iterator>
-ssaf::getUnsafeBuffers(const UnsafeBufferUsageEntitySummary &S);
-
-static Object serialize(const EntitySummary &S,
- JSONFormat::EntityIdToJSONFn Fn) {
- const auto &SS = static_cast<const UnsafeBufferUsageEntitySummary &>(S);
- Array UnsafeBuffersData;
-
- for (const auto &EPL : getUnsafeBuffers(SS))
- UnsafeBuffersData.push_back(entityPointerLevelToJSON(EPL, Fn));
- return Object{{SummarySerializationKey.data(), std::move(UnsafeBuffersData)}};
-}
-
-static llvm::Expected<std::unique_ptr<EntitySummary>>
-deserializeImpl(const Object &Data, JSONFormat::EntityIdFromJSONFn Fn) {
- const Array *UnsafeBuffersData =
- Data.getArray(SummarySerializationKey.data());
-
- if (!UnsafeBuffersData)
- return makeSawButExpectedError(Object(Data), "an Object with a key %s",
- SummarySerializationKey.data());
-
- EntityPointerLevelSet EPLs;
-
- for (const auto &EltData : *UnsafeBuffersData) {
- llvm::Expected<EntityPointerLevel> EPL =
- entityPointerLevelFromJSON(EltData, Fn);
-
- if (!EPL)
- return EPL.takeError();
- EPLs.insert(*EPL);
- }
- return std::make_unique<UnsafeBufferUsageEntitySummary>(
- buildUnsafeBufferUsageEntitySummary(std::move(EPLs)));
-}
-
-static llvm::Expected<std::unique_ptr<EntitySummary>>
-deserialize(const Object &Data, EntityIdTable &,
- JSONFormat::EntityIdFromJSONFn Fn) {
- return deserializeImpl(Data, Fn);
-}
-
-namespace {
-struct UnsafeBufferUsageJSONFormatInfo final : JSONFormat::FormatInfo {
- UnsafeBufferUsageJSONFormatInfo()
- : JSONFormat::FormatInfo(UnsafeBufferUsageEntitySummary::summaryName(),
- serialize, deserialize) {}
-};
-} // namespace
-
-static llvm::Registry<JSONFormat::FormatInfo>::Add<
- UnsafeBufferUsageJSONFormatInfo>
- RegisterUnsafeBufferUsageJSONFormatInfo(
- UnsafeBufferUsageEntitySummary::Name,
- "JSON Format info for UnsafeBufferUsageEntitySummary");
-
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int UnsafeBufferUsageJSONFormatAnchorSource = 0;
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt
deleted file mode 100644
index b214c06644db7..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-add_subdirectory(Analyses)
-add_subdirectory(Core)
-add_subdirectory(Frontend)
-add_subdirectory(Plugins)
-add_subdirectory(SourceTransformation)
-add_subdirectory(Tool)
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.cpp
deleted file mode 100644
index cac27b2c3f278..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-//===- ASTMapping.cpp - AST to SSAF Entity mapping ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements utilities for mapping AST declarations to SSAF entities.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "clang/AST/Decl.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/UnifiedSymbolResolution/USRGeneration.h"
-#include "llvm/ADT/SmallString.h"
-
-namespace clang::ssaf {
-
-std::optional<EntityName> getEntityName(const Decl *D) {
- if (!D)
- return std::nullopt;
-
- if (D->isImplicit())
- return std::nullopt;
-
- if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->getBuiltinID())
- return std::nullopt;
-
- if (!isa<FunctionDecl, ParmVarDecl, VarDecl, FieldDecl, RecordDecl>(D))
- return std::nullopt;
-
- llvm::SmallString<16> Suffix;
- const Decl *USRDecl = D;
-
- // For parameters, use the parent function's USR with parameter index as
- // suffix
- if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
- const auto *FD =
- dyn_cast_or_null<FunctionDecl>(PVD->getParentFunctionOrMethod());
- if (!FD)
- return std::nullopt;
- USRDecl = FD;
-
- const auto ParamIdx = PVD->getFunctionScopeIndex();
- llvm::raw_svector_ostream OS(Suffix);
- // Parameter uses function's USR with 1-based index as suffix
- OS << (ParamIdx + 1);
- }
-
- llvm::SmallString<128> USRBuf;
- if (clang::index::generateUSRForDecl(USRDecl, USRBuf))
- return std::nullopt;
-
- if (USRBuf.empty())
- return std::nullopt;
-
- return EntityName(USRBuf.str(), Suffix, {});
-}
-
-std::optional<EntityName> getEntityNameForReturn(const FunctionDecl *FD) {
- if (!FD)
- return std::nullopt;
-
- if (FD->isImplicit())
- return std::nullopt;
-
- if (FD->getBuiltinID())
- return std::nullopt;
-
- llvm::SmallString<128> USRBuf;
- if (clang::index::generateUSRForDecl(FD, USRBuf)) {
- return std::nullopt;
- }
-
- if (USRBuf.empty())
- return std::nullopt;
-
- return EntityName(USRBuf.str(), /*Suffix=*/"0", /*Namespace=*/{});
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
deleted file mode 100644
index bcaf5db7f3093..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Support
- TargetParser
- )
-
-add_clang_library(clangScalableStaticAnalysisFrameworkCore
- ASTEntityMapping.cpp
- EntityLinker/EntityLinker.cpp
- Model/BuildNamespace.cpp
- Model/EntityId.cpp
- Model/EntityIdTable.cpp
- Model/EntityLinkage.cpp
- Model/EntityName.cpp
- Model/SummaryName.cpp
- Serialization/JSONFormat/Artifact.cpp
- Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
- Serialization/JSONFormat/JSONFormatImpl.cpp
- Serialization/JSONFormat/LUSummary.cpp
- Serialization/JSONFormat/LUSummaryEncoding.cpp
- Serialization/JSONFormat/TUSummary.cpp
- Serialization/JSONFormat/TUSummaryEncoding.cpp
- Serialization/JSONFormat/WPASuite.cpp
- Serialization/SerializationFormatRegistry.cpp
- SummaryData/LUSummaryConsumer.cpp
- SummaryData/SummaryDataBuilderRegistry.cpp
- Support/ErrorBuilder.cpp
- TUSummary/ExtractorRegistry.cpp
- TUSummary/TUSummaryBuilder.cpp
- TUSummary/TUSummaryExtractor.cpp
- WholeProgramAnalysis/AnalysisDriver.cpp
- WholeProgramAnalysis/AnalysisName.cpp
- WholeProgramAnalysis/AnalysisRegistry.cpp
-
- LINK_LIBS
- clangAST
- clangUnifiedSymbolResolution
-
- DEPENDS
- )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.cpp
deleted file mode 100644
index 5aff18999e114..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-//===- EntityLinker.cpp ---------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
-#include <cassert>
-
-using namespace clang::ssaf;
-
-//===----------------------------------------------------------------------===//
-// Error Message Constants
-//===----------------------------------------------------------------------===//
-
-namespace ErrorMessages {
-
-static constexpr const char *EntityLinkerFatalErrorPrefix =
- "EntityLinker: Corrupted TUSummary or logic bug";
-
-static constexpr const char *EntityAlreadyExistsInLinkageTable =
- "{0} - {1} with {2} already exists in LUSummary";
-
-static constexpr const char *MissingLinkageInformation =
- "{0} - {1} missing linkage information in TUSummary";
-
-static constexpr const char *DuplicateEntityIdInTUSummary =
- "{0} - Duplicate {1} in EntityResolutionTable";
-
-static constexpr const char *EntityNotFoundInResolutionTable =
- "{0} - {1} not found in EntityResolutionTable";
-
-static constexpr const char *FailedToInsertEntityIntoOutputSummary =
- "{0} - Failed to insert data for {1} with {2} against {3} to LUSummary";
-
-static constexpr const char *DuplicateTUNamespace =
- "failed to link TU summary: duplicate {0}";
-
-} // namespace ErrorMessages
-
-static NestedBuildNamespace
-resolveNamespace(const NestedBuildNamespace &LUNamespace,
- const NestedBuildNamespace &TUNamespace,
- const NestedBuildNamespace &EntityNamespace,
- EntityLinkageType Linkage) {
- switch (Linkage) {
- case EntityLinkageType::None:
- case EntityLinkageType::Internal:
- // Qualify with the TU namespace first (to disambiguate across TUs),
- // then with the LU namespace.
- return EntityNamespace.makeQualified(TUNamespace)
- .makeQualified(LUNamespace);
- case EntityLinkageType::External:
- return NestedBuildNamespace(LUNamespace);
- }
-
- llvm_unreachable("Unhandled EntityLinkageType variant");
-}
-
-EntityId EntityLinker::resolveEntity(const EntityName &OldName,
- const EntityLinkage &Linkage,
- const NestedBuildNamespace &TUNamespace) {
- NestedBuildNamespace NewNamespace = resolveNamespace(
- Output.LUNamespace, TUNamespace, OldName.Namespace, Linkage.getLinkage());
-
- EntityName NewName(OldName.USR, OldName.Suffix, NewNamespace);
-
- // NewId construction will always return a fresh id for `None` and `Internal`
- // linkage entities since their namespaces will be different even if their
- // names clash. For `External` linkage entities with identical names this
- // function will return the id assigned at the first insertion.
- EntityId NewId = Output.IdTable.getId(NewName);
-
- auto [_, Inserted] = Output.LinkageTable.try_emplace(NewId, Linkage);
- if (!Inserted) {
- // Insertion failure for `None` and `Internal` linkage is a fatal error
- // because these entities have unique namespaces and should never collide.
- // `External` linkage entities may collide.
- if (Linkage.getLinkage() == EntityLinkageType::None ||
- Linkage.getLinkage() == EntityLinkageType::Internal) {
- ErrorBuilder::fatal(ErrorMessages::EntityAlreadyExistsInLinkageTable,
- ErrorMessages::EntityLinkerFatalErrorPrefix, NewId,
- Linkage);
- }
- }
-
- return NewId;
-}
-
-std::map<EntityId, EntityId>
-EntityLinker::resolve(const TUSummaryEncoding &Summary) {
- std::map<EntityId, EntityId> EntityResolutionTable;
-
- Summary.IdTable.forEach([&](const EntityName &OldName, const EntityId OldId) {
- auto Iter = Summary.LinkageTable.find(OldId);
- if (Iter == Summary.LinkageTable.end()) {
- ErrorBuilder::fatal(ErrorMessages::MissingLinkageInformation,
- ErrorMessages::EntityLinkerFatalErrorPrefix, OldId);
- }
-
- const EntityLinkage &Linkage = Iter->second;
-
- EntityId NewId = resolveEntity(OldName, Linkage,
- NestedBuildNamespace(Summary.TUNamespace));
-
- auto [_, Inserted] = EntityResolutionTable.insert({OldId, NewId});
- if (!Inserted) {
- ErrorBuilder::fatal(ErrorMessages::DuplicateEntityIdInTUSummary,
- ErrorMessages::EntityLinkerFatalErrorPrefix, OldId);
- }
- });
-
- return EntityResolutionTable;
-}
-
-std::vector<EntitySummaryEncoding *>
-EntityLinker::merge(TUSummaryEncoding &Summary,
- const std::map<EntityId, EntityId> &EntityResolutionTable) {
- std::vector<EntitySummaryEncoding *> PatchTargets;
-
- for (auto &[SN, DataMap] : Summary.Data) {
- auto &OutputSummaryData = Output.Data[SN];
-
- for (auto &[OldId, ES] : DataMap) {
- auto Iter = EntityResolutionTable.find(OldId);
- if (Iter == EntityResolutionTable.end()) {
- ErrorBuilder::fatal(ErrorMessages::EntityNotFoundInResolutionTable,
- ErrorMessages::EntityLinkerFatalErrorPrefix, OldId);
- }
-
- const auto NewId = Iter->second;
-
- auto [It, Inserted] = OutputSummaryData.try_emplace(NewId, std::move(ES));
-
- if (Inserted) {
- PatchTargets.push_back(It->second.get());
- } else {
- // Safe to retrieve linkage using .at since the resolve step ensures
- // linkage information is always present for every OldId.
- auto Linkage = Summary.LinkageTable.at(OldId);
-
- // Insertion should never fail for `None` and `Internal` linkage
- // entities because these entities will have different namespaces across
- // TUs even if their names match.
- if (Linkage.getLinkage() == EntityLinkageType::None ||
- Linkage.getLinkage() == EntityLinkageType::Internal) {
- ErrorBuilder::fatal(
- ErrorMessages::FailedToInsertEntityIntoOutputSummary,
- ErrorMessages::EntityLinkerFatalErrorPrefix, NewId, Linkage, SN);
- }
-
- // TODO: Insertion is expected to fail for duplicate occurrences of
- // `External` linkage entities. Report these cases in a "debug" mode to
- // help debug potential ODR violations.
- }
- }
- }
-
- return PatchTargets;
-}
-
-llvm::Error
-EntityLinker::patch(const std::vector<EntitySummaryEncoding *> &PatchTargets,
- const std::map<EntityId, EntityId> &EntityResolutionTable) {
- for (auto *PatchTarget : PatchTargets) {
- assert(PatchTarget && "EntityLinker::patch: Patch target cannot be null");
-
- if (auto Err = PatchTarget->patch(EntityResolutionTable)) {
- return Err;
- }
- }
- return llvm::Error::success();
-}
-
-llvm::Error EntityLinker::link(std::unique_ptr<TUSummaryEncoding> Summary) {
- auto [_, Inserted] = ProcessedTUNamespaces.insert(Summary->TUNamespace);
- if (!Inserted) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::DuplicateTUNamespace,
- Summary->TUNamespace)
- .build();
- }
-
- TUSummaryEncoding &SummaryRef = *Summary;
-
- auto EntityResolutionTable = resolve(SummaryRef);
- auto PatchTargets = merge(SummaryRef, EntityResolutionTable);
- return patch(PatchTargets, EntityResolutionTable);
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.cpp
deleted file mode 100644
index 09fff31e8f4a8..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-//===- BuildNamespace.cpp -------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "../ModelStringConversions.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <tuple>
-
-namespace clang::ssaf {
-
-BuildNamespace
-BuildNamespace::makeCompilationUnit(llvm::StringRef CompilationId) {
- return BuildNamespace{BuildNamespaceKind::CompilationUnit,
- CompilationId.str()};
-}
-
-bool BuildNamespace::operator==(const BuildNamespace &Other) const {
- return asTuple() == Other.asTuple();
-}
-
-bool BuildNamespace::operator!=(const BuildNamespace &Other) const {
- return !(*this == Other);
-}
-
-bool BuildNamespace::operator<(const BuildNamespace &Other) const {
- return asTuple() < Other.asTuple();
-}
-
-NestedBuildNamespace
-NestedBuildNamespace::makeCompilationUnit(llvm::StringRef CompilationId) {
- NestedBuildNamespace Result;
- Result.Namespaces.push_back(
- BuildNamespace::makeCompilationUnit(CompilationId));
- return Result;
-}
-
-bool NestedBuildNamespace::empty() const { return Namespaces.empty(); }
-
-bool NestedBuildNamespace::operator==(const NestedBuildNamespace &Other) const {
- return Namespaces == Other.Namespaces;
-}
-
-bool NestedBuildNamespace::operator!=(const NestedBuildNamespace &Other) const {
- return !(*this == Other);
-}
-
-bool NestedBuildNamespace::operator<(const NestedBuildNamespace &Other) const {
- return Namespaces < Other.Namespaces;
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, BuildNamespaceKind BNK) {
- return OS << buildNamespaceKindToString(BNK);
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const BuildNamespace &BN) {
- return OS << "BuildNamespace(" << BN.Kind << ", " << BN.Name << ")";
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const NestedBuildNamespace &NBN) {
- OS << "NestedBuildNamespace([";
- llvm::interleaveComma(NBN.Namespaces, OS);
- OS << "])";
- return OS;
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityId.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityId.cpp
deleted file mode 100644
index 9c4eec2d7e299..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityId.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-//===- EntityId.cpp -------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-
-namespace clang::ssaf {
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityId &Id) {
- return OS << "EntityId(" << Id.Index << ")";
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.cpp
deleted file mode 100644
index cb514581ca9ec..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- EntityIdTable.cpp --------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include <cassert>
-
-namespace clang::ssaf {
-
-EntityId EntityIdTable::getId(const EntityName &Name) {
- EntityId Id(Entities.size());
- const auto Res = Entities.try_emplace(Name, Id);
- return Res.first->second;
-}
-
-bool EntityIdTable::contains(const EntityName &Name) const {
- return Entities.find(Name) != Entities.end();
-}
-
-void EntityIdTable::forEach(
- llvm::function_ref<void(const EntityName &, EntityId)> Callback) const {
- for (const auto &NameIdPair : Entities) {
- Callback(NameIdPair.first, NameIdPair.second);
- }
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.cpp
deleted file mode 100644
index 179b906c0b999..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-//===- EntityLinkage.cpp --------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-
-#include "../ModelStringConversions.h"
-
-namespace clang::ssaf {
-
-bool EntityLinkage::operator==(const EntityLinkage &Other) const {
- return Linkage == Other.Linkage;
-}
-
-bool EntityLinkage::operator!=(const EntityLinkage &Other) const {
- return !(*this == Other);
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- EntityLinkageType Linkage) {
- return OS << entityLinkageTypeToString(Linkage);
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
- const EntityLinkage &Linkage) {
- return OS << "EntityLinkage(" << Linkage.getLinkage() << ")";
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityName.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityName.cpp
deleted file mode 100644
index 9145506865f24..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/EntityName.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- EntityName.cpp -----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-
-namespace clang::ssaf {
-
-EntityName::EntityName(llvm::StringRef USR, llvm::StringRef Suffix,
- NestedBuildNamespace Namespace)
- : USR(USR.str()), Suffix(Suffix), Namespace(std::move(Namespace)) {}
-
-bool EntityName::operator==(const EntityName &Other) const {
- return asTuple() == Other.asTuple();
-}
-
-bool EntityName::operator!=(const EntityName &Other) const {
- return !(*this == Other);
-}
-
-bool EntityName::operator<(const EntityName &Other) const {
- return asTuple() < Other.asTuple();
-}
-
-EntityName EntityName::makeQualified(NestedBuildNamespace Namespace) const {
- auto Copy = *this;
- Copy.Namespace = Copy.Namespace.makeQualified(Namespace);
-
- return Copy;
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityName &EN) {
- return OS << "EntityName(" << EN.USR << ", " << EN.Suffix << ", "
- << EN.Namespace << ")";
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/SummaryName.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Model/SummaryName.cpp
deleted file mode 100644
index 1609912aa7f90..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Model/SummaryName.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-//===- SummaryName.cpp ----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-
-namespace clang::ssaf {
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SummaryName &SN) {
- return OS << "SummaryName(" << SN.str() << ")";
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h b/clang/lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h
deleted file mode 100644
index f168a475de807..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h
+++ /dev/null
@@ -1,87 +0,0 @@
-//===- ModelStringConversions.h ---------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Internal string conversion utilities for SSAF model types.
-//
-// These functions are shared by the model .cpp files (for operator<<) and
-// JSONFormat.cpp (for serialization). They are not part of the public API.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODELSTRINGCONVERSIONS_H
-#define LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODELSTRINGCONVERSIONS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <optional>
-
-namespace clang::ssaf {
-
-//===----------------------------------------------------------------------===//
-// BuildNamespaceKind
-//===----------------------------------------------------------------------===//
-
-/// Returns the canonical string representation of \p BNK used for
-/// serialization and display (e.g. "CompilationUnit", "LinkUnit").
-inline llvm::StringRef buildNamespaceKindToString(BuildNamespaceKind BNK) {
- switch (BNK) {
- case BuildNamespaceKind::CompilationUnit:
- return "CompilationUnit";
- case BuildNamespaceKind::LinkUnit:
- return "LinkUnit";
- }
- llvm_unreachable("Unhandled BuildNamespaceKind variant");
-}
-
-/// Parses a string produced by buildNamespaceKindToString(). Returns
-/// std::nullopt if \p Str does not match any known BuildNamespaceKind value.
-inline std::optional<BuildNamespaceKind>
-buildNamespaceKindFromString(llvm::StringRef Str) {
- if (Str == "CompilationUnit")
- return BuildNamespaceKind::CompilationUnit;
- if (Str == "LinkUnit")
- return BuildNamespaceKind::LinkUnit;
- return std::nullopt;
-}
-
-//===----------------------------------------------------------------------===//
-// EntityLinkageType
-//===----------------------------------------------------------------------===//
-
-/// Returns the canonical string representation of \p LT used for
-/// serialization and display (e.g. "None", "Internal", "External").
-inline llvm::StringRef entityLinkageTypeToString(EntityLinkageType LT) {
- switch (LT) {
- case EntityLinkageType::None:
- return "None";
- case EntityLinkageType::Internal:
- return "Internal";
- case EntityLinkageType::External:
- return "External";
- }
- llvm_unreachable("Unhandled EntityLinkageType variant");
-}
-
-/// Parses a string produced by entityLinkageTypeToString(). Returns
-/// std::nullopt if \p Str does not match any known EntityLinkageType value.
-inline std::optional<EntityLinkageType>
-entityLinkageTypeFromString(llvm::StringRef Str) {
- if (Str == "None")
- return EntityLinkageType::None;
- if (Str == "Internal")
- return EntityLinkageType::Internal;
- if (Str == "External")
- return EntityLinkageType::External;
- return std::nullopt;
-}
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_MODELSTRINGCONVERSIONS_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/Artifact.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/Artifact.cpp
deleted file mode 100644
index 424d7368cf33f..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/Artifact.cpp
+++ /dev/null
@@ -1,173 +0,0 @@
-//===- Artifact.cpp -------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Generic artifact read/write entry points that dispatch on the
-// self-describing "type" field of the JSON document.
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONFormatImpl.h"
-
-namespace clang::ssaf {
-
-llvm::Expected<Artifact> JSONFormat::readArtifact(llvm::StringRef Path) {
- auto ExpectedJSON = readJSON(Path);
- if (!ExpectedJSON) {
- return ErrorBuilder::wrap(ExpectedJSON.takeError())
- .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
- .build();
- }
-
- Object *RootObjectPtr = ExpectedJSON->getAsObject();
- if (!RootObjectPtr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObject, "Artifact",
- "object")
- .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
- .build();
- }
-
- auto ExpectedType = readSummaryType(*RootObjectPtr);
- if (!ExpectedType) {
- return ErrorBuilder::wrap(ExpectedType.takeError())
- .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
- .build();
- }
-
- // Dispatch by the self-describing type field. The helpers operate on
- // the already-parsed root object so the file is read and parsed only
- // once per readArtifact call.
- if (*ExpectedType == JSONTypeValueTUSummary) {
- auto ExpectedTU = readTUSummaryFromObject(*RootObjectPtr);
- if (!ExpectedTU) {
- return ErrorBuilder::wrap(ExpectedTU.takeError())
- .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
- .build();
- }
- return Artifact{std::move(*ExpectedTU)};
- }
-
- if (*ExpectedType == JSONTypeValueLUSummary) {
- auto ExpectedLU = readLUSummaryFromObject(*RootObjectPtr);
- if (!ExpectedLU) {
- return ErrorBuilder::wrap(ExpectedLU.takeError())
- .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
- .build();
- }
- return Artifact{std::move(*ExpectedLU)};
- }
-
- if (*ExpectedType == JSONTypeValueWPASuite) {
- auto ExpectedWPA = readWPASuiteFromObject(*RootObjectPtr);
- if (!ExpectedWPA) {
- return ErrorBuilder::wrap(ExpectedWPA.takeError())
- .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
- .build();
- }
- return Artifact{std::move(*ExpectedWPA)};
- }
-
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::UnknownArtifactType, *ExpectedType,
- JSONTypeKey, JSONTypeValueTUSummary,
- JSONTypeValueLUSummary, JSONTypeValueWPASuite)
- .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
- .build();
-}
-
-llvm::Error JSONFormat::writeArtifact(const Artifact &A, llvm::StringRef Path) {
- return std::visit(
- [&](const auto &S) -> llvm::Error {
- using T = std::decay_t<decltype(S)>;
- if constexpr (std::is_same_v<T, TUSummary>) {
- return writeTUSummary(S, Path);
- } else if constexpr (std::is_same_v<T, LUSummary>) {
- return writeLUSummary(S, Path);
- } else {
- static_assert(std::is_same_v<T, WPASuite>,
- "Artifact visitor must cover all variant alternatives");
- return writeWPASuite(S, Path);
- }
- },
- A);
-}
-
-llvm::Expected<ArtifactEncoding>
-JSONFormat::readArtifactEncoding(llvm::StringRef Path) {
- auto ExpectedJSON = readJSON(Path);
- if (!ExpectedJSON) {
- return ErrorBuilder::wrap(ExpectedJSON.takeError())
- .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
- .build();
- }
-
- Object *RootObjectPtr = ExpectedJSON->getAsObject();
- if (!RootObjectPtr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObject,
- "ArtifactEncoding", "object")
- .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
- .build();
- }
-
- auto ExpectedType = readSummaryType(*RootObjectPtr);
- if (!ExpectedType) {
- return ErrorBuilder::wrap(ExpectedType.takeError())
- .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
- .build();
- }
-
- // Dispatch by the self-describing type field. The helpers operate on
- // the already-parsed root object so the file is read and parsed only
- // once per readArtifactEncoding call.
- if (*ExpectedType == JSONTypeValueTUSummary) {
- auto ExpectedTU = readTUSummaryEncodingFromObject(*RootObjectPtr);
- if (!ExpectedTU) {
- return ErrorBuilder::wrap(ExpectedTU.takeError())
- .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
- .build();
- }
- return ArtifactEncoding{std::move(*ExpectedTU)};
- }
-
- if (*ExpectedType == JSONTypeValueLUSummary) {
- auto ExpectedLU = readLUSummaryEncodingFromObject(*RootObjectPtr);
- if (!ExpectedLU) {
- return ErrorBuilder::wrap(ExpectedLU.takeError())
- .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
- .build();
- }
- return ArtifactEncoding{std::move(*ExpectedLU)};
- }
-
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::UnknownArtifactEncodingType,
- *ExpectedType, JSONTypeKey,
- JSONTypeValueTUSummary, JSONTypeValueLUSummary)
- .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
- .build();
-}
-
-llvm::Error JSONFormat::writeArtifactEncoding(const ArtifactEncoding &E,
- llvm::StringRef Path) {
- return std::visit(
- [&](const auto &Enc) -> llvm::Error {
- using T = std::decay_t<decltype(Enc)>;
- if constexpr (std::is_same_v<T, TUSummaryEncoding>) {
- return writeTUSummaryEncoding(Enc, Path);
- } else {
- static_assert(
- std::is_same_v<T, LUSummaryEncoding>,
- "ArtifactEncoding visitor must cover all variant alternatives");
- return writeLUSummaryEncoding(Enc, Path);
- }
- },
- E);
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
deleted file mode 100644
index 35c45ac108e07..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//===- JSONEntitySummaryEncoding.cpp --------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONEntitySummaryEncoding.h"
-#include "JSONFormatImpl.h"
-
-namespace clang::ssaf {
-
-llvm::Error JSONEntitySummaryEncoding::patchEntityIdObject(
- llvm::json::Object &Obj, const std::map<EntityId, EntityId> &Table,
- llvm::json::Value *AtVal) {
-
- if (Obj.size() != 1) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadEntityIdObject,
- JSONEntityIdKey)
- .build();
- }
-
- std::optional<uint64_t> OptEntityIdIndex = AtVal->getAsUINT64();
- if (!OptEntityIdIndex) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadEntityIdObject,
- JSONEntityIdKey)
- .build();
- }
-
- auto OldId = JSONFormat::makeEntityId(*OptEntityIdIndex);
- auto It = Table.find(OldId);
- if (It == Table.end()) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToPatchEntityIdNotInTable,
- OldId)
- .build();
- }
-
- *AtVal = static_cast<uint64_t>(JSONFormat::getIndex(It->second));
-
- return llvm::Error::success();
-}
-
-llvm::Error JSONEntitySummaryEncoding::patchRegularObject(
- llvm::json::Object &Obj, const std::map<EntityId, EntityId> &Table) {
- for (auto &[Key, Val] : Obj) {
- if (auto Err = patchValue(Val, Table)) {
- return Err;
- }
- }
- return llvm::Error::success();
-}
-
-llvm::Error JSONEntitySummaryEncoding::patchObject(
- llvm::json::Object &Obj, const std::map<EntityId, EntityId> &Table) {
-
- llvm::json::Value *AtVal = Obj.get(JSONEntityIdKey);
- return AtVal ? patchEntityIdObject(Obj, Table, AtVal)
- : patchRegularObject(Obj, Table);
-}
-
-llvm::Error JSONEntitySummaryEncoding::patchValue(
- llvm::json::Value &V, const std::map<EntityId, EntityId> &Table) {
- if (llvm::json::Object *Obj = V.getAsObject()) {
- if (auto Err = patchObject(*Obj, Table)) {
- return Err;
- }
- } else if (llvm::json::Array *Arr = V.getAsArray()) {
- for (auto &Val : *Arr) {
- if (auto Err = patchValue(Val, Table)) {
- return Err;
- }
- }
- }
- return llvm::Error::success();
-}
-
-llvm::Error JSONEntitySummaryEncoding::patch(
- const std::map<EntityId, EntityId> &EntityResolutionTable) {
- return patchValue(Data, EntityResolutionTable);
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
deleted file mode 100644
index 9a1f5d49757f7..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===- JSONEntitySummaryEncoding.h ------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Opaque JSON-based entity summary encoding used by JSONFormat. Stores raw
-// EntitySummary JSON blobs and patches embedded entity ID references without
-// requiring knowledge of the analysis schema.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
-#define LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "llvm/Support/JSON.h"
-
-#include <map>
-
-namespace clang::ssaf {
-
-class JSONEntitySummaryEncoding final : public EntitySummaryEncoding {
- friend JSONFormat;
-
-public:
- llvm::Error
- patch(const std::map<EntityId, EntityId> &EntityResolutionTable) override;
-
-private:
- explicit JSONEntitySummaryEncoding(llvm::json::Value Data)
- : Data(std::move(Data)) {}
-
- llvm::Error patchEntityIdObject(llvm::json::Object &Obj,
- const std::map<EntityId, EntityId> &Table,
- llvm::json::Value *AtVal);
- llvm::Error patchRegularObject(llvm::json::Object &Obj,
- const std::map<EntityId, EntityId> &Table);
- llvm::Error patchObject(llvm::json::Object &Obj,
- const std::map<EntityId, EntityId> &Table);
- llvm::Error patchValue(llvm::json::Value &V,
- const std::map<EntityId, EntityId> &Table);
-
- llvm::json::Value Data;
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
deleted file mode 100644
index f56e96295515d..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
+++ /dev/null
@@ -1,1380 +0,0 @@
-//===- JSONFormatImpl.cpp -------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONFormatImpl.h"
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "llvm/Support/Registry.h"
-#include "llvm/TargetParser/Triple.h"
-
-using namespace clang;
-using namespace ssaf;
-
-LLVM_DEFINE_REGISTRY(llvm::Registry<JSONFormat::FormatInfo>)
-LLVM_DEFINE_REGISTRY(llvm::Registry<JSONFormat::AnalysisResultRegistry::Codec>)
-
-static SerializationFormatRegistry::Add<JSONFormat>
- RegisterJSONFormat("json", "JSON serialization format");
-
-namespace clang::ssaf {
-
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int JSONFormatAnchorSource = 0;
-
-//----------------------------------------------------------------------------
-// JSON Reader and Writer
-//----------------------------------------------------------------------------
-
-llvm::Expected<Value> readJSON(llvm::StringRef Path) {
- if (!llvm::sys::fs::exists(Path)) {
- return ErrorBuilder::create(std::errc::no_such_file_or_directory,
- ErrorMessages::FailedToReadFile, Path,
- ErrorMessages::FileNotFound)
- .build();
- }
-
- if (llvm::sys::fs::is_directory(Path)) {
- return ErrorBuilder::create(std::errc::is_a_directory,
- ErrorMessages::FailedToReadFile, Path,
- ErrorMessages::FileIsDirectory)
- .build();
- }
-
- if (!Path.ends_with(JSONFormatFileExtension)) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadFile, Path,
- llvm::formatv(ErrorMessages::FileIsNotJSON,
- JSONFormatFileExtension))
- .build();
- }
-
- auto BufferOrError = llvm::MemoryBuffer::getFile(Path);
- if (!BufferOrError) {
- const std::error_code EC = BufferOrError.getError();
- return ErrorBuilder::create(EC, ErrorMessages::FailedToReadFile, Path,
- EC.message())
- .build();
- }
-
- return llvm::json::parse(BufferOrError.get()->getBuffer());
-}
-
-llvm::Error writeJSON(Value &&V, llvm::StringRef Path) {
- if (llvm::sys::fs::exists(Path)) {
- return ErrorBuilder::create(std::errc::file_exists,
- ErrorMessages::FailedToWriteFile, Path,
- ErrorMessages::FileExists)
- .build();
- }
-
- llvm::StringRef Dir = llvm::sys::path::parent_path(Path);
- if (!Dir.empty() && !llvm::sys::fs::is_directory(Dir)) {
- return ErrorBuilder::create(std::errc::no_such_file_or_directory,
- ErrorMessages::FailedToWriteFile, Path,
- ErrorMessages::ParentDirectoryNotFound)
- .build();
- }
-
- if (!Path.ends_with(JSONFormatFileExtension)) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToWriteFile, Path,
- llvm::formatv(ErrorMessages::FileIsNotJSON,
- JSONFormatFileExtension))
- .build();
- }
-
- std::error_code EC;
- llvm::raw_fd_ostream OutStream(Path, EC, llvm::sys::fs::OF_Text);
-
- if (EC) {
- return ErrorBuilder::create(EC, ErrorMessages::FailedToWriteFile, Path,
- EC.message())
- .build();
- }
-
- OutStream << llvm::formatv("{0:2}\n", V);
- OutStream.flush();
-
- // This path handles post-write stream errors (e.g. ENOSPC after buffered
- // writes). It is difficult to exercise in unit tests so it is intentionally
- // left without test coverage.
- if (OutStream.has_error()) {
- return ErrorBuilder::create(OutStream.error(),
- ErrorMessages::FailedToWriteFile, Path,
- OutStream.error().message())
- .build();
- }
-
- return llvm::Error::success();
-}
-
-//----------------------------------------------------------------------------
-// JSONFormat Static Methods
-//----------------------------------------------------------------------------
-
-std::map<SummaryName, JSONFormat::FormatInfo> JSONFormat::initFormatInfos() {
- std::map<SummaryName, FormatInfo> FormatInfos;
- for (const auto &FormatInfoEntry : llvm::Registry<FormatInfo>::entries()) {
- std::unique_ptr<FormatInfo> Info = FormatInfoEntry.instantiate();
- bool Inserted = FormatInfos.try_emplace(Info->ForSummary, *Info).second;
- if (!Inserted) {
- llvm::report_fatal_error(
- "FormatInfo is already registered for summary: " +
- Info->ForSummary.str());
- }
- }
- return FormatInfos;
-}
-
-void JSONFormat::forEachRegisteredAnalysis(
- llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> Callback) const {
- for (const auto &Entry : llvm::Registry<FormatInfo>::entries())
- Callback(Entry.getName(), Entry.getDesc());
-}
-
-//----------------------------------------------------------------------------
-// SummaryName
-//----------------------------------------------------------------------------
-
-SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr) {
- return SummaryName(SummaryNameStr.str());
-}
-
-llvm::StringRef summaryNameToJSON(const SummaryName &SN) { return SN.str(); }
-
-//----------------------------------------------------------------------------
-// Summary Type field
-//----------------------------------------------------------------------------
-
-llvm::Expected<llvm::StringRef> readSummaryType(const Object &RootObject) {
- std::optional<llvm::StringRef> OptType = RootObject.getString(JSONTypeKey);
- if (!OptType) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "summary type", JSONTypeKey, "string")
- .build();
- }
- return *OptType;
-}
-
-llvm::Error checkSummaryType(const Object &RootObject,
- llvm::StringRef ExpectedType) {
- auto ExpectedActual = readSummaryType(RootObject);
- if (!ExpectedActual) {
- return ExpectedActual.takeError();
- }
- if (*ExpectedActual != ExpectedType) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::MismatchedSummaryType,
- ExpectedType, JSONTypeKey, *ExpectedActual)
- .build();
- }
- return llvm::Error::success();
-}
-
-//----------------------------------------------------------------------------
-// AnalysisName
-//----------------------------------------------------------------------------
-
-AnalysisName analysisNameFromJSON(llvm::StringRef AnalysisNameStr) {
- return AnalysisName(AnalysisNameStr.str());
-}
-
-llvm::StringRef analysisNameToJSON(const AnalysisName &AN) { return AN.str(); }
-
-//----------------------------------------------------------------------------
-// EntityId
-//----------------------------------------------------------------------------
-
-EntityId JSONFormat::entityIdFromJSON(const uint64_t EntityIdIndex) const {
- return makeEntityId(static_cast<size_t>(EntityIdIndex));
-}
-
-uint64_t JSONFormat::entityIdToJSON(EntityId EI) const {
- return static_cast<uint64_t>(getIndex(EI));
-}
-
-llvm::Expected<EntityId>
-JSONFormat::entityIdFromJSONObject(const Object &EntityIdObject) {
- if (EntityIdObject.size() != 1) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadEntityIdObject,
- JSONEntityIdKey)
- .build();
- }
-
- const llvm::json::Value *AtVal = EntityIdObject.get(JSONEntityIdKey);
- if (!AtVal) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadEntityIdObject,
- JSONEntityIdKey)
- .build();
- }
-
- std::optional<uint64_t> OptEntityIdIndex = AtVal->getAsUINT64();
- if (!OptEntityIdIndex) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadEntityIdObject,
- JSONEntityIdKey)
- .build();
- }
-
- return makeEntityId(static_cast<size_t>(*OptEntityIdIndex));
-}
-
-Object JSONFormat::entityIdToJSONObject(EntityId EI) {
- Object Result;
- Result[JSONEntityIdKey] = static_cast<uint64_t>(getIndex(EI));
- return Result;
-}
-
-//----------------------------------------------------------------------------
-// BuildNamespaceKind
-//----------------------------------------------------------------------------
-
-llvm::Expected<BuildNamespaceKind>
-buildNamespaceKindFromJSON(llvm::StringRef BuildNamespaceKindStr) {
- auto OptBuildNamespaceKind =
- buildNamespaceKindFromString(BuildNamespaceKindStr);
- if (!OptBuildNamespaceKind) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::InvalidBuildNamespaceKind,
- BuildNamespaceKindStr)
- .build();
- }
- return *OptBuildNamespaceKind;
-}
-
-// Provided for consistency with respect to rest of the codebase.
-llvm::StringRef buildNamespaceKindToJSON(BuildNamespaceKind BNK) {
- return buildNamespaceKindToString(BNK);
-}
-
-//----------------------------------------------------------------------------
-// BuildNamespace
-//----------------------------------------------------------------------------
-
-llvm::Expected<BuildNamespace>
-JSONFormat::buildNamespaceFromJSON(const Object &BuildNamespaceObject) const {
- auto OptBuildNamespaceKindStr = BuildNamespaceObject.getString("kind");
- if (!OptBuildNamespaceKindStr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "BuildNamespaceKind", "kind", "string")
- .build();
- }
-
- auto ExpectedKind = buildNamespaceKindFromJSON(*OptBuildNamespaceKindStr);
- if (!ExpectedKind) {
- return ErrorBuilder::wrap(ExpectedKind.takeError())
- .context(ErrorMessages::ReadingFromField, "BuildNamespaceKind", "kind")
- .build();
- }
-
- auto OptNameStr = BuildNamespaceObject.getString("name");
- if (!OptNameStr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "BuildNamespaceName", "name", "string")
- .build();
- }
-
- return {BuildNamespace(*ExpectedKind, *OptNameStr)};
-}
-
-Object JSONFormat::buildNamespaceToJSON(const BuildNamespace &BN) const {
- Object Result;
- Result["kind"] = buildNamespaceKindToJSON(getKind(BN));
- Result["name"] = getName(BN);
- return Result;
-}
-
-//----------------------------------------------------------------------------
-// NestedBuildNamespace
-//----------------------------------------------------------------------------
-
-llvm::Expected<NestedBuildNamespace> JSONFormat::nestedBuildNamespaceFromJSON(
- const Array &NestedBuildNamespaceArray) const {
- std::vector<BuildNamespace> Namespaces;
-
- size_t NamespaceCount = NestedBuildNamespaceArray.size();
- Namespaces.reserve(NamespaceCount);
-
- for (const auto &[Index, BuildNamespaceValue] :
- llvm::enumerate(NestedBuildNamespaceArray)) {
- const Object *BuildNamespaceObject = BuildNamespaceValue.getAsObject();
- if (!BuildNamespaceObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtIndex,
- "BuildNamespace", Index, "object")
- .build();
- }
-
- auto ExpectedBuildNamespace = buildNamespaceFromJSON(*BuildNamespaceObject);
- if (!ExpectedBuildNamespace) {
- return ErrorBuilder::wrap(ExpectedBuildNamespace.takeError())
- .context(ErrorMessages::ReadingFromIndex, "BuildNamespace", Index)
- .build();
- }
-
- Namespaces.push_back(std::move(*ExpectedBuildNamespace));
- }
-
- return NestedBuildNamespace(std::move(Namespaces));
-}
-
-Array JSONFormat::nestedBuildNamespaceToJSON(
- const NestedBuildNamespace &NBN) const {
- Array Result;
- const auto &Namespaces = getNamespaces(NBN);
- Result.reserve(Namespaces.size());
-
- for (const auto &BN : Namespaces) {
- Result.push_back(buildNamespaceToJSON(BN));
- }
-
- return Result;
-}
-
-//----------------------------------------------------------------------------
-// EntityName
-//----------------------------------------------------------------------------
-
-/// Reads "usr" and "suffix" fields from an EntityName JSON object.
-/// Shared core logic for both TU and LU entity name deserialization.
-static llvm::Expected<std::pair<llvm::StringRef, llvm::StringRef>>
-entityNameCoreFromJSON(const Object &EntityNameObject) {
- const auto OptUSR = EntityNameObject.getString("usr");
- if (!OptUSR) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField, "USR",
- "usr", "string")
- .build();
- }
-
- const auto OptSuffix = EntityNameObject.getString("suffix");
- if (!OptSuffix) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "Suffix", "suffix", "string")
- .build();
- }
-
- return std::make_pair(*OptUSR, *OptSuffix);
-}
-
-llvm::Expected<EntityName>
-JSONFormat::tuEntityNameFromJSON(const Object &EntityNameObject) const {
- auto ExpectedCore = entityNameCoreFromJSON(EntityNameObject);
- if (!ExpectedCore)
- return ExpectedCore.takeError();
-
- auto [USR, Suffix] = *ExpectedCore;
- return EntityName{USR, Suffix, NestedBuildNamespace()};
-}
-
-Object JSONFormat::tuEntityNameToJSON(const EntityName &EN) const {
- Object Result;
- Result["usr"] = getUSR(EN);
- Result["suffix"] = getSuffix(EN);
- return Result;
-}
-
-llvm::Expected<EntityName>
-JSONFormat::luEntityNameFromJSON(const Object &EntityNameObject) const {
- auto ExpectedCore = entityNameCoreFromJSON(EntityNameObject);
- if (!ExpectedCore)
- return ExpectedCore.takeError();
-
- auto [USR, Suffix] = *ExpectedCore;
-
- const Array *OptNamespaceArray = EntityNameObject.getArray("namespace");
- if (!OptNamespaceArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "NestedBuildNamespace", "namespace", "array")
- .build();
- }
-
- auto ExpectedNamespace = nestedBuildNamespaceFromJSON(*OptNamespaceArray);
- if (!ExpectedNamespace) {
- return ErrorBuilder::wrap(ExpectedNamespace.takeError())
- .context(ErrorMessages::ReadingFromField, "NestedBuildNamespace",
- "namespace")
- .build();
- }
-
- return EntityName{USR, Suffix, std::move(*ExpectedNamespace)};
-}
-
-Object JSONFormat::luEntityNameToJSON(const EntityName &EN) const {
- Object Result;
- Result["usr"] = getUSR(EN);
- Result["suffix"] = getSuffix(EN);
- Result["namespace"] = nestedBuildNamespaceToJSON(getNamespace(EN));
- return Result;
-}
-
-//----------------------------------------------------------------------------
-// EntityLinkageType
-//----------------------------------------------------------------------------
-
-llvm::Expected<EntityLinkageType>
-entityLinkageTypeFromJSON(llvm::StringRef EntityLinkageTypeStr) {
- auto OptEntityLinkageType = entityLinkageTypeFromString(EntityLinkageTypeStr);
- if (!OptEntityLinkageType) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::InvalidEntityLinkageType,
- EntityLinkageTypeStr)
- .build();
- }
- return *OptEntityLinkageType;
-}
-
-// Provided for consistency with respect to rest of the codebase.
-llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT) {
- return entityLinkageTypeToString(LT);
-}
-
-//----------------------------------------------------------------------------
-// TargetTriple
-//----------------------------------------------------------------------------
-
-llvm::Error validateNormalizedTargetTriple(llvm::StringRef Triple) {
- std::string Normalized = llvm::Triple::normalize(Triple);
- if (Normalized != Triple) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::TargetTripleNotNormalized,
- Triple, Normalized)
- .build();
- }
- return llvm::Error::success();
-}
-
-//----------------------------------------------------------------------------
-// EntityLinkage
-//----------------------------------------------------------------------------
-
-llvm::Expected<EntityLinkage>
-JSONFormat::entityLinkageFromJSON(const Object &EntityLinkageObject) const {
- auto OptLinkageStr = EntityLinkageObject.getString("type");
- if (!OptLinkageStr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityLinkageType", "type", "string")
- .build();
- }
-
- auto ExpectedLinkageType = entityLinkageTypeFromJSON(*OptLinkageStr);
- if (!ExpectedLinkageType) {
- return ErrorBuilder::wrap(ExpectedLinkageType.takeError())
- .context(ErrorMessages::ReadingFromField, "EntityLinkageType", "type")
- .build();
- }
-
- return EntityLinkage(*ExpectedLinkageType);
-}
-
-Object JSONFormat::entityLinkageToJSON(const EntityLinkage &EL) const {
- Object Result;
- Result["type"] = entityLinkageTypeToJSON(getLinkage(EL));
- return Result;
-}
-
-//----------------------------------------------------------------------------
-// EntityIdTableEntry
-//----------------------------------------------------------------------------
-
-/// Shared logic for reading the "id" field from an EntityIdTableEntry object.
-static llvm::Expected<EntityId>
-entityIdTableEntryIdFromJSON(const Object &EntityIdTableEntryObject,
- llvm::function_ref<EntityId(uint64_t)> MakeId) {
- const Value *EntityIdIntValue = EntityIdTableEntryObject.get("id");
- if (!EntityIdIntValue) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityId", "id",
- "number (unsigned 64-bit integer)")
- .build();
- }
-
- const std::optional<uint64_t> OptEntityIdInt =
- EntityIdIntValue->getAsUINT64();
- if (!OptEntityIdInt) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityId", "id",
- "number (unsigned 64-bit integer)")
- .build();
- }
-
- return MakeId(*OptEntityIdInt);
-}
-
-llvm::Expected<std::pair<EntityName, EntityId>>
-JSONFormat::tuEntityIdTableEntryFromJSON(
- const Object &EntityIdTableEntryObject) const {
-
- const Object *OptEntityNameObject =
- EntityIdTableEntryObject.getObject("name");
- if (!OptEntityNameObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityName", "name", "object")
- .build();
- }
-
- auto ExpectedEntityName = tuEntityNameFromJSON(*OptEntityNameObject);
- if (!ExpectedEntityName) {
- return ErrorBuilder::wrap(ExpectedEntityName.takeError())
- .context(ErrorMessages::ReadingFromField, "EntityName", "name")
- .build();
- }
-
- auto ExpectedId = entityIdTableEntryIdFromJSON(
- EntityIdTableEntryObject,
- [this](uint64_t V) { return entityIdFromJSON(V); });
- if (!ExpectedId)
- return ExpectedId.takeError();
-
- return std::make_pair(std::move(*ExpectedEntityName), std::move(*ExpectedId));
-}
-
-Object JSONFormat::tuEntityIdTableEntryToJSON(const EntityName &EN,
- EntityId EI) const {
- Object Entry;
- Entry["id"] = entityIdToJSON(EI);
- Entry["name"] = tuEntityNameToJSON(EN);
- return Entry;
-}
-
-llvm::Expected<std::pair<EntityName, EntityId>>
-JSONFormat::luEntityIdTableEntryFromJSON(
- const Object &EntityIdTableEntryObject) const {
-
- const Object *OptEntityNameObject =
- EntityIdTableEntryObject.getObject("name");
- if (!OptEntityNameObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityName", "name", "object")
- .build();
- }
-
- auto ExpectedEntityName = luEntityNameFromJSON(*OptEntityNameObject);
- if (!ExpectedEntityName) {
- return ErrorBuilder::wrap(ExpectedEntityName.takeError())
- .context(ErrorMessages::ReadingFromField, "EntityName", "name")
- .build();
- }
-
- auto ExpectedId = entityIdTableEntryIdFromJSON(
- EntityIdTableEntryObject,
- [this](uint64_t V) { return entityIdFromJSON(V); });
- if (!ExpectedId)
- return ExpectedId.takeError();
-
- return std::make_pair(std::move(*ExpectedEntityName), std::move(*ExpectedId));
-}
-
-Object JSONFormat::luEntityIdTableEntryToJSON(const EntityName &EN,
- EntityId EI) const {
- Object Entry;
- Entry["id"] = entityIdToJSON(EI);
- Entry["name"] = luEntityNameToJSON(EN);
- return Entry;
-}
-
-//----------------------------------------------------------------------------
-// EntityIdTable
-//----------------------------------------------------------------------------
-
-/// Shared logic for deserializing an EntityIdTable from a JSON array.
-/// \p EntryReader is called for each entry object to produce an
-/// (EntityName, EntityId) pair.
-static llvm::Expected<EntityIdTable> entityIdTableFromJSONImpl(
- const Array &EntityIdTableArray,
- llvm::function_ref<
- llvm::Expected<std::pair<EntityName, EntityId>>(const Object &)>
- EntryReader,
- llvm::function_ref<std::map<EntityName, EntityId> &(EntityIdTable &)>
- GetEntities) {
- EntityIdTable IdTable;
- std::map<EntityName, EntityId> &Entities = GetEntities(IdTable);
-
- for (const auto &[Index, EntityIdTableEntryValue] :
- llvm::enumerate(EntityIdTableArray)) {
- const Object *OptEntityIdTableEntryObject =
- EntityIdTableEntryValue.getAsObject();
- if (!OptEntityIdTableEntryObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtIndex,
- "EntityIdTable entry", Index, "object")
- .build();
- }
-
- auto ExpectedEntityIdTableEntry = EntryReader(*OptEntityIdTableEntryObject);
- if (!ExpectedEntityIdTableEntry) {
- return ErrorBuilder::wrap(ExpectedEntityIdTableEntry.takeError())
- .context(ErrorMessages::ReadingFromIndex, "EntityIdTable entry",
- Index)
- .build();
- }
-
- auto [EntityIt, EntityInserted] =
- Entities.emplace(std::move(*ExpectedEntityIdTableEntry));
- if (!EntityInserted) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedInsertionOnDuplication,
- "EntityIdTable entry", Index,
- EntityIt->second)
- .build();
- }
- }
-
- return IdTable;
-}
-
-llvm::Expected<EntityIdTable>
-JSONFormat::tuEntityIdTableFromJSON(const Array &EntityIdTableArray) const {
- return entityIdTableFromJSONImpl(
- EntityIdTableArray,
- [this](const Object &O) { return tuEntityIdTableEntryFromJSON(O); },
- [](EntityIdTable &T) -> std::map<EntityName, EntityId> & {
- return getEntities(T);
- });
-}
-
-Array JSONFormat::tuEntityIdTableToJSON(const EntityIdTable &IdTable) const {
- Array EntityIdTableArray;
- const auto &Entities = getEntities(IdTable);
- EntityIdTableArray.reserve(Entities.size());
-
- for (const auto &[EntityName, EntityId] : Entities) {
- EntityIdTableArray.push_back(
- tuEntityIdTableEntryToJSON(EntityName, EntityId));
- }
-
- return EntityIdTableArray;
-}
-
-llvm::Expected<EntityIdTable>
-JSONFormat::luEntityIdTableFromJSON(const Array &EntityIdTableArray) const {
- return entityIdTableFromJSONImpl(
- EntityIdTableArray,
- [this](const Object &O) { return luEntityIdTableEntryFromJSON(O); },
- [](EntityIdTable &T) -> std::map<EntityName, EntityId> & {
- return getEntities(T);
- });
-}
-
-Array JSONFormat::luEntityIdTableToJSON(const EntityIdTable &IdTable) const {
- Array EntityIdTableArray;
- const auto &Entities = getEntities(IdTable);
- EntityIdTableArray.reserve(Entities.size());
-
- for (const auto &[EntityName, EntityId] : Entities) {
- EntityIdTableArray.push_back(
- luEntityIdTableEntryToJSON(EntityName, EntityId));
- }
-
- return EntityIdTableArray;
-}
-
-//----------------------------------------------------------------------------
-// LinkageTableEntry
-//----------------------------------------------------------------------------
-
-llvm::Expected<std::pair<EntityId, EntityLinkage>>
-JSONFormat::linkageTableEntryFromJSON(
- const Object &LinkageTableEntryObject) const {
- const Value *EntityIdIntValue = LinkageTableEntryObject.get("id");
- if (!EntityIdIntValue) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityId", "id",
- "number (unsigned 64-bit integer)")
- .build();
- }
-
- const std::optional<uint64_t> OptEntityIdInt =
- EntityIdIntValue->getAsUINT64();
- if (!OptEntityIdInt) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityId", "id",
- "number (unsigned 64-bit integer)")
- .build();
- }
-
- EntityId EI = entityIdFromJSON(*OptEntityIdInt);
-
- const Object *OptEntityLinkageObject =
- LinkageTableEntryObject.getObject("linkage");
- if (!OptEntityLinkageObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityLinkage", "linkage", "object")
- .build();
- }
-
- auto ExpectedEntityLinkage = entityLinkageFromJSON(*OptEntityLinkageObject);
- if (!ExpectedEntityLinkage) {
- return ErrorBuilder::wrap(ExpectedEntityLinkage.takeError())
- .context(ErrorMessages::ReadingFromField, "EntityLinkage", "linkage")
- .build();
- }
-
- return std::make_pair(std::move(EI), std::move(*ExpectedEntityLinkage));
-}
-
-Object JSONFormat::linkageTableEntryToJSON(EntityId EI,
- const EntityLinkage &EL) const {
- Object Entry;
- Entry["id"] = entityIdToJSON(EI);
- Entry["linkage"] = entityLinkageToJSON(EL);
- return Entry;
-}
-
-//----------------------------------------------------------------------------
-// LinkageTable
-//----------------------------------------------------------------------------
-
-// ExpectedIds is the set of EntityIds from the IdTable that must appear in the
-// linkage table—no more, no fewer. It is taken by value because it is consumed
-// during parsing: each successfully matched id is erased from the set, and any
-// ids remaining at the end are reported as missing.
-llvm::Expected<std::map<EntityId, EntityLinkage>>
-JSONFormat::linkageTableFromJSON(const Array &LinkageTableArray,
- std::set<EntityId> ExpectedIds) const {
- std::map<EntityId, EntityLinkage> LinkageTable;
-
- for (const auto &[Index, LinkageTableEntryValue] :
- llvm::enumerate(LinkageTableArray)) {
- const Object *OptLinkageTableEntryObject =
- LinkageTableEntryValue.getAsObject();
- if (!OptLinkageTableEntryObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtIndex,
- "LinkageTable entry", Index, "object")
- .build();
- }
-
- auto ExpectedLinkageTableEntry =
- linkageTableEntryFromJSON(*OptLinkageTableEntryObject);
- if (!ExpectedLinkageTableEntry) {
- return ErrorBuilder::wrap(ExpectedLinkageTableEntry.takeError())
- .context(ErrorMessages::ReadingFromIndex, "LinkageTable entry", Index)
- .build();
- }
-
- const EntityId EI = ExpectedLinkageTableEntry->first;
-
- auto [It, Inserted] =
- LinkageTable.insert(std::move(*ExpectedLinkageTableEntry));
- if (!Inserted) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedInsertionOnDuplication,
- "LinkageTable entry", Index, It->first)
- .build();
- }
-
- if (ExpectedIds.erase(EI) == 0) {
- return ErrorBuilder::create(
- std::errc::invalid_argument,
- ErrorMessages::FailedToDeserializeLinkageTableExtraId, EI)
- .context(ErrorMessages::ReadingFromIndex, "LinkageTable entry", Index)
- .build();
- }
- }
-
- if (!ExpectedIds.empty()) {
- return ErrorBuilder::create(
- std::errc::invalid_argument,
- ErrorMessages::FailedToDeserializeLinkageTableMissingId,
- *ExpectedIds.begin())
- .build();
- }
-
- return LinkageTable;
-}
-
-Array JSONFormat::linkageTableToJSON(
- const std::map<EntityId, EntityLinkage> &LinkageTable) const {
- Array Result;
- Result.reserve(LinkageTable.size());
-
- for (const auto &[EI, EL] : LinkageTable) {
- Result.push_back(linkageTableEntryToJSON(EI, EL));
- }
-
- return Result;
-}
-
-//----------------------------------------------------------------------------
-// EntitySummary
-//----------------------------------------------------------------------------
-
-llvm::Expected<std::unique_ptr<EntitySummary>>
-JSONFormat::entitySummaryFromJSON(const SummaryName &SN,
- const Object &EntitySummaryObject,
- EntityIdTable &IdTable) const {
- auto InfoIt = FormatInfos.find(SN);
- if (InfoIt == FormatInfos.end()) {
- return ErrorBuilder::create(
- std::errc::invalid_argument,
- ErrorMessages::FailedToDeserializeEntitySummaryNoFormatInfo, SN)
- .build();
- }
-
- const auto &InfoEntry = InfoIt->second;
- assert(InfoEntry.ForSummary == SN);
-
- return InfoEntry.Deserialize(EntitySummaryObject, IdTable,
- entityIdFromJSONObject);
-}
-
-llvm::Expected<Object>
-JSONFormat::entitySummaryToJSON(const SummaryName &SN,
- const EntitySummary &ES) const {
- auto InfoIt = FormatInfos.find(SN);
- if (InfoIt == FormatInfos.end()) {
- return ErrorBuilder::create(
- std::errc::invalid_argument,
- ErrorMessages::FailedToSerializeEntitySummaryNoFormatInfo, SN)
- .build();
- }
-
- const auto &InfoEntry = InfoIt->second;
- assert(InfoEntry.ForSummary == SN);
-
- return InfoEntry.Serialize(ES, entityIdToJSONObject);
-}
-
-//----------------------------------------------------------------------------
-// EntityDataMapEntry
-//----------------------------------------------------------------------------
-
-llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummary>>>
-JSONFormat::entityDataMapEntryFromJSON(const Object &EntityDataMapEntryObject,
- const SummaryName &SN,
- EntityIdTable &IdTable) const {
-
- const Value *EntityIdIntValue = EntityDataMapEntryObject.get("entity_id");
- if (!EntityIdIntValue) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityId", "entity_id",
- "number (unsigned 64-bit integer)")
- .build();
- }
-
- const std::optional<uint64_t> OptEntityIdInt =
- EntityIdIntValue->getAsUINT64();
- if (!OptEntityIdInt) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityId", "entity_id",
- "number (unsigned 64-bit integer)")
- .build();
- }
-
- EntityId EI = entityIdFromJSON(*OptEntityIdInt);
-
- const Object *OptEntitySummaryObject =
- EntityDataMapEntryObject.getObject("entity_summary");
- if (!OptEntitySummaryObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntitySummary", "entity_summary", "object")
- .build();
- }
-
- auto ExpectedEntitySummary =
- entitySummaryFromJSON(SN, *OptEntitySummaryObject, IdTable);
- if (!ExpectedEntitySummary) {
- return ErrorBuilder::wrap(ExpectedEntitySummary.takeError())
- .context(ErrorMessages::ReadingFromField, "EntitySummary",
- "entity_summary")
- .build();
- }
-
- if (*ExpectedEntitySummary == nullptr) {
- return ErrorBuilder::create(
- std::errc::invalid_argument,
- ErrorMessages::FailedToDeserializeEntitySummaryMissingData, SN)
- .build();
- }
-
- auto ActualSN = (*ExpectedEntitySummary)->getSummaryName();
- if (SN != ActualSN) {
- return ErrorBuilder::create(
- std::errc::invalid_argument,
- ErrorMessages::
- FailedToDeserializeEntitySummaryMismatchedSummaryName,
- SN, ActualSN)
- .build();
- }
-
- return std::make_pair(std::move(EI), std::move(*ExpectedEntitySummary));
-}
-
-llvm::Expected<Object> JSONFormat::entityDataMapEntryToJSON(
- const EntityId EI, const std::unique_ptr<EntitySummary> &EntitySummary,
- const SummaryName &SN) const {
- Object Entry;
-
- Entry["entity_id"] = entityIdToJSON(EI);
-
- if (!EntitySummary) {
- ErrorBuilder::fatal(
- ErrorMessages::FailedToSerializeEntitySummaryMissingData, SN);
- }
-
- const auto ActualSN = EntitySummary->getSummaryName();
- if (SN != ActualSN) {
- ErrorBuilder::fatal(
- ErrorMessages::FailedToSerializeEntitySummaryMismatchedSummaryName, SN,
- ActualSN);
- }
-
- auto ExpectedEntitySummaryObject = entitySummaryToJSON(SN, *EntitySummary);
- if (!ExpectedEntitySummaryObject) {
- return ErrorBuilder::wrap(ExpectedEntitySummaryObject.takeError())
- .context(ErrorMessages::WritingToField, "EntitySummary",
- "entity_summary")
- .build();
- }
-
- Entry["entity_summary"] = std::move(*ExpectedEntitySummaryObject);
-
- return Entry;
-}
-
-//----------------------------------------------------------------------------
-// EntityDataMap
-//----------------------------------------------------------------------------
-
-llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummary>>>
-JSONFormat::entityDataMapFromJSON(const SummaryName &SN,
- const Array &EntityDataArray,
- EntityIdTable &IdTable) const {
- std::map<EntityId, std::unique_ptr<EntitySummary>> EntityDataMap;
-
- for (const auto &[Index, EntityDataMapEntryValue] :
- llvm::enumerate(EntityDataArray)) {
- const Object *OptEntityDataMapEntryObject =
- EntityDataMapEntryValue.getAsObject();
- if (!OptEntityDataMapEntryObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtIndex,
- "EntitySummary entry", Index, "object")
- .build();
- }
-
- auto ExpectedEntityDataMapEntry =
- entityDataMapEntryFromJSON(*OptEntityDataMapEntryObject, SN, IdTable);
- if (!ExpectedEntityDataMapEntry) {
- return ErrorBuilder::wrap(ExpectedEntityDataMapEntry.takeError())
- .context(ErrorMessages::ReadingFromIndex, "EntitySummary entry",
- Index)
- .build();
- }
-
- auto [DataIt, DataInserted] =
- EntityDataMap.insert(std::move(*ExpectedEntityDataMapEntry));
- if (!DataInserted) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedInsertionOnDuplication,
- "EntitySummary entry", Index, DataIt->first)
- .build();
- }
- }
-
- return std::move(EntityDataMap);
-}
-
-llvm::Expected<Array> JSONFormat::entityDataMapToJSON(
- const SummaryName &SN,
- const std::map<EntityId, std::unique_ptr<EntitySummary>> &EntityDataMap)
- const {
- Array Result;
- Result.reserve(EntityDataMap.size());
-
- for (const auto &[Index, EntityDataMapEntry] :
- llvm::enumerate(EntityDataMap)) {
- const auto &[EntityId, EntitySummary] = EntityDataMapEntry;
-
- auto ExpectedEntityDataMapEntryObject =
- entityDataMapEntryToJSON(EntityId, EntitySummary, SN);
-
- if (!ExpectedEntityDataMapEntryObject) {
- return ErrorBuilder::wrap(ExpectedEntityDataMapEntryObject.takeError())
- .context(ErrorMessages::WritingToIndex, "EntitySummary entry", Index)
- .build();
- }
-
- Result.push_back(std::move(*ExpectedEntityDataMapEntryObject));
- }
-
- return Result;
-}
-
-//----------------------------------------------------------------------------
-// SummaryDataMapEntry
-//----------------------------------------------------------------------------
-
-llvm::Expected<
- std::pair<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>>
-JSONFormat::summaryDataMapEntryFromJSON(const Object &SummaryDataMapEntryObject,
- EntityIdTable &IdTable) const {
-
- std::optional<llvm::StringRef> OptSummaryNameStr =
- SummaryDataMapEntryObject.getString("summary_name");
- if (!OptSummaryNameStr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "SummaryName", "summary_name", "string")
- .build();
- }
-
- SummaryName SN = summaryNameFromJSON(*OptSummaryNameStr);
-
- const Array *OptEntityDataArray =
- SummaryDataMapEntryObject.getArray("summary_data");
- if (!OptEntityDataArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntitySummary entries", "summary_data",
- "array")
- .build();
- }
-
- auto ExpectedEntityDataMap =
- entityDataMapFromJSON(SN, *OptEntityDataArray, IdTable);
- if (!ExpectedEntityDataMap) {
- return ErrorBuilder::wrap(ExpectedEntityDataMap.takeError())
- .context(ErrorMessages::ReadingFromField, "EntitySummary entries",
- "summary_data")
- .build();
- }
-
- return std::make_pair(std::move(SN), std::move(*ExpectedEntityDataMap));
-}
-
-llvm::Expected<Object> JSONFormat::summaryDataMapEntryToJSON(
- const SummaryName &SN,
- const std::map<EntityId, std::unique_ptr<EntitySummary>> &SD) const {
- Object Result;
-
- Result["summary_name"] = summaryNameToJSON(SN);
-
- auto ExpectedSummaryDataArray = entityDataMapToJSON(SN, SD);
- if (!ExpectedSummaryDataArray) {
- return ErrorBuilder::wrap(ExpectedSummaryDataArray.takeError())
- .context(ErrorMessages::WritingToField, "EntitySummary entries",
- "summary_data")
- .build();
- }
-
- Result["summary_data"] = std::move(*ExpectedSummaryDataArray);
-
- return Result;
-}
-
-//----------------------------------------------------------------------------
-// SummaryDataMap
-//----------------------------------------------------------------------------
-
-llvm::Expected<
- std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>>
-JSONFormat::summaryDataMapFromJSON(const Array &SummaryDataArray,
- EntityIdTable &IdTable) const {
- std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>
- SummaryDataMap;
-
- for (const auto &[Index, SummaryDataMapEntryValue] :
- llvm::enumerate(SummaryDataArray)) {
- const Object *OptSummaryDataMapEntryObject =
- SummaryDataMapEntryValue.getAsObject();
- if (!OptSummaryDataMapEntryObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtIndex,
- "SummaryData entry", Index, "object")
- .build();
- }
-
- auto ExpectedSummaryDataMapEntry =
- summaryDataMapEntryFromJSON(*OptSummaryDataMapEntryObject, IdTable);
- if (!ExpectedSummaryDataMapEntry) {
- return ErrorBuilder::wrap(ExpectedSummaryDataMapEntry.takeError())
- .context(ErrorMessages::ReadingFromIndex, "SummaryData entry", Index)
- .build();
- }
-
- auto [SummaryIt, SummaryInserted] =
- SummaryDataMap.emplace(std::move(*ExpectedSummaryDataMapEntry));
- if (!SummaryInserted) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedInsertionOnDuplication,
- "SummaryData entry", Index, SummaryIt->first)
- .build();
- }
- }
-
- return std::move(SummaryDataMap);
-}
-
-llvm::Expected<Array> JSONFormat::summaryDataMapToJSON(
- const std::map<SummaryName,
- std::map<EntityId, std::unique_ptr<EntitySummary>>>
- &SummaryDataMap) const {
- Array Result;
- Result.reserve(SummaryDataMap.size());
-
- for (const auto &[Index, SummaryDataMapEntry] :
- llvm::enumerate(SummaryDataMap)) {
- const auto &[SummaryName, DataMap] = SummaryDataMapEntry;
-
- auto ExpectedSummaryDataMapObject =
- summaryDataMapEntryToJSON(SummaryName, DataMap);
- if (!ExpectedSummaryDataMapObject) {
- return ErrorBuilder::wrap(ExpectedSummaryDataMapObject.takeError())
- .context(ErrorMessages::WritingToIndex, "SummaryData entry", Index)
- .build();
- }
-
- Result.push_back(std::move(*ExpectedSummaryDataMapObject));
- }
-
- return std::move(Result);
-}
-
-//----------------------------------------------------------------------------
-// EncodingDataMapEntry
-//----------------------------------------------------------------------------
-
-llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
-JSONFormat::encodingDataMapEntryFromJSON(
- const Object &EntityDataMapEntryObject) const {
- const Value *EntityIdIntValue = EntityDataMapEntryObject.get("entity_id");
- if (!EntityIdIntValue) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityId", "entity_id",
- "number (unsigned 64-bit integer)")
- .build();
- }
-
- const std::optional<uint64_t> OptEntityIdInt =
- EntityIdIntValue->getAsUINT64();
- if (!OptEntityIdInt) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntityId", "entity_id",
- "number (unsigned 64-bit integer)")
- .build();
- }
-
- EntityId EI = entityIdFromJSON(*OptEntityIdInt);
-
- const Object *OptEntitySummaryObject =
- EntityDataMapEntryObject.getObject("entity_summary");
- if (!OptEntitySummaryObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntitySummary", "entity_summary", "object")
- .build();
- }
-
- std::unique_ptr<EntitySummaryEncoding> Encoding(
- new JSONEntitySummaryEncoding(Value(Object(*OptEntitySummaryObject))));
-
- return std::make_pair(std::move(EI), std::move(Encoding));
-}
-
-Object JSONFormat::encodingDataMapEntryToJSON(
- EntityId EI, const std::unique_ptr<EntitySummaryEncoding> &Encoding) const {
- Object Entry;
- Entry["entity_id"] = entityIdToJSON(EI);
-
- // All EntitySummaryEncoding objects stored in a TUSummaryEncoding or
- // LUSummaryEncoding read by JSONFormat are JSONEntitySummaryEncoding
- // instances, since encodingDataMapEntryFromJSON is the only place that
- // creates them.
- auto *JSONEncoding = static_cast<JSONEntitySummaryEncoding *>(Encoding.get());
- Entry["entity_summary"] = JSONEncoding->Data;
-
- return Entry;
-}
-
-//----------------------------------------------------------------------------
-// EncodingDataMap
-//----------------------------------------------------------------------------
-
-llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
-JSONFormat::encodingDataMapFromJSON(const Array &EntityDataArray) const {
- std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>> EncodingDataMap;
-
- for (const auto &[Index, EntityDataMapEntryValue] :
- llvm::enumerate(EntityDataArray)) {
- const Object *OptEntityDataMapEntryObject =
- EntityDataMapEntryValue.getAsObject();
- if (!OptEntityDataMapEntryObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtIndex,
- "EntitySummary entry", Index, "object")
- .build();
- }
-
- auto ExpectedEntry =
- encodingDataMapEntryFromJSON(*OptEntityDataMapEntryObject);
- if (!ExpectedEntry) {
- return ErrorBuilder::wrap(ExpectedEntry.takeError())
- .context(ErrorMessages::ReadingFromIndex, "EntitySummary entry",
- Index)
- .build();
- }
-
- auto [DataIt, DataInserted] =
- EncodingDataMap.insert(std::move(*ExpectedEntry));
- if (!DataInserted) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedInsertionOnDuplication,
- "EntitySummary entry", Index, DataIt->first)
- .build();
- }
- }
-
- return std::move(EncodingDataMap);
-}
-
-Array JSONFormat::encodingDataMapToJSON(
- const std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>
- &EncodingDataMap) const {
- Array Result;
- Result.reserve(EncodingDataMap.size());
-
- for (const auto &[EI, Encoding] : EncodingDataMap) {
- Result.push_back(encodingDataMapEntryToJSON(EI, Encoding));
- }
-
- return Result;
-}
-
-//----------------------------------------------------------------------------
-// EncodingSummaryDataMapEntry
-//----------------------------------------------------------------------------
-
-llvm::Expected<std::pair<
- SummaryName, std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>>
-JSONFormat::encodingSummaryDataMapEntryFromJSON(
- const Object &SummaryDataMapEntryObject) const {
- std::optional<llvm::StringRef> OptSummaryNameStr =
- SummaryDataMapEntryObject.getString("summary_name");
- if (!OptSummaryNameStr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "SummaryName", "summary_name", "string")
- .build();
- }
-
- SummaryName SN = summaryNameFromJSON(*OptSummaryNameStr);
-
- const Array *OptEntityDataArray =
- SummaryDataMapEntryObject.getArray("summary_data");
- if (!OptEntityDataArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "EntitySummary entries", "summary_data",
- "array")
- .build();
- }
-
- auto ExpectedEncodingDataMap = encodingDataMapFromJSON(*OptEntityDataArray);
- if (!ExpectedEncodingDataMap) {
- return ErrorBuilder::wrap(ExpectedEncodingDataMap.takeError())
- .context(ErrorMessages::ReadingFromField, "EntitySummary entries",
- "summary_data")
- .build();
- }
-
- return std::make_pair(std::move(SN), std::move(*ExpectedEncodingDataMap));
-}
-
-Object JSONFormat::encodingSummaryDataMapEntryToJSON(
- const SummaryName &SN,
- const std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>
- &EncodingMap) const {
- Object Result;
-
- Result["summary_name"] = summaryNameToJSON(SN);
- Result["summary_data"] = encodingDataMapToJSON(EncodingMap);
-
- return Result;
-}
-
-//----------------------------------------------------------------------------
-// EncodingSummaryDataMap
-//----------------------------------------------------------------------------
-
-llvm::Expected<std::map<
- SummaryName, std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>>
-JSONFormat::encodingSummaryDataMapFromJSON(
- const Array &SummaryDataArray) const {
- std::map<SummaryName,
- std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
- EncodingSummaryDataMap;
-
- for (const auto &[Index, SummaryDataMapEntryValue] :
- llvm::enumerate(SummaryDataArray)) {
- const Object *OptSummaryDataMapEntryObject =
- SummaryDataMapEntryValue.getAsObject();
- if (!OptSummaryDataMapEntryObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtIndex,
- "SummaryData entry", Index, "object")
- .build();
- }
-
- auto ExpectedEntry =
- encodingSummaryDataMapEntryFromJSON(*OptSummaryDataMapEntryObject);
- if (!ExpectedEntry) {
- return ErrorBuilder::wrap(ExpectedEntry.takeError())
- .context(ErrorMessages::ReadingFromIndex, "SummaryData entry", Index)
- .build();
- }
-
- auto [SummaryIt, SummaryInserted] =
- EncodingSummaryDataMap.emplace(std::move(*ExpectedEntry));
- if (!SummaryInserted) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedInsertionOnDuplication,
- "SummaryData entry", Index, SummaryIt->first)
- .build();
- }
- }
-
- return std::move(EncodingSummaryDataMap);
-}
-
-Array JSONFormat::encodingSummaryDataMapToJSON(
- const std::map<SummaryName,
- std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
- &EncodingSummaryDataMap) const {
- Array Result;
- Result.reserve(EncodingSummaryDataMap.size());
-
- for (const auto &[SN, EncodingMap] : EncodingSummaryDataMap) {
- Result.push_back(encodingSummaryDataMapEntryToJSON(SN, EncodingMap));
- }
-
- return Result;
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h
deleted file mode 100644
index 44eb62fba6024..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h
+++ /dev/null
@@ -1,219 +0,0 @@
-//===- JSONFormatImpl.h -----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Internal implementation header shared by all translation units in the
-// JSONFormat subdirectory. Not part of the public API.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
-#define LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
-
-#include "../../ModelStringConversions.h"
-#include "JSONEntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Registry.h"
-
-namespace clang::ssaf {
-
-using Array = llvm::json::Array;
-using Object = llvm::json::Object;
-using Value = llvm::json::Value;
-
-//----------------------------------------------------------------------------
-// File Format Constant
-//----------------------------------------------------------------------------
-
-inline constexpr const char *JSONFormatFileExtension = ".json";
-
-//----------------------------------------------------------------------------
-// Error Message Constants
-//----------------------------------------------------------------------------
-
-namespace ErrorMessages {
-
-inline constexpr const char *FailedToReadFile =
- "failed to read file '{0}': {1}";
-inline constexpr const char *FailedToWriteFile =
- "failed to write file '{0}': {1}";
-inline constexpr const char *FileNotFound = "file does not exist";
-inline constexpr const char *FileIsDirectory =
- "path is a directory, not a file";
-inline constexpr const char *FileIsNotJSON =
- "file does not end with '{0}' extension";
-inline constexpr const char *FileExists = "file already exists";
-inline constexpr const char *ParentDirectoryNotFound =
- "parent directory does not exist";
-
-inline constexpr const char *ReadingFromField = "reading {0} from field '{1}'";
-inline constexpr const char *WritingToField = "writing {0} to field '{1}'";
-inline constexpr const char *ReadingFromIndex = "reading {0} from index '{1}'";
-inline constexpr const char *WritingToIndex = "writing {0} to index '{1}'";
-inline constexpr const char *ReadingFromFile = "reading {0} from file '{1}'";
-inline constexpr const char *WritingToFile = "writing {0} to file '{1}'";
-
-inline constexpr const char *FailedInsertionOnDuplication =
- "failed to insert {0} at index '{1}': encountered duplicate '{2}'";
-
-inline constexpr const char *FailedToReadObject =
- "failed to read {0}: expected JSON {1}";
-inline constexpr const char *FailedToReadObjectAtField =
- "failed to read {0} from field '{1}': expected JSON {2}";
-inline constexpr const char *FailedToReadObjectAtIndex =
- "failed to read {0} from index '{1}': expected JSON {2}";
-
-inline constexpr const char *MismatchedSummaryType =
- "expected '{0}' for field '{1}' but got '{2}'";
-inline constexpr const char *UnknownArtifactType =
- "unknown value '{0}' for field '{1}': expected '{2}', '{3}', or '{4}'";
-inline constexpr const char *UnknownArtifactEncodingType =
- "unknown value '{0}' for field '{1}': expected '{2}', or '{3}'";
-
-inline constexpr const char *FailedToDeserializeEntitySummaryNoFormatInfo =
- "failed to deserialize EntitySummary: no FormatInfo registered for '{0}'";
-inline constexpr const char *FailedToSerializeEntitySummaryNoFormatInfo =
- "failed to serialize EntitySummary: no FormatInfo registered for '{0}'";
-
-inline constexpr const char *FailedToDeserializeEntitySummaryMissingData =
- "failed to deserialize EntitySummary: null EntitySummary data for '{0}'";
-inline constexpr const char *FailedToSerializeEntitySummaryMissingData =
- "JSONFormat - null EntitySummary data for '{0}'";
-
-inline constexpr const char
- *FailedToDeserializeEntitySummaryMismatchedSummaryName =
- "failed to deserialize EntitySummary: EntitySummary data for '{0}' "
- "reports mismatched '{1}'";
-inline constexpr const char
- *FailedToSerializeEntitySummaryMismatchedSummaryName =
- "JSONFormat - EntitySummary data for '{0}' reports mismatched '{1}'";
-
-inline constexpr const char *InvalidBuildNamespaceKind =
- "invalid BuildNamespaceKind value '{0}' for field 'kind'";
-
-inline constexpr const char *InvalidEntityLinkageType =
- "invalid EntityLinkageType value '{0}' for field 'type'";
-
-inline constexpr const char *FailedToDeserializeLinkageTableExtraId =
- "failed to deserialize LinkageTable: extra '{0}' not present in IdTable";
-
-inline constexpr const char *FailedToDeserializeLinkageTableMissingId =
- "failed to deserialize LinkageTable: missing '{0}' present in IdTable";
-
-inline constexpr const char *FailedToReadEntityIdObject =
- "failed to read EntityId: expected JSON object with a single '{0}' key "
- "mapped to a number (unsigned 64-bit integer)";
-
-inline constexpr const char *FailedToPatchEntityIdNotInTable =
- "failed to patch EntityId: '{0}' not found in entity resolution table";
-
-inline constexpr const char *TargetTripleNotNormalized =
- "target triple '{0}' is not in normalized form (expected '{1}')";
-
-} // namespace ErrorMessages
-
-//----------------------------------------------------------------------------
-// Entity Id JSON Representation
-//----------------------------------------------------------------------------
-
-/// An entity ID is encoded as the single-key object {"@": <index>}.
-inline constexpr const char *JSONEntityIdKey = "@";
-
-//----------------------------------------------------------------------------
-// Summary Type JSON Representation
-//----------------------------------------------------------------------------
-
-/// Root-object key naming the summary kind so files are self-describing.
-inline constexpr const char *JSONTypeKey = "type";
-
-/// Value written to \c JSONTypeKey for serialized \c TUSummary files.
-inline constexpr const char *JSONTypeValueTUSummary = "TUSummary";
-
-/// Value written to \c JSONTypeKey for serialized \c LUSummary files.
-inline constexpr const char *JSONTypeValueLUSummary = "LUSummary";
-
-/// Value written to \c JSONTypeKey for serialized \c WPASuite files.
-inline constexpr const char *JSONTypeValueWPASuite = "WPASuite";
-
-/// Reads the \c JSONTypeKey field from the root object and verifies it
-/// equals \p ExpectedType. Returns success or an error with the field
-/// missing/mismatch detail.
-llvm::Error checkSummaryType(const Object &RootObject,
- llvm::StringRef ExpectedType);
-
-/// Reads the \c JSONTypeKey field from the root object as a string.
-/// Returns the string on success; on error, the message is suitable for
-/// callers that want to report the missing field themselves.
-llvm::Expected<llvm::StringRef> readSummaryType(const Object &RootObject);
-
-//----------------------------------------------------------------------------
-// JSON Reader and Writer
-//----------------------------------------------------------------------------
-
-llvm::Expected<Value> readJSON(llvm::StringRef Path);
-llvm::Error writeJSON(Value &&V, llvm::StringRef Path);
-
-//----------------------------------------------------------------------------
-// SummaryName helpers (free functions, anonymous-namespace in .cpp)
-//----------------------------------------------------------------------------
-
-SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr);
-llvm::StringRef summaryNameToJSON(const SummaryName &SN);
-
-//----------------------------------------------------------------------------
-// AnalysisName helpers
-//----------------------------------------------------------------------------
-
-AnalysisName analysisNameFromJSON(llvm::StringRef AnalysisNameStr);
-llvm::StringRef analysisNameToJSON(const AnalysisName &AN);
-
-//----------------------------------------------------------------------------
-// BuildNamespaceKind helpers
-//----------------------------------------------------------------------------
-
-llvm::Expected<BuildNamespaceKind>
-buildNamespaceKindFromJSON(llvm::StringRef BuildNamespaceKindStr);
-
-// Provided for consistency with respect to rest of the codebase.
-llvm::StringRef buildNamespaceKindToJSON(BuildNamespaceKind BNK);
-
-//----------------------------------------------------------------------------
-// EntityLinkageType helpers
-//----------------------------------------------------------------------------
-
-llvm::Expected<EntityLinkageType>
-entityLinkageTypeFromJSON(llvm::StringRef EntityLinkageTypeStr);
-
-// Provided for consistency with respect to rest of the codebase.
-llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT);
-
-//----------------------------------------------------------------------------
-// TargetTriple helpers
-//----------------------------------------------------------------------------
-
-/// Validates that \p Triple is a target triple string in normalized form.
-/// Returns success if \p Triple equals \c llvm::Triple::normalize(Triple),
-/// otherwise returns an \c invalid_argument error describing the expected
-/// normalized form.
-llvm::Error validateNormalizedTargetTriple(llvm::StringRef Triple);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_LIB_SCALABLESTATICANALYSISFRAMEWORK_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummary.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummary.cpp
deleted file mode 100644
index b0f7059b5fffc..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummary.cpp
+++ /dev/null
@@ -1,196 +0,0 @@
-//===- LUSummary.cpp ------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONFormatImpl.h"
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "llvm/TargetParser/Triple.h"
-
-#include <set>
-
-namespace clang::ssaf {
-
-//----------------------------------------------------------------------------
-// LUSummary
-//----------------------------------------------------------------------------
-
-llvm::Expected<LUSummary> JSONFormat::readLUSummary(llvm::StringRef Path) {
- auto ExpectedJSON = readJSON(Path);
- if (!ExpectedJSON) {
- return ErrorBuilder::wrap(ExpectedJSON.takeError())
- .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
- .build();
- }
-
- Object *RootObjectPtr = ExpectedJSON->getAsObject();
- if (!RootObjectPtr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObject, "LUSummary",
- "object")
- .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
- .build();
- }
-
- if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueLUSummary)) {
- return ErrorBuilder::wrap(std::move(Err))
- .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
- .build();
- }
-
- auto ExpectedSummary = readLUSummaryFromObject(*RootObjectPtr);
- if (!ExpectedSummary) {
- return ErrorBuilder::wrap(ExpectedSummary.takeError())
- .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
- .build();
- }
-
- return std::move(*ExpectedSummary);
-}
-
-llvm::Expected<LUSummary>
-JSONFormat::readLUSummaryFromObject(const Object &RootObject) {
- auto OptTargetTriple = RootObject.getString("target_triple");
- if (!OptTargetTriple) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "TargetTriple", "target_triple", "string")
- .build();
- }
-
- if (auto Err = validateNormalizedTargetTriple(*OptTargetTriple)) {
- return ErrorBuilder::wrap(std::move(Err))
- .context(ErrorMessages::ReadingFromField, "TargetTriple",
- "target_triple")
- .build();
- }
-
- llvm::Triple T(*OptTargetTriple);
-
- const Array *LUNamespaceArray = RootObject.getArray("lu_namespace");
- if (!LUNamespaceArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "NestedBuildNamespace", "lu_namespace", "array")
- .build();
- }
-
- auto ExpectedLUNamespace = nestedBuildNamespaceFromJSON(*LUNamespaceArray);
- if (!ExpectedLUNamespace) {
- return ErrorBuilder::wrap(ExpectedLUNamespace.takeError())
- .context(ErrorMessages::ReadingFromField, "NestedBuildNamespace",
- "lu_namespace")
- .build();
- }
-
- LUSummary Summary(std::move(T), std::move(*ExpectedLUNamespace));
-
- {
- const Array *IdTableArray = RootObject.getArray("id_table");
- if (!IdTableArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "IdTable", "id_table", "array")
- .build();
- }
-
- auto ExpectedIdTable = luEntityIdTableFromJSON(*IdTableArray);
- if (!ExpectedIdTable) {
- return ErrorBuilder::wrap(ExpectedIdTable.takeError())
- .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
- .build();
- }
-
- getIdTable(Summary) = std::move(*ExpectedIdTable);
- }
-
- {
- const Array *LinkageTableArray = RootObject.getArray("linkage_table");
- if (!LinkageTableArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "LinkageTable", "linkage_table", "array")
- .build();
- }
-
- auto ExpectedIdRange =
- llvm::make_second_range(getEntities(getIdTable(Summary)));
- std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
- ExpectedIdRange.end());
-
- // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
- // that the linkage table contains exactly the ids present in the IdTable.
- auto ExpectedLinkageTable =
- linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds));
- if (!ExpectedLinkageTable) {
- return ErrorBuilder::wrap(ExpectedLinkageTable.takeError())
- .context(ErrorMessages::ReadingFromField, "LinkageTable",
- "linkage_table")
- .build();
- }
-
- getLinkageTable(Summary) = std::move(*ExpectedLinkageTable);
- }
-
- {
- const Array *SummaryDataArray = RootObject.getArray("data");
- if (!SummaryDataArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "SummaryData entries", "data", "array")
- .build();
- }
-
- auto ExpectedSummaryDataMap =
- summaryDataMapFromJSON(*SummaryDataArray, getIdTable(Summary));
- if (!ExpectedSummaryDataMap) {
- return ErrorBuilder::wrap(ExpectedSummaryDataMap.takeError())
- .context(ErrorMessages::ReadingFromField, "SummaryData entries",
- "data")
- .build();
- }
-
- getData(Summary) = std::move(*ExpectedSummaryDataMap);
- }
-
- return std::move(Summary);
-}
-
-llvm::Error JSONFormat::writeLUSummary(const LUSummary &S,
- llvm::StringRef Path) {
- Object RootObject;
-
- RootObject[JSONTypeKey] = JSONTypeValueLUSummary;
-
- RootObject["target_triple"] =
- llvm::Triple::normalize(getTargetTriple(S).str());
-
- RootObject["lu_namespace"] = nestedBuildNamespaceToJSON(getLUNamespace(S));
-
- RootObject["id_table"] = luEntityIdTableToJSON(getIdTable(S));
-
- RootObject["linkage_table"] = linkageTableToJSON(getLinkageTable(S));
-
- auto ExpectedDataObject = summaryDataMapToJSON(getData(S));
- if (!ExpectedDataObject) {
- return ErrorBuilder::wrap(ExpectedDataObject.takeError())
- .context(ErrorMessages::WritingToFile, "LUSummary", Path)
- .build();
- }
-
- RootObject["data"] = std::move(*ExpectedDataObject);
-
- if (auto Error = writeJSON(std::move(RootObject), Path)) {
- return ErrorBuilder::wrap(std::move(Error))
- .context(ErrorMessages::WritingToFile, "LUSummary", Path)
- .build();
- }
-
- return llvm::Error::success();
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
deleted file mode 100644
index 691f8cb5b7be1..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-//===- LUSummaryEncoding.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONFormatImpl.h"
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "llvm/TargetParser/Triple.h"
-
-#include <set>
-
-namespace clang::ssaf {
-
-//----------------------------------------------------------------------------
-// LUSummaryEncoding
-//----------------------------------------------------------------------------
-
-llvm::Expected<LUSummaryEncoding>
-JSONFormat::readLUSummaryEncoding(llvm::StringRef Path) {
- auto ExpectedJSON = readJSON(Path);
- if (!ExpectedJSON) {
- return ErrorBuilder::wrap(ExpectedJSON.takeError())
- .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
- .build();
- }
-
- Object *RootObjectPtr = ExpectedJSON->getAsObject();
- if (!RootObjectPtr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObject, "LUSummary",
- "object")
- .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
- .build();
- }
-
- if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueLUSummary)) {
- return ErrorBuilder::wrap(std::move(Err))
- .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
- .build();
- }
-
- auto ExpectedEncoding = readLUSummaryEncodingFromObject(*RootObjectPtr);
- if (!ExpectedEncoding) {
- return ErrorBuilder::wrap(ExpectedEncoding.takeError())
- .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
- .build();
- }
-
- return std::move(*ExpectedEncoding);
-}
-
-llvm::Expected<LUSummaryEncoding>
-JSONFormat::readLUSummaryEncodingFromObject(const Object &RootObject) {
- auto OptTargetTriple = RootObject.getString("target_triple");
- if (!OptTargetTriple) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "TargetTriple", "target_triple", "string")
- .build();
- }
-
- if (auto Err = validateNormalizedTargetTriple(*OptTargetTriple)) {
- return ErrorBuilder::wrap(std::move(Err))
- .context(ErrorMessages::ReadingFromField, "TargetTriple",
- "target_triple")
- .build();
- }
-
- llvm::Triple T(*OptTargetTriple);
-
- const Array *LUNamespaceArray = RootObject.getArray("lu_namespace");
- if (!LUNamespaceArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "NestedBuildNamespace", "lu_namespace", "array")
- .build();
- }
-
- auto ExpectedLUNamespace = nestedBuildNamespaceFromJSON(*LUNamespaceArray);
- if (!ExpectedLUNamespace) {
- return ErrorBuilder::wrap(ExpectedLUNamespace.takeError())
- .context(ErrorMessages::ReadingFromField, "NestedBuildNamespace",
- "lu_namespace")
- .build();
- }
-
- LUSummaryEncoding Encoding(std::move(T), std::move(*ExpectedLUNamespace));
-
- {
- const Array *IdTableArray = RootObject.getArray("id_table");
- if (!IdTableArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "IdTable", "id_table", "array")
- .build();
- }
-
- auto ExpectedIdTable = luEntityIdTableFromJSON(*IdTableArray);
- if (!ExpectedIdTable) {
- return ErrorBuilder::wrap(ExpectedIdTable.takeError())
- .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
- .build();
- }
-
- getIdTable(Encoding) = std::move(*ExpectedIdTable);
- }
-
- {
- const Array *LinkageTableArray = RootObject.getArray("linkage_table");
- if (!LinkageTableArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "LinkageTable", "linkage_table", "array")
- .build();
- }
-
- auto ExpectedIdRange =
- llvm::make_second_range(getEntities(getIdTable(Encoding)));
- std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
- ExpectedIdRange.end());
-
- // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
- // that the linkage table contains exactly the ids present in the IdTable.
- auto ExpectedLinkageTable =
- linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds));
- if (!ExpectedLinkageTable) {
- return ErrorBuilder::wrap(ExpectedLinkageTable.takeError())
- .context(ErrorMessages::ReadingFromField, "LinkageTable",
- "linkage_table")
- .build();
- }
-
- getLinkageTable(Encoding) = std::move(*ExpectedLinkageTable);
- }
-
- {
- const Array *SummaryDataArray = RootObject.getArray("data");
- if (!SummaryDataArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "SummaryData entries", "data", "array")
- .build();
- }
-
- auto ExpectedEncodingSummaryDataMap =
- encodingSummaryDataMapFromJSON(*SummaryDataArray);
- if (!ExpectedEncodingSummaryDataMap) {
- return ErrorBuilder::wrap(ExpectedEncodingSummaryDataMap.takeError())
- .context(ErrorMessages::ReadingFromField, "SummaryData entries",
- "data")
- .build();
- }
-
- getData(Encoding) = std::move(*ExpectedEncodingSummaryDataMap);
- }
-
- return std::move(Encoding);
-}
-
-llvm::Error
-JSONFormat::writeLUSummaryEncoding(const LUSummaryEncoding &SummaryEncoding,
- llvm::StringRef Path) {
- Object RootObject;
-
- RootObject[JSONTypeKey] = JSONTypeValueLUSummary;
-
- RootObject["target_triple"] =
- llvm::Triple::normalize(getTargetTriple(SummaryEncoding).str());
-
- RootObject["lu_namespace"] =
- nestedBuildNamespaceToJSON(getLUNamespace(SummaryEncoding));
-
- RootObject["id_table"] = luEntityIdTableToJSON(getIdTable(SummaryEncoding));
-
- RootObject["linkage_table"] =
- linkageTableToJSON(getLinkageTable(SummaryEncoding));
-
- RootObject["data"] = encodingSummaryDataMapToJSON(getData(SummaryEncoding));
-
- if (auto Error = writeJSON(std::move(RootObject), Path)) {
- return ErrorBuilder::wrap(std::move(Error))
- .context(ErrorMessages::WritingToFile, "LUSummary", Path)
- .build();
- }
-
- return llvm::Error::success();
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummary.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummary.cpp
deleted file mode 100644
index 1f543b9a60710..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummary.cpp
+++ /dev/null
@@ -1,196 +0,0 @@
-//===- TUSummary.cpp ------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONFormatImpl.h"
-
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "llvm/TargetParser/Triple.h"
-
-#include <set>
-
-namespace clang::ssaf {
-
-//----------------------------------------------------------------------------
-// TUSummary
-//----------------------------------------------------------------------------
-
-llvm::Expected<TUSummary> JSONFormat::readTUSummary(llvm::StringRef Path) {
- auto ExpectedJSON = readJSON(Path);
- if (!ExpectedJSON) {
- return ErrorBuilder::wrap(ExpectedJSON.takeError())
- .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
- .build();
- }
-
- Object *RootObjectPtr = ExpectedJSON->getAsObject();
- if (!RootObjectPtr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObject, "TUSummary",
- "object")
- .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
- .build();
- }
-
- if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueTUSummary)) {
- return ErrorBuilder::wrap(std::move(Err))
- .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
- .build();
- }
-
- auto ExpectedSummary = readTUSummaryFromObject(*RootObjectPtr);
- if (!ExpectedSummary) {
- return ErrorBuilder::wrap(ExpectedSummary.takeError())
- .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
- .build();
- }
-
- return std::move(*ExpectedSummary);
-}
-
-llvm::Expected<TUSummary>
-JSONFormat::readTUSummaryFromObject(const Object &RootObject) {
- auto OptTargetTriple = RootObject.getString("target_triple");
- if (!OptTargetTriple) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "TargetTriple", "target_triple", "string")
- .build();
- }
-
- if (auto Err = validateNormalizedTargetTriple(*OptTargetTriple)) {
- return ErrorBuilder::wrap(std::move(Err))
- .context(ErrorMessages::ReadingFromField, "TargetTriple",
- "target_triple")
- .build();
- }
-
- llvm::Triple T(*OptTargetTriple);
-
- const Object *TUNamespaceObject = RootObject.getObject("tu_namespace");
- if (!TUNamespaceObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "BuildNamespace", "tu_namespace", "object")
- .build();
- }
-
- auto ExpectedTUNamespace = buildNamespaceFromJSON(*TUNamespaceObject);
- if (!ExpectedTUNamespace) {
- return ErrorBuilder::wrap(ExpectedTUNamespace.takeError())
- .context(ErrorMessages::ReadingFromField, "BuildNamespace",
- "tu_namespace")
- .build();
- }
-
- TUSummary Summary(std::move(T), std::move(*ExpectedTUNamespace));
-
- {
- const Array *IdTableArray = RootObject.getArray("id_table");
- if (!IdTableArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "IdTable", "id_table", "array")
- .build();
- }
-
- auto ExpectedIdTable = tuEntityIdTableFromJSON(*IdTableArray);
- if (!ExpectedIdTable) {
- return ErrorBuilder::wrap(ExpectedIdTable.takeError())
- .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
- .build();
- }
-
- getIdTable(Summary) = std::move(*ExpectedIdTable);
- }
-
- {
- const Array *LinkageTableArray = RootObject.getArray("linkage_table");
- if (!LinkageTableArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "LinkageTable", "linkage_table", "array")
- .build();
- }
-
- auto ExpectedIdRange =
- llvm::make_second_range(getEntities(getIdTable(Summary)));
- std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
- ExpectedIdRange.end());
-
- // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
- // that the linkage table contains exactly the ids present in the IdTable.
- auto ExpectedLinkageTable =
- linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds));
- if (!ExpectedLinkageTable) {
- return ErrorBuilder::wrap(ExpectedLinkageTable.takeError())
- .context(ErrorMessages::ReadingFromField, "LinkageTable",
- "linkage_table")
- .build();
- }
-
- getLinkageTable(Summary) = std::move(*ExpectedLinkageTable);
- }
-
- {
- const Array *SummaryDataArray = RootObject.getArray("data");
- if (!SummaryDataArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "SummaryData entries", "data", "array")
- .build();
- }
-
- auto ExpectedSummaryDataMap =
- summaryDataMapFromJSON(*SummaryDataArray, getIdTable(Summary));
- if (!ExpectedSummaryDataMap) {
- return ErrorBuilder::wrap(ExpectedSummaryDataMap.takeError())
- .context(ErrorMessages::ReadingFromField, "SummaryData entries",
- "data")
- .build();
- }
-
- getData(Summary) = std::move(*ExpectedSummaryDataMap);
- }
-
- return std::move(Summary);
-}
-
-llvm::Error JSONFormat::writeTUSummary(const TUSummary &S,
- llvm::StringRef Path) {
- Object RootObject;
-
- RootObject[JSONTypeKey] = JSONTypeValueTUSummary;
-
- RootObject["target_triple"] =
- llvm::Triple::normalize(getTargetTriple(S).str());
-
- RootObject["tu_namespace"] = buildNamespaceToJSON(getTUNamespace(S));
-
- RootObject["id_table"] = tuEntityIdTableToJSON(getIdTable(S));
-
- RootObject["linkage_table"] = linkageTableToJSON(getLinkageTable(S));
-
- auto ExpectedDataObject = summaryDataMapToJSON(getData(S));
- if (!ExpectedDataObject) {
- return ErrorBuilder::wrap(ExpectedDataObject.takeError())
- .context(ErrorMessages::WritingToFile, "TUSummary", Path)
- .build();
- }
-
- RootObject["data"] = std::move(*ExpectedDataObject);
-
- if (auto Error = writeJSON(std::move(RootObject), Path)) {
- return ErrorBuilder::wrap(std::move(Error))
- .context(ErrorMessages::WritingToFile, "TUSummary", Path)
- .build();
- }
-
- return llvm::Error::success();
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
deleted file mode 100644
index 20167447e92d7..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
+++ /dev/null
@@ -1,193 +0,0 @@
-//===- TUSummaryEncoding.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONFormatImpl.h"
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "llvm/TargetParser/Triple.h"
-
-#include <set>
-
-namespace clang::ssaf {
-
-//----------------------------------------------------------------------------
-// TUSummaryEncoding
-//----------------------------------------------------------------------------
-
-llvm::Expected<TUSummaryEncoding>
-JSONFormat::readTUSummaryEncoding(llvm::StringRef Path) {
- auto ExpectedJSON = readJSON(Path);
- if (!ExpectedJSON) {
- return ErrorBuilder::wrap(ExpectedJSON.takeError())
- .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
- .build();
- }
-
- Object *RootObjectPtr = ExpectedJSON->getAsObject();
- if (!RootObjectPtr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObject, "TUSummary",
- "object")
- .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
- .build();
- }
-
- if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueTUSummary)) {
- return ErrorBuilder::wrap(std::move(Err))
- .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
- .build();
- }
-
- auto ExpectedEncoding = readTUSummaryEncodingFromObject(*RootObjectPtr);
- if (!ExpectedEncoding) {
- return ErrorBuilder::wrap(ExpectedEncoding.takeError())
- .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
- .build();
- }
-
- return std::move(*ExpectedEncoding);
-}
-
-llvm::Expected<TUSummaryEncoding>
-JSONFormat::readTUSummaryEncodingFromObject(const Object &RootObject) {
- auto OptTargetTriple = RootObject.getString("target_triple");
- if (!OptTargetTriple) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "TargetTriple", "target_triple", "string")
- .build();
- }
-
- if (auto Err = validateNormalizedTargetTriple(*OptTargetTriple)) {
- return ErrorBuilder::wrap(std::move(Err))
- .context(ErrorMessages::ReadingFromField, "TargetTriple",
- "target_triple")
- .build();
- }
-
- llvm::Triple T(*OptTargetTriple);
-
- const Object *TUNamespaceObject = RootObject.getObject("tu_namespace");
- if (!TUNamespaceObject) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "BuildNamespace", "tu_namespace", "object")
- .build();
- }
-
- auto ExpectedTUNamespace = buildNamespaceFromJSON(*TUNamespaceObject);
- if (!ExpectedTUNamespace) {
- return ErrorBuilder::wrap(ExpectedTUNamespace.takeError())
- .context(ErrorMessages::ReadingFromField, "BuildNamespace",
- "tu_namespace")
- .build();
- }
-
- TUSummaryEncoding Encoding(std::move(T), std::move(*ExpectedTUNamespace));
-
- {
- const Array *IdTableArray = RootObject.getArray("id_table");
- if (!IdTableArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "IdTable", "id_table", "array")
- .build();
- }
-
- auto ExpectedIdTable = tuEntityIdTableFromJSON(*IdTableArray);
- if (!ExpectedIdTable) {
- return ErrorBuilder::wrap(ExpectedIdTable.takeError())
- .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
- .build();
- }
-
- getIdTable(Encoding) = std::move(*ExpectedIdTable);
- }
-
- {
- const Array *LinkageTableArray = RootObject.getArray("linkage_table");
- if (!LinkageTableArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "LinkageTable", "linkage_table", "array")
- .build();
- }
-
- auto ExpectedIdRange =
- llvm::make_second_range(getEntities(getIdTable(Encoding)));
- std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
- ExpectedIdRange.end());
-
- // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
- // that the linkage table contains exactly the ids present in the IdTable.
- auto ExpectedLinkageTable =
- linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds));
- if (!ExpectedLinkageTable) {
- return ErrorBuilder::wrap(ExpectedLinkageTable.takeError())
- .context(ErrorMessages::ReadingFromField, "LinkageTable",
- "linkage_table")
- .build();
- }
-
- getLinkageTable(Encoding) = std::move(*ExpectedLinkageTable);
- }
-
- {
- const Array *SummaryDataArray = RootObject.getArray("data");
- if (!SummaryDataArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "SummaryData entries", "data", "array")
- .build();
- }
-
- auto ExpectedEncodingSummaryDataMap =
- encodingSummaryDataMapFromJSON(*SummaryDataArray);
- if (!ExpectedEncodingSummaryDataMap) {
- return ErrorBuilder::wrap(ExpectedEncodingSummaryDataMap.takeError())
- .context(ErrorMessages::ReadingFromField, "SummaryData entries",
- "data")
- .build();
- }
-
- getData(Encoding) = std::move(*ExpectedEncodingSummaryDataMap);
- }
-
- return std::move(Encoding);
-}
-
-llvm::Error
-JSONFormat::writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding,
- llvm::StringRef Path) {
- Object RootObject;
-
- RootObject[JSONTypeKey] = JSONTypeValueTUSummary;
-
- RootObject["target_triple"] =
- llvm::Triple::normalize(getTargetTriple(SummaryEncoding).str());
-
- RootObject["tu_namespace"] =
- buildNamespaceToJSON(getTUNamespace(SummaryEncoding));
-
- RootObject["id_table"] = tuEntityIdTableToJSON(getIdTable(SummaryEncoding));
-
- RootObject["linkage_table"] =
- linkageTableToJSON(getLinkageTable(SummaryEncoding));
-
- RootObject["data"] = encodingSummaryDataMapToJSON(getData(SummaryEncoding));
-
- if (auto Error = writeJSON(std::move(RootObject), Path)) {
- return ErrorBuilder::wrap(std::move(Error))
- .context(ErrorMessages::WritingToFile, "TUSummary", Path)
- .build();
- }
-
- return llvm::Error::success();
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp
deleted file mode 100644
index e65a883279513..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-//===- WPASuite.cpp -------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONFormatImpl.h"
-
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-
-namespace clang::ssaf {
-
-//----------------------------------------------------------------------------
-// AnalysisResultMapEntry
-//----------------------------------------------------------------------------
-
-llvm::Expected<std::pair<AnalysisName, std::unique_ptr<AnalysisResult>>>
-JSONFormat::analysisResultMapEntryFromJSON(const Object &Entry) const {
- auto OptName = Entry.getString("analysis_name");
- if (!OptName) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "AnalysisName", "analysis_name", "string")
- .build();
- }
-
- AnalysisName Name = analysisNameFromJSON(*OptName);
-
- auto ExpectedCodec = AnalysisResultRegistry::instantiate(Name);
- if (!ExpectedCodec) {
- return ExpectedCodec.takeError();
- }
-
- const Object *ResultObj = Entry.getObject("result");
- if (!ResultObj) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "AnalysisResult", "result", "object")
- .build();
- }
-
- auto ExpectedResult =
- (*ExpectedCodec)->deserialize(*ResultObj, &entityIdFromJSONObject);
- if (!ExpectedResult) {
- return ExpectedResult.takeError();
- }
-
- return std::make_pair(std::move(Name), std::move(*ExpectedResult));
-}
-
-llvm::Expected<Object> JSONFormat::analysisResultMapEntryToJSON(
- const AnalysisName &Name,
- const std::unique_ptr<AnalysisResult> &Result) const {
- auto ExpectedCodec = AnalysisResultRegistry::instantiate(Name);
- if (!ExpectedCodec) {
- return ExpectedCodec.takeError();
- }
-
- Object Entry;
- Entry["analysis_name"] = analysisNameToJSON(Name);
- Entry["result"] = (*ExpectedCodec)->serialize(*Result, &entityIdToJSONObject);
- return Entry;
-}
-
-//----------------------------------------------------------------------------
-// AnalysisResultMap
-//----------------------------------------------------------------------------
-
-llvm::Expected<std::map<AnalysisName, std::unique_ptr<AnalysisResult>>>
-JSONFormat::analysisResultMapFromJSON(const Array &ResultsArray) const {
- std::map<AnalysisName, std::unique_ptr<AnalysisResult>> Results;
-
- auto AsObject = [](const Value &V) { return V.getAsObject(); };
- auto ObjectsRange = llvm::map_range(ResultsArray, AsObject);
-
- for (auto [I, Entry] : enumerate(ObjectsRange)) {
- if (!Entry) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtIndex,
- "WPA result entry", I, "object")
- .build();
- }
-
- auto ExpectedPair = analysisResultMapEntryFromJSON(*Entry);
- if (!ExpectedPair) {
- return ErrorBuilder::wrap(ExpectedPair.takeError())
- .context(ErrorMessages::ReadingFromIndex, "WPA result entry", I)
- .build();
- }
-
- auto [Name, Result] = std::move(*ExpectedPair);
- bool Inserted = Results.try_emplace(Name, std::move(Result)).second;
- if (!Inserted) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedInsertionOnDuplication,
- "WPA result", I, Name)
- .build();
- }
- }
- return std::move(Results);
-}
-
-llvm::Expected<Array> JSONFormat::analysisResultMapToJSON(
- const std::map<AnalysisName, std::unique_ptr<AnalysisResult>> &Data) const {
- Array Results;
- for (const auto &[Name, Result] : Data) {
- auto ExpectedEntry = analysisResultMapEntryToJSON(Name, Result);
- if (!ExpectedEntry) {
- return ExpectedEntry.takeError();
- }
- Results.push_back(std::move(*ExpectedEntry));
- }
- return Results;
-}
-
-//----------------------------------------------------------------------------
-// WPASuite
-//----------------------------------------------------------------------------
-
-llvm::Expected<WPASuite> JSONFormat::readWPASuite(llvm::StringRef Path) {
- auto ExpectedJSON = readJSON(Path);
- if (!ExpectedJSON) {
- return ErrorBuilder::wrap(ExpectedJSON.takeError())
- .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
- .build();
- }
-
- Object *RootObjectPtr = ExpectedJSON->getAsObject();
- if (!RootObjectPtr) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObject, "WPASuite",
- "object")
- .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
- .build();
- }
-
- if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueWPASuite)) {
- return ErrorBuilder::wrap(std::move(Err))
- .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
- .build();
- }
-
- auto ExpectedSuite = readWPASuiteFromObject(*RootObjectPtr);
- if (!ExpectedSuite) {
- return ErrorBuilder::wrap(ExpectedSuite.takeError())
- .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
- .build();
- }
-
- return std::move(*ExpectedSuite);
-}
-
-llvm::Expected<WPASuite>
-JSONFormat::readWPASuiteFromObject(const Object &RootObject) {
- WPASuite Suite = makeWPASuite();
-
- {
- const Array *IdTableArray = RootObject.getArray("id_table");
- if (!IdTableArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "IdTable", "id_table", "array")
- .build();
- }
-
- auto ExpectedIdTable = luEntityIdTableFromJSON(*IdTableArray);
- if (!ExpectedIdTable) {
- return ErrorBuilder::wrap(ExpectedIdTable.takeError())
- .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
- .build();
- }
-
- getIdTable(Suite) = std::move(*ExpectedIdTable);
- }
-
- {
- const Array *ResultsArray = RootObject.getArray("results");
- if (!ResultsArray) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- ErrorMessages::FailedToReadObjectAtField,
- "WPA results", "results", "array")
- .build();
- }
-
- auto ExpectedResultsMap = analysisResultMapFromJSON(*ResultsArray);
- if (!ExpectedResultsMap) {
- return ErrorBuilder::wrap(ExpectedResultsMap.takeError())
- .context(ErrorMessages::ReadingFromField, "WPA results", "results")
- .build();
- }
-
- getData(Suite) = std::move(*ExpectedResultsMap);
- }
-
- return std::move(Suite);
-}
-
-llvm::Error JSONFormat::writeWPASuite(const WPASuite &Suite,
- llvm::StringRef Path) {
- Object RootObject;
-
- RootObject[JSONTypeKey] = JSONTypeValueWPASuite;
-
- RootObject["id_table"] = luEntityIdTableToJSON(getIdTable(Suite));
-
- auto ExpectedResults = analysisResultMapToJSON(getData(Suite));
- if (!ExpectedResults) {
- return ErrorBuilder::wrap(ExpectedResults.takeError())
- .context(ErrorMessages::WritingToFile, "WPASuite", Path)
- .build();
- }
-
- RootObject["results"] = std::move(*ExpectedResults);
-
- if (auto Error = writeJSON(std::move(RootObject), Path)) {
- return ErrorBuilder::wrap(std::move(Error))
- .context(ErrorMessages::WritingToFile, "WPASuite", Path)
- .build();
- }
-
- return llvm::Error::success();
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.cpp
deleted file mode 100644
index 1219635e5068d..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-//===- SerializationFormatRegistry.cpp ------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include <memory>
-
-using namespace clang;
-using namespace ssaf;
-
-LLVM_DEFINE_REGISTRY(SerializationFormatRegistry)
-
-bool ssaf::isFormatRegistered(llvm::StringRef FormatName) {
- for (const auto &Entry : SerializationFormatRegistry::entries())
- if (Entry.getName() == FormatName)
- return true;
- return false;
-}
-
-std::unique_ptr<SerializationFormat>
-ssaf::makeFormat(llvm::StringRef FormatName) {
- for (const auto &Entry : SerializationFormatRegistry::entries())
- if (Entry.getName() == FormatName)
- return Entry.instantiate();
- assert(false && "Unknown SerializationFormat name");
- return nullptr;
-}
-
-void ssaf::printAvailableFormats(llvm::raw_ostream &OS) {
- OS << "OVERVIEW: Available SSAF serialization formats:\n\n";
- for (const auto &Entry : SerializationFormatRegistry::entries())
- OS << " " << Entry.getName() << " - " << Entry.getDesc() << "\n";
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.cpp
deleted file mode 100644
index 3021751213d72..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-//===- LUSummaryConsumer.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-
-using namespace clang;
-using namespace ssaf;
-
-llvm::Expected<std::unique_ptr<SummaryData>>
-LUSummaryConsumer::build(LUDataIterator LUIt) {
- const SummaryName SN = LUIt->first;
- auto Builder = SummaryDataBuilderRegistry::instantiate(SN.str());
- if (!Builder) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- "no builder registered for analysis '{0}'",
- SN.str())
- .build();
- }
-
- for (auto &[Id, Summary] : LUIt->second) {
- Builder->addSummary(Id, std::move(Summary));
- }
- Builder->finalize();
- LU->Data.erase(LUIt);
-
- return std::move(*Builder).takeData();
-}
-
-llvm::Expected<std::unique_ptr<SummaryData>>
-LUSummaryConsumer::build(const SummaryName &SN) {
- auto LUIt = LU->Data.find(SN);
- if (LUIt == LU->Data.end()) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- "no data for analysis '{0}' in LUSummary",
- SN.str())
- .build();
- }
- return build(LUIt);
-}
-
-llvm::Expected<SummaryDataStore>
-LUSummaryConsumer::run(llvm::ArrayRef<SummaryName> Names) {
- SummaryDataStore Store;
- for (const auto &SN : Names) {
- auto Result = build(SN);
- if (!Result) {
- return Result.takeError();
- }
- Store.Data.emplace(SN, std::move(*Result));
- }
- return std::move(Store);
-}
-
-SummaryDataStore LUSummaryConsumer::run() && {
- SummaryDataStore Store;
- // Advance the iterator before calling build(): build() erases the current
- // element on success, but std::map only invalidates iterators to the erased
- // element, so the pre-advanced iterator remains valid in all cases.
- auto It = LU->Data.begin();
- while (It != LU->Data.end()) {
- auto Current = It++; // Read the comment above!
- SummaryName SN = Current->first; // copy before build() potentially erases
- auto Result = build(Current);
- if (!Result) {
- llvm::consumeError(Result.takeError());
- continue;
- }
- Store.Data.emplace(std::move(SN), std::move(*Result));
- }
- return Store;
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.cpp
deleted file mode 100644
index 867290c6eac31..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- SummaryDataBuilderRegistry.cpp -------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h"
-
-using namespace clang;
-using namespace ssaf;
-
-using RegistryT = llvm::Registry<SummaryDataBuilderBase>;
-LLVM_DEFINE_REGISTRY(RegistryT)
-
-namespace {
-const RegistryT::entry *findEntry(llvm::StringRef Name) {
- for (const auto &Entry : RegistryT::entries()) {
- if (Entry.getName() == Name) {
- return &Entry;
- }
- }
- return nullptr;
-}
-} // namespace
-
-bool SummaryDataBuilderRegistry::contains(llvm::StringRef Name) {
- return findEntry(Name) != nullptr;
-}
-
-std::unique_ptr<SummaryDataBuilderBase>
-SummaryDataBuilderRegistry::instantiate(llvm::StringRef Name) {
- const auto *Entry = findEntry(Name);
- return Entry ? Entry->instantiate() : nullptr;
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.cpp
deleted file mode 100644
index 3abc42e171065..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-//===- ErrorBuilder.cpp ---------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include <cassert>
-
-namespace clang::ssaf {
-
-static constexpr llvm::StringLiteral ErrorSeparator = " + ";
-static constexpr llvm::StringLiteral ContextSeparator = "\n";
-
-ErrorBuilder ErrorBuilder::wrap(llvm::Error E) {
- assert(
- E &&
- "Cannot wrap a success error - check for success before calling wrap()");
-
- std::optional<std::error_code> EC;
- std::vector<std::string> Messages;
-
- llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) {
- // Capture error code from the first error only.
- if (!EC)
- EC = EI.convertToErrorCode();
-
- // Collect messages from all errors.
- std::string ErrorMsg = EI.message();
- if (!ErrorMsg.empty())
- Messages.push_back(std::move(ErrorMsg));
- });
-
- assert(EC && "wrap() called with a non-success error but no handler fired - "
- "indicates a bug in handleAllErrors");
-
- ErrorBuilder Builder(*EC);
-
- // Combine all messages with " + " and push as a single context entry.
- Builder.pushContext(llvm::join(Messages, ErrorSeparator));
-
- return Builder;
-}
-
-ErrorBuilder &ErrorBuilder::context(const char *Msg) {
- pushContext(std::string(Msg));
- return *this;
-}
-
-llvm::Error ErrorBuilder::build() const {
- // Reverse the context stack so that the most recent context appears first
- // and the wrapped error (if any) appears last.
- // Note: Even if ContextStack is empty, we create an error with the stored
- // error code and an empty message (this is valid in LLVM).
- return llvm::createStringError(
- llvm::join(llvm::reverse(ContextStack), ContextSeparator), Code);
-}
-
-} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
deleted file mode 100644
index b59d190dde519..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- ExtractorRegistry.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
-#include <memory>
-
-using namespace clang;
-using namespace ssaf;
-
-LLVM_DEFINE_REGISTRY(clang::ssaf::TUSummaryExtractorRegistry)
-
-bool ssaf::isTUSummaryExtractorRegistered(llvm::StringRef SummaryName) {
- for (const auto &Entry : TUSummaryExtractorRegistry::entries())
- if (Entry.getName() == SummaryName)
- return true;
- return false;
-}
-
-std::unique_ptr<TUSummaryExtractor>
-ssaf::makeTUSummaryExtractor(llvm::StringRef SummaryName,
- TUSummaryBuilder &Builder) {
- for (const auto &Entry : TUSummaryExtractorRegistry::entries())
- if (Entry.getName() == SummaryName)
- return Entry.instantiate(Builder);
- assert(false && "Unknown SummaryExtractor name");
- return nullptr;
-}
-
-void ssaf::printAvailableTUSummaryExtractors(llvm::raw_ostream &OS) {
- OS << "OVERVIEW: Available SSAF summary extractors:\n\n";
- for (const auto &Entry : TUSummaryExtractorRegistry::entries())
- OS << " " << Entry.getName() << " - " << Entry.getDesc() << "\n";
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
deleted file mode 100644
index daea76f7001cb..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- TUSummaryBuilder.cpp -----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include <memory>
-#include <utility>
-
-using namespace clang;
-using namespace ssaf;
-
-EntityId TUSummaryBuilder::addEntity(const EntityName &EN,
- EntityLinkageType Linkage) {
- EntityId Id = Summary.IdTable.getId(EN);
- [[maybe_unused]] EntityLinkageType Link =
- Summary.LinkageTable.try_emplace(Id, Linkage).first->second.getLinkage();
- // Even if we had in the past a linkage, that must bee the same as we set now.
- assert(Link == Linkage);
- return Id;
-}
-
-std::pair<EntitySummary *, bool>
-TUSummaryBuilder::addSummaryImpl(EntityId Entity,
- std::unique_ptr<EntitySummary> &&Data) {
- auto &EntitySummaries = Summary.Data[Data->getSummaryName()];
- auto [It, Inserted] = EntitySummaries.try_emplace(Entity, std::move(Data));
- return {It->second.get(), Inserted};
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp
deleted file mode 100644
index ccd5eef377d2d..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp
+++ /dev/null
@@ -1,80 +0,0 @@
-//===- TUSummaryExtractor.cpp ---------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclBase.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "llvm/Support/Casting.h"
-#include <optional>
-
-using namespace clang;
-using namespace ssaf;
-
-static EntityLinkageType getLinkageForDecl(const Decl *D) {
- const auto *ND = dyn_cast<NamedDecl>(D);
- if (!ND)
- return EntityLinkageType::None;
-
- // Parameters have no linkage in C++, but SSAF needs them to inherit
- // the external linkage from their parent functions.
- // Here is why:
- // SSAF treats parameters as entities and may not always associate them back
- // to their parent functions. Therefore, it needs to identify parameters of
- // functions with external linkage across different TUs. Treating them as
- // having no linkage (as in C++) causes the same parameter in different TUs
- // to be assigned different EntityIDs. As a result, the behavior of the
- // parameter across multiple TUs cannot be correlated.
- if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
- if (const auto *FD = llvm::dyn_cast_or_null<FunctionDecl>(
- PVD->getParentFunctionOrMethod())) {
- return getLinkageForDecl(FD);
- }
- }
-
- switch (ND->getFormalLinkage()) {
- case Linkage::Invalid: {
- llvm_unreachable("Shouldn't be invalid");
- }
- case Linkage::None:
- return EntityLinkageType::None;
- case Linkage::Internal:
- return EntityLinkageType::Internal;
- case Linkage::UniqueExternal:
- return EntityLinkageType::Internal;
- case Linkage::VisibleNone:
- return EntityLinkageType::Internal;
- case Linkage::Module:
- return EntityLinkageType::External;
- case Linkage::External:
- return EntityLinkageType::External;
- }
- llvm_unreachable("Unhandled clang::Linkage kind");
-}
-
-std::optional<EntityId> TUSummaryExtractor::addEntity(const NamedDecl *D) {
- auto Name = getEntityName(D);
- if (!Name)
- return std::nullopt;
- return SummaryBuilder.addEntity(*Name, getLinkageForDecl(D));
-}
-
-std::optional<EntityId>
-TUSummaryExtractor::addEntityForReturn(const FunctionDecl *FD) {
- auto Name = getEntityNameForReturn(FD);
- if (!Name)
- return std::nullopt;
- return SummaryBuilder.addEntity(*Name, getLinkageForDecl(FD));
-}
-
-const SSAFOptions &TUSummaryExtractor::getOptions() const {
- return SummaryBuilder.getOptions();
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.cpp
deleted file mode 100644
index 1425f7079295f..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-//===- AnalysisDriver.cpp -------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/ErrorHandling.h"
-#include <map>
-#include <vector>
-
-using namespace clang;
-using namespace ssaf;
-
-AnalysisDriver::AnalysisDriver(std::unique_ptr<LUSummary> LU)
- : LU(std::move(LU)) {}
-
-llvm::Expected<std::vector<std::unique_ptr<AnalysisBase>>>
-AnalysisDriver::toposort(llvm::ArrayRef<AnalysisName> Roots) {
- struct Visitor {
- enum class State { Unvisited, Visiting, Visited };
-
- std::map<AnalysisName, State> Marks;
- std::vector<AnalysisName> Path;
- std::vector<std::unique_ptr<AnalysisBase>> Result;
-
- explicit Visitor(size_t N) {
- Path.reserve(N);
- Result.reserve(N);
- }
-
- std::string formatCycle(const AnalysisName &CycleEntry) const {
- auto CycleBegin = llvm::find(Path, CycleEntry);
- std::string Cycle;
- llvm::raw_string_ostream OS(Cycle);
- llvm::interleave(llvm::make_range(CycleBegin, Path.end()), OS, " -> ");
- OS << " -> " << CycleEntry;
- return Cycle;
- }
-
- llvm::Error visit(const AnalysisName &Name) {
- auto [It, _] = Marks.emplace(Name, State::Unvisited);
-
- switch (It->second) {
- case State::Visited:
- return llvm::Error::success();
-
- case State::Visiting:
- return ErrorBuilder::create(std::errc::invalid_argument,
- "cycle detected: {0}", formatCycle(Name))
- .build();
-
- case State::Unvisited: {
- It->second = State::Visiting;
- Path.push_back(Name);
-
- llvm::Expected<std::unique_ptr<AnalysisBase>> V =
- AnalysisRegistry::instantiate(Name);
- if (!V) {
- return V.takeError();
- }
-
- // Unwrap for convenience to avoid the noise of dereferencing an
- // Expected on every subsequent access.
- std::unique_ptr<AnalysisBase> Analysis = std::move(*V);
-
- for (const auto &Dep : Analysis->getDependencyNames()) {
- if (auto Err = visit(Dep)) {
- return Err;
- }
- }
-
- // std::map iterators are not invalidated by insertions, so It remains
- // valid after recursive visit() calls that insert new entries.
- It->second = State::Visited;
- Path.pop_back();
- Result.push_back(std::move(Analysis));
-
- return llvm::Error::success();
- }
- }
- llvm_unreachable("unhandled State");
- }
- };
-
- Visitor V(Roots.size());
- for (const auto &Root : Roots) {
- if (auto Err = V.visit(Root)) {
- return std::move(Err);
- }
- }
- return std::move(V.Result);
-}
-
-llvm::Error AnalysisDriver::executeSummaryAnalysis(SummaryAnalysisBase &Summary,
- WPASuite &Suite) const {
- SummaryName SN = Summary.getSummaryName();
- auto DataIt = LU->Data.find(SN);
- if (DataIt == LU->Data.end()) {
- return ErrorBuilder::create(std::errc::invalid_argument,
- "no data for analysis '{0}' in LUSummary",
- Summary.getAnalysisName())
- .build();
- }
-
- if (auto Err = Summary.initialize()) {
- return Err;
- }
-
- for (auto &[Id, EntitySummary] : DataIt->second) {
- if (auto Err = Summary.add(Id, *EntitySummary)) {
- return Err;
- }
- }
-
- if (auto Err = Summary.finalize()) {
- return Err;
- }
-
- return llvm::Error::success();
-}
-
-llvm::Error AnalysisDriver::executeDerivedAnalysis(DerivedAnalysisBase &Derived,
- WPASuite &Suite) const {
- std::map<AnalysisName, const AnalysisResult *> DepMap;
-
- for (const auto &DepName : Derived.getDependencyNames()) {
- auto It = Suite.Data.find(DepName);
- if (It == Suite.Data.end()) {
- ErrorBuilder::fatal("missing dependency '{0}' for analysis '{1}': "
- "dependency graph is not topologically sorted",
- DepName, Derived.getAnalysisName());
- }
- DepMap[DepName] = It->second.get();
- }
-
- if (auto Err = Derived.initialize(DepMap)) {
- return Err;
- }
-
- while (true) {
- auto StepOrErr = Derived.step();
- if (!StepOrErr) {
- return StepOrErr.takeError();
- }
- if (!*StepOrErr) {
- break;
- }
- }
-
- if (auto Err = Derived.finalize()) {
- return Err;
- }
-
- return llvm::Error::success();
-}
-
-llvm::Expected<WPASuite> AnalysisDriver::execute(
- EntityIdTable IdTable,
- llvm::ArrayRef<std::unique_ptr<AnalysisBase>> Sorted) const {
- WPASuite Suite;
- Suite.IdTable = std::move(IdTable);
-
- for (auto &Analysis : Sorted) {
- switch (Analysis->TheKind) {
- case AnalysisBase::Kind::Summary: {
- SummaryAnalysisBase &SA = static_cast<SummaryAnalysisBase &>(*Analysis);
- if (auto Err = executeSummaryAnalysis(SA, Suite)) {
- return std::move(Err);
- }
- break;
- }
- case AnalysisBase::Kind::Derived: {
- DerivedAnalysisBase &DA = static_cast<DerivedAnalysisBase &>(*Analysis);
- if (auto Err = executeDerivedAnalysis(DA, Suite)) {
- return std::move(Err);
- }
- break;
- }
- }
- AnalysisName Name = Analysis->getAnalysisName();
- Suite.Data.emplace(std::move(Name), std::move(*Analysis).takeResult());
- }
-
- return std::move(Suite);
-}
-
-llvm::Expected<WPASuite> AnalysisDriver::run() && {
- auto ExpectedSorted = toposort(AnalysisRegistry::names());
- if (!ExpectedSorted) {
- return ExpectedSorted.takeError();
- }
- return execute(std::move(LU->IdTable), *ExpectedSorted);
-}
-
-llvm::Expected<WPASuite>
-AnalysisDriver::run(llvm::ArrayRef<AnalysisName> Names) const {
- auto ExpectedSorted = toposort(Names);
- if (!ExpectedSorted) {
- return ExpectedSorted.takeError();
- }
-
- return execute(LU->IdTable, *ExpectedSorted);
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.cpp
deleted file mode 100644
index 9719196ed4d6d..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-//===- AnalysisName.cpp ---------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-
-using namespace clang::ssaf;
-
-llvm::raw_ostream &clang::ssaf::operator<<(llvm::raw_ostream &OS,
- const AnalysisName &AN) {
- return OS << "AnalysisName(" << AN.str() << ")";
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
deleted file mode 100644
index 55b4f36a1764f..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//===- AnalysisRegistry.cpp -----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "llvm/ADT/STLExtras.h"
-
-using namespace clang;
-using namespace ssaf;
-
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int AnalysisRegistryAnchorSource = 0;
-} // namespace clang::ssaf
-
-LLVM_DEFINE_REGISTRY(llvm::Registry<AnalysisBase>)
-
-std::vector<AnalysisName> &AnalysisRegistry::getAnalysisNames() {
- static std::vector<AnalysisName> Names;
- return Names;
-}
-
-bool AnalysisRegistry::contains(const AnalysisName &Name) {
- return llvm::is_contained(getAnalysisNames(), Name);
-}
-
-const std::vector<AnalysisName> &AnalysisRegistry::names() {
- return getAnalysisNames();
-}
-
-llvm::Expected<std::unique_ptr<AnalysisBase>>
-AnalysisRegistry::instantiate(const AnalysisName &Name) {
- for (const auto &Entry : llvm::Registry<AnalysisBase>::entries()) {
- if (Entry.getName() == Name.str()) {
- return std::unique_ptr<AnalysisBase>(Entry.instantiate());
- }
- }
- return ErrorBuilder::create(std::errc::invalid_argument,
- "no analysis registered for '{0}'", Name)
- .build();
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
deleted file mode 100644
index dd799a9db90c8..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Frontend/CMakeLists.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Support
- TargetParser
- )
-
-add_clang_library(clangScalableStaticAnalysisFrameworkFrontend
- TUSummaryExtractorFrontendAction.cpp
-
- LINK_LIBS
- clangAST
- clangBasic
- clangFrontend
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangSema
- )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp b/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp
deleted file mode 100644
index 4f290ccac3d16..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.cpp
+++ /dev/null
@@ -1,199 +0,0 @@
-//===- TUSummaryExtractorFrontendAction.cpp -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/Basic/DiagnosticFrontend.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Frontend/MultiplexConsumer.h"
-#include "clang/Frontend/SSAFOptions.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/IOSandbox.h"
-#include "llvm/Support/Path.h"
-#include "llvm/TargetParser/Triple.h"
-#include <memory>
-#include <string>
-#include <vector>
-
-using namespace clang;
-using namespace ssaf;
-
-static std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
-parseOutputFileFormatAndPathOrReportError(DiagnosticsEngine &Diags,
- StringRef SSAFTUSummaryFile) {
-
- StringRef Ext = llvm::sys::path::extension(SSAFTUSummaryFile);
- StringRef FilePath = SSAFTUSummaryFile.drop_back(Ext.size());
-
- if (!Ext.consume_front(".") || FilePath.empty()) {
- Diags.Report(diag::warn_ssaf_extract_tu_summary_file_unknown_format)
- << SSAFTUSummaryFile;
- return std::nullopt;
- }
-
- if (!isFormatRegistered(Ext)) {
- Diags.Report(diag::warn_ssaf_extract_tu_summary_file_unknown_output_format)
- << Ext << SSAFTUSummaryFile;
- return std::nullopt;
- }
-
- return std::pair{Ext, FilePath};
-}
-
-/// Return \c true if reported unrecognized extractors.
-static bool
-reportUnrecognizedExtractorNames(DiagnosticsEngine &Diags,
- ArrayRef<std::string> SSAFExtractSummaries) {
- if (SSAFExtractSummaries.empty()) {
- Diags.Report(diag::warn_ssaf_must_enable_summary_extractors);
- return true;
- }
-
- std::vector<StringRef> UnrecognizedExtractorNames;
- for (StringRef Name : SSAFExtractSummaries)
- if (!isTUSummaryExtractorRegistered(Name))
- UnrecognizedExtractorNames.push_back(Name);
-
- if (!UnrecognizedExtractorNames.empty()) {
- Diags.Report(diag::warn_ssaf_extract_summary_unknown_extractor_name)
- << UnrecognizedExtractorNames.size()
- << llvm::join(UnrecognizedExtractorNames, ", ");
- return true;
- }
-
- return false;
-}
-
-static std::vector<std::unique_ptr<ASTConsumer>>
-makeTUSummaryExtractors(TUSummaryBuilder &Builder,
- ArrayRef<std::string> SSAFExtractSummaries) {
- std::vector<std::unique_ptr<ASTConsumer>> Extractors;
- Extractors.reserve(SSAFExtractSummaries.size());
- for (StringRef Name : SSAFExtractSummaries) {
- assert(isTUSummaryExtractorRegistered(Name));
- Extractors.push_back(makeTUSummaryExtractor(Name, Builder));
- }
- return Extractors;
-}
-
-namespace {
-
-/// Drives all extractor \c ASTConsumers and serializes the completed
-/// \c TUSummary.
-///
-/// Derives from \c MultiplexConsumer so every \c ASTConsumer virtual method is
-/// automatically forwarded to each extractor.
-class TUSummaryRunner final : public MultiplexConsumer {
-public:
- static std::unique_ptr<TUSummaryRunner> create(CompilerInstance &CI);
-
-private:
- TUSummaryRunner(llvm::Triple TargetTriple,
- std::unique_ptr<SerializationFormat> Format,
- const SSAFOptions &Opts);
-
- void HandleTranslationUnit(ASTContext &Ctx) override;
-
- TUSummary Summary;
-
- /// Owned by the \c CompilerInstance.
- const SSAFOptions &Opts;
-
- TUSummaryBuilder Builder = TUSummaryBuilder(Summary, Opts);
- std::unique_ptr<SerializationFormat> Format;
-};
-} // namespace
-
-std::unique_ptr<TUSummaryRunner> TUSummaryRunner::create(CompilerInstance &CI) {
- const SSAFOptions &Opts = CI.getSSAFOpts();
- DiagnosticsEngine &Diags = CI.getDiagnostics();
-
- if (Opts.CompilationUnitId.empty()) {
- Diags.Report(diag::warn_ssaf_tu_summary_requires_compilation_unit_id);
- return nullptr;
- }
-
- auto MaybePair =
- parseOutputFileFormatAndPathOrReportError(Diags, Opts.TUSummaryFile);
- if (!MaybePair.has_value())
- return nullptr;
- auto [FormatName, OutputPath] = MaybePair.value();
-
- if (reportUnrecognizedExtractorNames(Diags, Opts.ExtractSummaries))
- return nullptr;
-
- return std::unique_ptr<TUSummaryRunner>{new TUSummaryRunner{
- CI.getTarget().getTriple(), makeFormat(FormatName), Opts}};
-}
-
-TUSummaryRunner::TUSummaryRunner(llvm::Triple TargetTriple,
- std::unique_ptr<SerializationFormat> Format,
- const SSAFOptions &Opts)
- : MultiplexConsumer(std::vector<std::unique_ptr<ASTConsumer>>{}),
- Summary(std::move(TargetTriple),
- BuildNamespace(BuildNamespaceKind::CompilationUnit,
- Opts.CompilationUnitId)),
- Opts(Opts), Format(std::move(Format)) {
- assert(this->Format);
- assert(!Opts.CompilationUnitId.empty());
-
- // Now the Summary and the builders are constructed, we can also construct the
- // extractors.
- auto Extractors = makeTUSummaryExtractors(Builder, Opts.ExtractSummaries);
- assert(!Extractors.empty());
-
- // We must initialize the Consumers here because our extractors need a
- // Builder that holds a reference to the TUSummary, which would be only
- // initialized after the MultiplexConsumer ctor. This is the only way we can
- // avoid the use of the TUSummary before it starts its lifetime.
- MultiplexConsumer::Consumers = std::move(Extractors);
-}
-
-void TUSummaryRunner::HandleTranslationUnit(ASTContext &Ctx) {
- // First, invoke the Summary Extractors.
- MultiplexConsumer::HandleTranslationUnit(Ctx);
-
- // FIXME(sandboxing): Remove this by adopting `llvm::vfs::OutputBackend`.
- llvm::sys::sandbox::ScopedSetting Guard = llvm::sys::sandbox::scopedDisable();
-
- // Then serialize the result.
- if (auto Err = Format->writeTUSummary(Summary, Opts.TUSummaryFile)) {
- Ctx.getDiagnostics().Report(diag::warn_ssaf_write_tu_summary_failed)
- << Opts.TUSummaryFile << llvm::toString(std::move(Err));
- }
-}
-
-TUSummaryExtractorFrontendAction::~TUSummaryExtractorFrontendAction() = default;
-
-TUSummaryExtractorFrontendAction::TUSummaryExtractorFrontendAction(
- std::unique_ptr<FrontendAction> WrappedAction)
- : WrapperFrontendAction(std::move(WrappedAction)) {}
-
-std::unique_ptr<ASTConsumer>
-TUSummaryExtractorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
- auto WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
- if (!WrappedConsumer)
- return nullptr;
-
- if (auto Runner = TUSummaryRunner::create(CI)) {
- CI.getCodeGenOpts().ClearASTBeforeBackend = false;
- std::vector<std::unique_ptr<ASTConsumer>> Consumers;
- Consumers.reserve(2);
- Consumers.push_back(std::move(WrappedConsumer));
- Consumers.push_back(std::move(Runner));
- return std::make_unique<MultiplexConsumer>(std::move(Consumers));
- }
- return WrappedConsumer;
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt
deleted file mode 100644
index b77ffc49c0f9f..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-if(CLANG_PLUGIN_SUPPORT AND LLVM_ENABLE_PLUGINS AND NOT WIN32)
- # Plugins must never bring LLVM or Clang libraries in statically.
- # clang-ssaf-analyzer already loads clangScalableStaticAnalysisFrameworkCore
- # and LLVM into the process; a second static copy would produce duplicate
- # llvm::Registry instances with separate global state, breaking registration.
- #
- # Instead: build each plugin as a MODULE with PLUGIN_TOOL pointing to the
- # tool that will load it, and pull only include paths (not link deps) from
- # the libraries whose headers are needed. All symbols are resolved from the
- # tool's address space when the plugin is loaded via --load.
- #
- # This plugin is intended to be linked with undefined references; this isn't
- # supported on PE-COFF.
- add_subdirectory(ExamplePlugin)
-endif()
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/AnalysisResults.h b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/AnalysisResults.h
deleted file mode 100644
index c8ae6a542b8f0..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/AnalysisResults.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//===- AnalysisResults.h - Shared analysis result types ---------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef EXAMPLE_PLUGIN_ANALYSIS_RESULTS_H
-#define EXAMPLE_PLUGIN_ANALYSIS_RESULTS_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include <string>
-#include <utility>
-#include <vector>
-
-namespace example_plugin {
-
-struct TagsAnalysisResult final : clang::ssaf::AnalysisResult {
- static clang::ssaf::AnalysisName analysisName() {
- return clang::ssaf::AnalysisName("TagsAnalysisResult");
- }
-
- std::vector<std::string> Tags;
-};
-
-struct PairsAnalysisResult final : clang::ssaf::AnalysisResult {
- static clang::ssaf::AnalysisName analysisName() {
- return clang::ssaf::AnalysisName("PairsAnalysisResult");
- }
-
- std::vector<std::pair<clang::ssaf::EntityId, int>> PairCounts;
-};
-
-} // namespace example_plugin
-
-#endif // EXAMPLE_PLUGIN_ANALYSIS_RESULTS_H
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt
deleted file mode 100644
index 06c8e2abc1bd4..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-# Do NOT set LLVM_LINK_COMPONENTS and clang_target_link_libraries here.
-#
-# Setting them would cause LLVM libraries to be linked statically into this
-# MODULE, producing a second copy of LLVM in the process alongside the copy
-# already loaded by the host tool. Let the dynamic loader resolve every SSAF and
-# LLVM symbol from the tool's address space at load time.
-
-add_llvm_library(SSAFExamplePlugin MODULE BUILDTREE_ONLY
- TagsAnalysis.cpp
- PairsAnalysis.cpp
- TagsPairsAnalysis.cpp
- PLUGIN_TOOL clang-ssaf-format
- )
-
-# Pull in SSAF and LLVM include paths without any static link dependency.
-target_include_directories(SSAFExamplePlugin PRIVATE
- $<TARGET_PROPERTY:clangScalableStaticAnalysisFrameworkCore,INTERFACE_INCLUDE_DIRECTORIES>
- )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/PairsAnalysis.cpp b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/PairsAnalysis.cpp
deleted file mode 100644
index 34923f4a15e6e..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/PairsAnalysis.cpp
+++ /dev/null
@@ -1,197 +0,0 @@
-//===- PairsAnalysis.cpp - Pairs analysis for ExamplePlugin ---------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "AnalysisResults.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/Registry.h"
-#include <memory>
-#include <utility>
-#include <vector>
-
-using namespace clang::ssaf;
-using namespace llvm;
-using example_plugin::PairsAnalysisResult;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// PairsEntitySummary
-//
-// Per-entity data: a list of (EntityId, EntityId) pairs. Stored in the LU
-// data section under summary_name "PairsEntitySummary". Serialized as:
-// { "pairs": [{"first": {...}, "second": {...}}, ...] }
-//===----------------------------------------------------------------------===//
-
-struct PairsEntitySummary final : EntitySummary {
- static SummaryName summaryName() { return SummaryName("PairsEntitySummary"); }
-
- SummaryName getSummaryName() const override {
- return SummaryName("PairsEntitySummary");
- }
-
- std::vector<std::pair<EntityId, EntityId>> Pairs;
-};
-
-json::Object serializePairsEntitySummary(const EntitySummary &ES,
- JSONFormat::EntityIdToJSONFn ToJSON) {
- const auto &S = static_cast<const PairsEntitySummary &>(ES);
- json::Array PairsArray;
- for (const auto &[First, Second] : S.Pairs) {
- PairsArray.push_back(json::Object{
- {"first", ToJSON(First)},
- {"second", ToJSON(Second)},
- });
- }
- return json::Object{{"pairs", std::move(PairsArray)}};
-}
-
-Expected<std::unique_ptr<EntitySummary>>
-deserializePairsEntitySummary(const json::Object &Obj, EntityIdTable &,
- JSONFormat::EntityIdFromJSONFn FromJSON) {
- auto Result = std::make_unique<PairsEntitySummary>();
- const json::Array *PairsArray = Obj.getArray("pairs");
- if (!PairsArray) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid field 'pairs'");
- }
- for (const auto &[Index, Value] : llvm::enumerate(*PairsArray)) {
- const json::Object *Pair = Value.getAsObject();
- if (!Pair) {
- return createStringError(
- inconvertibleErrorCode(),
- "pairs element at index %zu is not a JSON object", Index);
- }
- const json::Object *FirstObj = Pair->getObject("first");
- if (!FirstObj) {
- return createStringError(
- inconvertibleErrorCode(),
- "missing or invalid 'first' field at index '%zu'", Index);
- }
- const json::Object *SecondObj = Pair->getObject("second");
- if (!SecondObj) {
- return createStringError(
- inconvertibleErrorCode(),
- "missing or invalid 'second' field at index '%zu'", Index);
- }
- auto ExpectedFirst = FromJSON(*FirstObj);
- if (!ExpectedFirst) {
- return createStringError(inconvertibleErrorCode(),
- "invalid 'first' entity id at index '%zu': %s",
- Index,
- toString(ExpectedFirst.takeError()).c_str());
- }
- auto ExpectedSecond = FromJSON(*SecondObj);
- if (!ExpectedSecond) {
- return createStringError(inconvertibleErrorCode(),
- "invalid 'second' entity id at index '%zu': %s",
- Index,
- toString(ExpectedSecond.takeError()).c_str());
- }
- Result->Pairs.emplace_back(*ExpectedFirst, *ExpectedSecond);
- }
- return std::move(Result);
-}
-
-struct PairsEntitySummaryFormatInfo final : JSONFormat::FormatInfo {
- PairsEntitySummaryFormatInfo()
- : JSONFormat::FormatInfo(SummaryName("PairsEntitySummary"),
- serializePairsEntitySummary,
- deserializePairsEntitySummary) {}
-};
-
-llvm::Registry<JSONFormat::FormatInfo>::Add<PairsEntitySummaryFormatInfo>
- RegisterPairsEntitySummaryForJSON(
- "PairsEntitySummary", "JSON format info for PairsEntitySummary");
-
-//===----------------------------------------------------------------------===//
-// PairsAnalysisResult serialization
-//
-// Per-entity pair count. Serialized as:
-// { "pair_counts": [{"entity_id": {...}, "count": N}, ...] }
-//===----------------------------------------------------------------------===//
-
-json::Object serializePairsAnalysisResult(const PairsAnalysisResult &R,
- JSONFormat::EntityIdToJSONFn ToJSON) {
- json::Array Arr;
- for (const auto &[EI, Count] : R.PairCounts) {
- Arr.push_back(json::Object{{"entity_id", ToJSON(EI)}, {"count", Count}});
- }
- return json::Object{{"pair_counts", std::move(Arr)}};
-}
-
-Expected<std::unique_ptr<AnalysisResult>>
-deserializePairsAnalysisResult(const json::Object &Obj,
- JSONFormat::EntityIdFromJSONFn FromJSON) {
- const json::Array *Arr = Obj.getArray("pair_counts");
- if (!Arr) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid field 'pair_counts'");
- }
-
- auto R = std::make_unique<PairsAnalysisResult>();
- for (const auto &[Index, Val] : llvm::enumerate(*Arr)) {
- const json::Object *Entry = Val.getAsObject();
- if (!Entry) {
- return createStringError(
- inconvertibleErrorCode(),
- "pair_counts element at index %zu is not an object", Index);
- }
- const json::Object *EIObj = Entry->getObject("entity_id");
- if (!EIObj) {
- return createStringError(
- inconvertibleErrorCode(),
- "missing or invalid 'entity_id' field at index %zu", Index);
- }
- auto ExpectedEI = FromJSON(*EIObj);
- if (!ExpectedEI) {
- return ExpectedEI.takeError();
- }
-
- auto CountVal = Entry->getInteger("count");
- if (!CountVal) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid 'count' field at index %zu",
- Index);
- }
- R->PairCounts.emplace_back(*ExpectedEI, static_cast<int>(*CountVal));
- }
- return std::move(R);
-}
-
-JSONFormat::AnalysisResultRegistry::Add<PairsAnalysisResult>
- RegisterPairsResultForJSON(serializePairsAnalysisResult,
- deserializePairsAnalysisResult);
-
-//===----------------------------------------------------------------------===//
-// PairsAnalysis
-//
-// SummaryAnalysis that reads per-entity PairsEntitySummary data and counts
-// the number of pairs per entity, producing (EntityId, count) pairs.
-//===----------------------------------------------------------------------===//
-
-class PairsAnalysis final
- : public SummaryAnalysis<PairsAnalysisResult, PairsEntitySummary> {
-public:
- using ResultType = PairsAnalysisResult;
-
- llvm::Error add(EntityId Id, const PairsEntitySummary &S) override {
- getResult().PairCounts.emplace_back(Id, static_cast<int>(S.Pairs.size()));
- return llvm::Error::success();
- }
-};
-
-AnalysisRegistry::Add<PairsAnalysis>
- RegisterPairsAnalysis("Counts pairs per entity");
-
-} // namespace
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsAnalysis.cpp b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsAnalysis.cpp
deleted file mode 100644
index 630a14544d7b0..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsAnalysis.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-//===- TagsAnalysis.cpp - Tags analysis for ExamplePlugin -----------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "AnalysisResults.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/Registry.h"
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <vector>
-
-using namespace clang::ssaf;
-using namespace llvm;
-using example_plugin::TagsAnalysisResult;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// TagsEntitySummary
-//
-// Per-entity data: a list of string tags. Stored in the LU data section
-// under summary_name "TagsEntitySummary". Serialized as:
-// { "tags": ["tag1", "tag2", ...] }
-//===----------------------------------------------------------------------===//
-
-struct TagsEntitySummary final : EntitySummary {
- static SummaryName summaryName() { return SummaryName("TagsEntitySummary"); }
-
- SummaryName getSummaryName() const override {
- return SummaryName("TagsEntitySummary");
- }
-
- std::vector<std::string> Tags;
-};
-
-json::Object serializeTagsEntitySummary(const EntitySummary &ES,
- JSONFormat::EntityIdToJSONFn) {
- const auto &S = static_cast<const TagsEntitySummary &>(ES);
- json::Array TagsArray;
- TagsArray.reserve(S.Tags.size());
- llvm::append_range(TagsArray, S.Tags);
- return json::Object{{"tags", std::move(TagsArray)}};
-}
-
-Expected<std::unique_ptr<EntitySummary>>
-deserializeTagsEntitySummary(const json::Object &Obj, EntityIdTable &,
- JSONFormat::EntityIdFromJSONFn) {
- const json::Array *TagsArray = Obj.getArray("tags");
- if (!TagsArray) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid field 'tags'");
- }
-
- auto S = std::make_unique<TagsEntitySummary>();
- for (const auto &[Index, Val] : llvm::enumerate(*TagsArray)) {
- auto Str = Val.getAsString();
- if (!Str) {
- return createStringError(inconvertibleErrorCode(),
- "tags element at index %zu is not a string",
- Index);
- }
- S->Tags.push_back(Str->str());
- }
- return std::move(S);
-}
-
-struct TagsEntitySummaryFormatInfo final : JSONFormat::FormatInfo {
- TagsEntitySummaryFormatInfo()
- : JSONFormat::FormatInfo(SummaryName("TagsEntitySummary"),
- serializeTagsEntitySummary,
- deserializeTagsEntitySummary) {}
-};
-
-llvm::Registry<JSONFormat::FormatInfo>::Add<TagsEntitySummaryFormatInfo>
- RegisterTagsEntitySummaryForJSON("TagsEntitySummary",
- "JSON format info for TagsEntitySummary");
-
-//===----------------------------------------------------------------------===//
-// TagsAnalysisResult serialization
-//
-// Sorted, deduplicated list of all tags seen across entities. Serialized as:
-// { "tags": ["tag1", "tag2", ...] }
-//===----------------------------------------------------------------------===//
-
-json::Object serializeTagsAnalysisResult(const TagsAnalysisResult &R,
- JSONFormat::EntityIdToJSONFn) {
- json::Array TagsArray;
- TagsArray.reserve(R.Tags.size());
- llvm::append_range(TagsArray, R.Tags);
- return json::Object{{"tags", std::move(TagsArray)}};
-}
-
-Expected<std::unique_ptr<AnalysisResult>>
-deserializeTagsAnalysisResult(const json::Object &Obj,
- JSONFormat::EntityIdFromJSONFn) {
- const json::Array *TagsArray = Obj.getArray("tags");
- if (!TagsArray) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid field 'tags'");
- }
-
- auto R = std::make_unique<TagsAnalysisResult>();
- for (const auto &[Index, Val] : llvm::enumerate(*TagsArray)) {
- auto S = Val.getAsString();
- if (!S) {
- return createStringError(inconvertibleErrorCode(),
- "tags element at index %zu is not a string",
- Index);
- }
- R->Tags.push_back(S->str());
- }
- return std::move(R);
-}
-
-JSONFormat::AnalysisResultRegistry::Add<TagsAnalysisResult>
- RegisterTagsResultForJSON(serializeTagsAnalysisResult,
- deserializeTagsAnalysisResult);
-
-//===----------------------------------------------------------------------===//
-// TagsAnalysis
-//
-// SummaryAnalysis that reads per-entity TagsEntitySummary data and collects
-// all unique tags into a sorted, deduplicated flat list.
-//===----------------------------------------------------------------------===//
-
-class TagsAnalysis final
- : public SummaryAnalysis<TagsAnalysisResult, TagsEntitySummary> {
-public:
- using ResultType = TagsAnalysisResult;
-
- llvm::Error add(EntityId, const TagsEntitySummary &S) override {
- for (const auto &Tag : S.Tags) {
- getResult().Tags.push_back(Tag);
- }
- return llvm::Error::success();
- }
-
- llvm::Error finalize() override {
- auto &Tags = getResult().Tags;
- std::sort(Tags.begin(), Tags.end());
- Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
- return llvm::Error::success();
- }
-};
-
-AnalysisRegistry::Add<TagsAnalysis>
- RegisterTagsAnalysis("Collects unique tags across entities");
-
-} // namespace
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp b/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
deleted file mode 100644
index 14750de321824..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-//===- TagsPairsAnalysis.cpp - Derived analysis for ExamplePlugin ---------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "AnalysisResults.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/Registry.h"
-#include <memory>
-
-using namespace clang::ssaf;
-using namespace llvm;
-using example_plugin::PairsAnalysisResult;
-using example_plugin::TagsAnalysisResult;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// TagsPairsAnalysisResult
-//
-// Aggregate statistics derived from TagsAnalysisResult and
-// PairsAnalysisResult. Serialized as:
-// { "unique_tag_count": N, "entity_count": N,
-// "total_pair_count": N, "max_pairs_per_entity": N }
-//===----------------------------------------------------------------------===//
-
-struct TagsPairsAnalysisResult final : AnalysisResult {
- static AnalysisName analysisName() {
- return AnalysisName("TagsPairsAnalysisResult");
- }
-
- int UniqueTagCount = 0;
- int EntityCount = 0;
- int TotalPairCount = 0;
- int MaxPairsPerEntity = 0;
-};
-
-json::Object serializeTagsPairsAnalysisResult(const TagsPairsAnalysisResult &R,
- JSONFormat::EntityIdToJSONFn) {
- return json::Object{{"unique_tag_count", R.UniqueTagCount},
- {"entity_count", R.EntityCount},
- {"total_pair_count", R.TotalPairCount},
- {"max_pairs_per_entity", R.MaxPairsPerEntity}};
-}
-
-Expected<std::unique_ptr<AnalysisResult>>
-deserializeTagsPairsAnalysisResult(const json::Object &Obj,
- JSONFormat::EntityIdFromJSONFn) {
- auto R = std::make_unique<TagsPairsAnalysisResult>();
-
- auto UTC = Obj.getInteger("unique_tag_count");
- if (!UTC) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid 'unique_tag_count'");
- }
- R->UniqueTagCount = static_cast<int>(*UTC);
-
- auto EC = Obj.getInteger("entity_count");
- if (!EC) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid 'entity_count'");
- }
- R->EntityCount = static_cast<int>(*EC);
-
- auto TPC = Obj.getInteger("total_pair_count");
- if (!TPC) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid 'total_pair_count'");
- }
- R->TotalPairCount = static_cast<int>(*TPC);
-
- auto MPE = Obj.getInteger("max_pairs_per_entity");
- if (!MPE) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid 'max_pairs_per_entity'");
- }
- R->MaxPairsPerEntity = static_cast<int>(*MPE);
-
- return std::move(R);
-}
-
-JSONFormat::AnalysisResultRegistry::Add<TagsPairsAnalysisResult>
- RegisterSummaryResultForJSON(serializeTagsPairsAnalysisResult,
- deserializeTagsPairsAnalysisResult);
-
-//===----------------------------------------------------------------------===//
-// TagsPairsAnalysis
-//
-// DerivedAnalysis that depends on TagsAnalysisResult and PairsAnalysisResult.
-// Computes aggregate statistics:
-// - unique_tag_count: number of distinct tags
-// - entity_count: number of entities with pair data
-// - total_pair_count: sum of all per-entity pair counts
-// - max_pairs_per_entity: maximum pairs on any single entity
-//===----------------------------------------------------------------------===//
-
-class TagsPairsAnalysis final
- : public DerivedAnalysis<TagsPairsAnalysisResult, TagsAnalysisResult,
- PairsAnalysisResult> {
-public:
- using ResultType = TagsPairsAnalysisResult;
-
- llvm::Error initialize(const TagsAnalysisResult &Tags,
- const PairsAnalysisResult &Pairs) override {
- getResult().UniqueTagCount = static_cast<int>(Tags.Tags.size());
- getResult().EntityCount = static_cast<int>(Pairs.PairCounts.size());
-
- int Total = 0;
- int Max = 0;
- for (const auto &[Id, Count] : Pairs.PairCounts) {
- Total += Count;
- if (Count > Max)
- Max = Count;
- }
- getResult().TotalPairCount = Total;
- getResult().MaxPairsPerEntity = Max;
-
- return llvm::Error::success();
- }
-
- llvm::Expected<bool> step() override {
- return false; // converged in initialize
- }
-};
-
-AnalysisRegistry::Add<TagsPairsAnalysis>
- RegisterTagsPairsAnalysis("Aggregate tag and pair statistics");
-
-} // namespace
diff --git a/clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/CMakeLists.txt
deleted file mode 100644
index c96a386977487..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/CMakeLists.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Support
- )
-
-add_clang_library(clangScalableStaticAnalysisFrameworkSourceTransformation
- TransformationRegistry.cpp
-
- LINK_LIBS
- clangAST
- clangBasic
- clangScalableStaticAnalysisFrameworkCore
- clangToolingCore
- )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/TransformationRegistry.cpp b/clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/TransformationRegistry.cpp
deleted file mode 100644
index 9d770c8bcd0f9..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/TransformationRegistry.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- TransformationRegistry.cpp -----------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationRegistry.h"
-#include <memory>
-
-using namespace clang;
-using namespace ssaf;
-
-namespace clang::ssaf {
-// NOLINTNEXTLINE(misc-use-internal-linkage)
-volatile int SSAFSourceTransformationAnchorSource = 0;
-} // namespace clang::ssaf
-
-LLVM_DEFINE_REGISTRY(clang::ssaf::TransformationRegistry)
-
-bool ssaf::isTransformationRegistered(llvm::StringRef Name) {
- for (const auto &Entry : TransformationRegistry::entries())
- if (Entry.getName() == Name)
- return true;
- return false;
-}
-
-std::unique_ptr<Transformation>
-ssaf::makeTransformation(llvm::StringRef Name, const WPASuite &Suite,
- SourceEditEmitter &Edits,
- TransformationReportEmitter &Report) {
- for (const auto &Entry : TransformationRegistry::entries())
- if (Entry.getName() == Name)
- return Entry.instantiate(Suite, Edits, Report);
- assert(false && "Unknown Transformation name");
- return nullptr;
-}
-
-void ssaf::printAvailableTransformations(llvm::raw_ostream &OS) {
- OS << "OVERVIEW: Available SSAF source transformations:\n\n";
- for (const auto &Entry : TransformationRegistry::entries())
- OS << " " << Entry.getName() << " - " << Entry.getDesc() << "\n";
-}
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
deleted file mode 100644
index edbe20e84c05d..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Tool/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-set(LLVM_LINK_COMPONENTS
- Support
- TargetParser
- )
-
-add_clang_library(clangScalableStaticAnalysisFrameworkTool
- Utils.cpp
-
- LINK_LIBS
- clangBasic
- clangScalableStaticAnalysisFrameworkCore
- )
diff --git a/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp b/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
deleted file mode 100644
index f14f34eb3bbb0..0000000000000
--- a/clang/lib/ScalableStaticAnalysisFramework/Tool/Utils.cpp
+++ /dev/null
@@ -1,207 +0,0 @@
-//===- Utils.cpp - Shared utilities for SSAF tools ------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/DynamicLibrary.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/WithColor.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <memory>
-#include <string>
-
-using namespace clang::ssaf;
-
-namespace fs = llvm::sys::fs;
-namespace path = llvm::sys::path;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// Error Messages
-//===----------------------------------------------------------------------===//
-
-namespace ErrorMessages {
-
-constexpr const char *CannotValidatePath = "failed to validate path '{0}': {1}";
-
-constexpr const char *ExtensionNotSupplied = "Extension not supplied";
-
-constexpr const char *NoFormatForExtension =
- "No format registered for extension '{0}'";
-
-constexpr const char *PathDoesNotExist = "Path does not exist";
-
-constexpr const char *PathIsNotAFile = "Path is not a file";
-
-constexpr const char *OutputDirectoryMissing =
- "Parent directory does not exist";
-
-constexpr const char *OutputDirectoryNotWritable =
- "Parent directory is not writable";
-
-constexpr const char *FileAlreadyExists = "File already exists";
-
-constexpr const char *FailedToLoadPlugin = "failed to load plugin '{0}': {1}";
-
-} // namespace ErrorMessages
-
-llvm::StringRef ToolName;
-llvm::StringRef ToolVersion;
-
-void printVersion(llvm::raw_ostream &OS) {
- OS << ToolName << " " << ToolVersion << "\n";
-}
-
-// Returns the SerializationFormat registered for \p Extension, or nullptr if
-// none is registered. Results are cached for the lifetime of the process.
-// FIXME: This will be revisited after we add support for registering formats
-// with extensions.
-SerializationFormat *getFormatForExtension(llvm::StringRef Extension) {
- // This cache is not thread-safe. SSAF tools are single-threaded CLIs, so
- // concurrent calls to this function are not expected.
-
- // Realistically, we don't expect to encounter more than four registered
- // formats.
- static llvm::SmallVector<
- std::pair<std::string, std::unique_ptr<SerializationFormat>>, 4>
- ExtensionFormatList;
-
- // Most recently used format is most likely to be reused again.
- auto ReversedList = llvm::reverse(ExtensionFormatList);
- auto It = llvm::find_if(ReversedList, [&](const auto &Entry) {
- return Entry.first == Extension;
- });
- if (It != ReversedList.end()) {
- return It->second.get();
- }
-
- if (!isFormatRegistered(Extension)) {
- return nullptr;
- }
-
- auto Format = makeFormat(Extension);
- SerializationFormat *Result = Format.get();
- assert(Result &&
- "makeFormat must return non-null for a registered extension");
-
- ExtensionFormatList.emplace_back(Extension, std::move(Format));
-
- return Result;
-}
-
-FormatFile fromPath(llvm::StringRef Path) {
- llvm::StringRef Extension = path::extension(Path);
- if (Extension.empty()) {
- fail(ErrorMessages::CannotValidatePath, Path,
- ErrorMessages::ExtensionNotSupplied);
- }
-
- Extension = Extension.drop_front();
- SerializationFormat *Format = getFormatForExtension(Extension);
- if (!Format) {
- std::string BadExtension =
- llvm::formatv(ErrorMessages::NoFormatForExtension, Extension);
- fail(ErrorMessages::CannotValidatePath, Path, BadExtension);
- }
-
- return {Path.str(), Format};
-}
-
-} // namespace
-
-llvm::StringRef clang::ssaf::getToolName() { return ToolName; }
-
-[[noreturn]] void clang::ssaf::fail(const char *Msg) {
- llvm::WithColor::error(llvm::errs(), ToolName) << Msg << "\n";
- llvm::sys::Process::Exit(1);
-}
-
-[[noreturn]] void clang::ssaf::fail(llvm::Error Err) {
- std::string Message = llvm::toString(std::move(Err));
- clang::ssaf::fail(Message.data());
-}
-
-void clang::ssaf::loadPlugins(llvm::ArrayRef<std::string> Paths) {
- for (const std::string &PluginPath : Paths) {
- if (!fs::exists(PluginPath)) {
- fail(ErrorMessages::FailedToLoadPlugin, PluginPath,
- ErrorMessages::PathDoesNotExist);
- }
- std::string ErrMsg;
- if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(PluginPath.c_str(),
- &ErrMsg)) {
- fail(ErrorMessages::FailedToLoadPlugin, PluginPath, ErrMsg);
- }
- }
-}
-
-void clang::ssaf::initTool(int argc, const char **argv, llvm::StringRef Version,
- llvm::cl::OptionCategory &Category,
- llvm::StringRef ToolHeading) {
- // path::stem strips the .exe extension on Windows so ToolName is consistent.
- ToolName = path::stem(argv[0]);
-
- // Set tool version for the version printer.
- ToolVersion = Version;
-
- // Hide options unrelated to the tool from --help output.
- llvm::cl::HideUnrelatedOptions(Category);
-
- // Register a custom version printer for the --version flag.
- llvm::cl::SetVersionPrinter(printVersion);
-
- // Parse command-line arguments and exit with an error if they are invalid.
- std::string Overview = (ToolHeading + "\n").str();
- llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
-}
-
-clang::ssaf::FormatFile
-clang::ssaf::FormatFile::fromInputPath(llvm::StringRef Path) {
- if (!fs::exists(Path)) {
- fail(ErrorMessages::CannotValidatePath, Path,
- ErrorMessages::PathDoesNotExist);
- }
-
- if (!fs::is_regular_file(Path)) {
- fail(ErrorMessages::CannotValidatePath, Path,
- ErrorMessages::PathIsNotAFile);
- }
-
- return fromPath(Path);
-}
-
-clang::ssaf::FormatFile
-clang::ssaf::FormatFile::fromOutputPath(llvm::StringRef Path) {
- if (fs::exists(Path)) {
- fail(ErrorMessages::CannotValidatePath, Path,
- ErrorMessages::FileAlreadyExists);
- }
-
- llvm::StringRef ParentDir = path::parent_path(Path);
- llvm::StringRef DirToCheck = ParentDir.empty() ? "." : ParentDir;
-
- if (!fs::exists(DirToCheck)) {
- fail(ErrorMessages::CannotValidatePath, Path,
- ErrorMessages::OutputDirectoryMissing);
- }
-
- if (fs::access(DirToCheck, fs::AccessMode::Write)) {
- fail(ErrorMessages::CannotValidatePath, Path,
- ErrorMessages::OutputDirectoryNotWritable);
- }
-
- return fromPath(Path);
-}
diff --git a/clang/tools/clang-ssaf-analyzer/CMakeLists.txt b/clang/tools/clang-ssaf-analyzer/CMakeLists.txt
index 830db2c4d1657..f1455e105b226 100644
--- a/clang/tools/clang-ssaf-analyzer/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-analyzer/CMakeLists.txt
@@ -16,10 +16,10 @@ add_clang_tool(clang-ssaf-analyzer
clang_target_link_libraries(clang-ssaf-analyzer
PRIVATE
clangBasic
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkSourceTransformation
- clangScalableStaticAnalysisFrameworkTool
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisSourceTransformation
+ clangScalableStaticAnalysisTool
)
if(CLANG_PLUGIN_SUPPORT)
diff --git a/clang/tools/clang-ssaf-analyzer/SSAFAnalyzer.cpp b/clang/tools/clang-ssaf-analyzer/SSAFAnalyzer.cpp
index 14f037beb60c1..9595347808dba 100644
--- a/clang/tools/clang-ssaf-analyzer/SSAFAnalyzer.cpp
+++ b/clang/tools/clang-ssaf-analyzer/SSAFAnalyzer.cpp
@@ -12,11 +12,11 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
-#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/InitLLVM.h"
diff --git a/clang/tools/clang-ssaf-format/CMakeLists.txt b/clang/tools/clang-ssaf-format/CMakeLists.txt
index 8416dd1d88023..6051a8c8ba307 100644
--- a/clang/tools/clang-ssaf-format/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-format/CMakeLists.txt
@@ -16,10 +16,10 @@ add_clang_tool(clang-ssaf-format
clang_target_link_libraries(clang-ssaf-format
PRIVATE
clangBasic
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkSourceTransformation
- clangScalableStaticAnalysisFrameworkTool
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisSourceTransformation
+ clangScalableStaticAnalysisTool
)
if(CLANG_PLUGIN_SUPPORT)
diff --git a/clang/tools/clang-ssaf-format/SSAFFormat.cpp b/clang/tools/clang-ssaf-format/SSAFFormat.cpp
index c1762c0fa3297..9416b45c974b5 100644
--- a/clang/tools/clang-ssaf-format/SSAFFormat.cpp
+++ b/clang/tools/clang-ssaf-format/SSAFFormat.cpp
@@ -11,12 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
-#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
diff --git a/clang/tools/clang-ssaf-linker/CMakeLists.txt b/clang/tools/clang-ssaf-linker/CMakeLists.txt
index 576daab0c9355..a4d371d908373 100644
--- a/clang/tools/clang-ssaf-linker/CMakeLists.txt
+++ b/clang/tools/clang-ssaf-linker/CMakeLists.txt
@@ -11,8 +11,8 @@ add_clang_tool(clang-ssaf-linker
clang_target_link_libraries(clang-ssaf-linker
PRIVATE
clangBasic
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkSourceTransformation
- clangScalableStaticAnalysisFrameworkTool
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisSourceTransformation
+ clangScalableStaticAnalysisTool
)
diff --git a/clang/tools/clang-ssaf-linker/SSAFLinker.cpp b/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
index 1a620dedcbd2d..a8bf6c97a37b8 100644
--- a/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
+++ b/clang/tools/clang-ssaf-linker/SSAFLinker.cpp
@@ -11,12 +11,12 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h" // IWYU pragma: keep
-#include "clang/ScalableStaticAnalysisFramework/Tool/Utils.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
+#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/CommandLine.h"
diff --git a/clang/unittests/CMakeLists.txt b/clang/unittests/CMakeLists.txt
index 71c7a6842fed2..937ad0dc80556 100644
--- a/clang/unittests/CMakeLists.txt
+++ b/clang/unittests/CMakeLists.txt
@@ -91,7 +91,7 @@ add_subdirectory(Tooling)
add_subdirectory(Format)
add_subdirectory(Frontend)
add_subdirectory(Rewrite)
-add_subdirectory(ScalableStaticAnalysisFramework)
+add_subdirectory(ScalableStaticAnalysis)
add_subdirectory(Sema)
add_subdirectory(CodeGen)
if(HAVE_CLANG_REPL_SUPPORT)
@@ -99,7 +99,7 @@ if(HAVE_CLANG_REPL_SUPPORT)
endif()
# FIXME: libclang unit tests are disabled on Windows due
# to failures, mostly in libclang.VirtualFileOverlay_*.
-if(NOT WIN32 AND CLANG_TOOL_LIBCLANG_BUILD)
+if(NOT WIN32 AND CLANG_TOOL_LIBCLANG_BUILD)
add_subdirectory(libclang)
endif()
add_subdirectory(DirectoryWatcher)
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp b/clang/unittests/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendActionTest.cpp
similarity index 95%
rename from clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
rename to clang/unittests/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendActionTest.cpp
index cb5448e4860bc..2d65fb675eec3 100644
--- a/clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp
+++ b/clang/unittests/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendActionTest.cpp
@@ -6,7 +6,7 @@
//
//===----------------------------------------------------------------------===//
-#include "clang/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendAction.h"
+#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/Frontend/CompilerInstance.h"
@@ -14,10 +14,10 @@
#include "clang/Frontend/SSAFOptions.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Lex/PreprocessorOptions.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
@@ -483,16 +483,14 @@ TEST_F(TUSummaryExtractorFrontendActionTest,
EXPECT_THAT(Log, Contains("Wrapped::Initialize"));
EXPECT_THAT(Log, Contains("Wrapped::HandleTranslationUnit"));
- EXPECT_THAT(
- errorsMsgsOf(DiagBuf),
- UnorderedElementsAre("option '--ssaf-tu-summary-file=' requires "
- "'--ssaf-compilation-unit-id=' to be set"));
+ EXPECT_THAT(errorsMsgsOf(DiagBuf),
+ UnorderedElementsAre("option '--ssaf-tu-summary-file=' requires "
+ "'--ssaf-compilation-unit-id=' to be set"));
EXPECT_FALSE(llvm::sys::fs::exists(Output));
}
-TEST_F(TUSummaryExtractorFrontendActionTest,
- EmptyCompilationUnitIdDiagnoses) {
+TEST_F(TUSummaryExtractorFrontendActionTest, EmptyCompilationUnitIdDiagnoses) {
std::string Output = makePath("output.MockSerializationFormat");
Compiler->getSSAFOpts().TUSummaryFile = Output;
Compiler->getSSAFOpts().ExtractSummaries = {"NoOpExtractor"};
@@ -507,10 +505,9 @@ TEST_F(TUSummaryExtractorFrontendActionTest,
EXPECT_THAT(Log, Contains("Wrapped::Initialize"));
EXPECT_THAT(Log, Contains("Wrapped::HandleTranslationUnit"));
- EXPECT_THAT(
- errorsMsgsOf(DiagBuf),
- UnorderedElementsAre("option '--ssaf-tu-summary-file=' requires "
- "'--ssaf-compilation-unit-id=' to be set"));
+ EXPECT_THAT(errorsMsgsOf(DiagBuf),
+ UnorderedElementsAre("option '--ssaf-tu-summary-file=' requires "
+ "'--ssaf-compilation-unit-id=' to be set"));
EXPECT_FALSE(llvm::sys::fs::exists(Output));
}
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.cpp
deleted file mode 100644
index 9d79647f841c8..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/ASTEntityMappingTest.cpp
+++ /dev/null
@@ -1,341 +0,0 @@
-//===- ASTEntityMappingTest.cpp -------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "FindDecl.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Tooling/Tooling.h"
-#include "gtest/gtest.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang::ssaf {
-namespace {
-
-TEST(ASTEntityMappingTest, FunctionDecl) {
- auto AST = tooling::buildASTFromCode(R"cpp(void foo() {})cpp");
- auto &Ctx = AST->getASTContext();
-
- const auto *FD = findFnByName("foo", Ctx);
- ASSERT_NE(FD, nullptr);
-
- auto EntityName = getEntityName(FD);
- EXPECT_TRUE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, VarDecl) {
- auto AST = tooling::buildASTFromCode(R"cpp(int x = 42;)cpp");
- auto &Ctx = AST->getASTContext();
-
- const auto *VD = findDeclByName<VarDecl>("x", Ctx);
- ASSERT_NE(VD, nullptr);
-
- auto EntityName = getEntityName(VD);
- EXPECT_TRUE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, ParmVarDecl) {
- auto AST = tooling::buildASTFromCode(R"cpp(void foo(int x) {})cpp");
- auto &Ctx = AST->getASTContext();
-
- const auto *FD = findFnByName("foo", Ctx);
- ASSERT_NE(FD, nullptr);
- ASSERT_EQ(FD->param_size(), 1u);
-
- const auto *PVD = FD->getParamDecl(0);
- ASSERT_NE(PVD, nullptr);
-
- auto EntityName = getEntityName(PVD);
- EXPECT_TRUE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, RecordDecl) {
- auto AST = tooling::buildASTFromCode(R"cpp(struct S {};)cpp");
- auto &Ctx = AST->getASTContext();
-
- const auto *RD = findDeclByName<RecordDecl>("S", Ctx);
- ASSERT_NE(RD, nullptr);
-
- auto EntityName = getEntityName(RD);
- EXPECT_TRUE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, FieldDecl) {
- auto AST = tooling::buildASTFromCode(R"cpp(struct S { int field; };)cpp");
- auto &Ctx = AST->getASTContext();
-
- const auto *FD = findDeclByName<FieldDecl>("field", Ctx);
- ASSERT_NE(FD, nullptr);
-
- auto EntityName = getEntityName(FD);
- EXPECT_TRUE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, NullDecl) {
- auto EntityName = getEntityName(nullptr);
- EXPECT_FALSE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, ImplicitDeclLambda) {
- auto AST = tooling::buildASTFromCode(
- R"cpp(
- auto L = [](){};
- )cpp",
- "test.cpp", std::make_shared<PCHContainerOperations>());
- auto &Ctx = AST->getASTContext();
-
- auto Matcher = cxxRecordDecl(isImplicit()).bind("decl");
- auto Matches = match(Matcher, Ctx);
- ASSERT_GT(Matches.size(), 0u);
-
- const auto *ImplCXXRD = Matches[0].getNodeAs<CXXRecordDecl>("decl");
- ASSERT_NE(ImplCXXRD, nullptr);
-
- auto EntityName = getEntityName(ImplCXXRD);
- EXPECT_FALSE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, BuiltinFunction) {
- auto AST = tooling::buildASTFromCode(R"cpp(
- void test() {
- __builtin_memcpy(0, 0, 0);
- }
- )cpp");
- auto &Ctx = AST->getASTContext();
-
- // Find the builtin call
- auto Matcher = callExpr().bind("call");
- auto Matches = match(Matcher, Ctx);
- ASSERT_EQ(Matches.size(), 1ul);
-
- const auto *CE = Matches[0].getNodeAs<CallExpr>("call");
- ASSERT_NE(CE, nullptr);
-
- const auto *Callee = CE->getDirectCallee();
- ASSERT_NE(Callee, nullptr);
- ASSERT_NE(Callee->getBuiltinID(), 0u /* not a built-in */);
-
- auto EntityName = getEntityName(Callee);
- EXPECT_FALSE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, UnsupportedDecl) {
- auto AST = tooling::buildASTFromCode(R"cpp(namespace N {})cpp");
- auto &Ctx = AST->getASTContext();
-
- const auto *ND = findDeclByName<NamespaceDecl>("N", Ctx);
- ASSERT_NE(ND, nullptr);
-
- auto EntityName = getEntityName(ND);
- EXPECT_FALSE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, FunctionReturn) {
- auto AST = tooling::buildASTFromCode(R"cpp(int foo() { return 42; })cpp");
- auto &Ctx = AST->getASTContext();
-
- const auto *FD = findFnByName("foo", Ctx);
- ASSERT_NE(FD, nullptr);
-
- auto EntityName = getEntityNameForReturn(FD);
- EXPECT_TRUE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, FunctionReturnNull) {
- auto EntityName = getEntityNameForReturn(nullptr);
- EXPECT_FALSE(EntityName.has_value());
-}
-
-TEST(ASTEntityMappingTest, FunctionReturnBuiltin) {
- auto AST = tooling::buildASTFromCode(R"cpp(
- void test() {
- __builtin_memcpy(0, 0, 0);
- }
- )cpp");
- auto &Ctx = AST->getASTContext();
-
- // Find the builtin call
- auto Matcher = callExpr().bind("call");
- auto Matches = match(Matcher, Ctx);
- ASSERT_FALSE(Matches.empty());
-
- const auto *CE = Matches[0].getNodeAs<CallExpr>("call");
- ASSERT_NE(CE, nullptr);
-
- const auto *Callee = CE->getDirectCallee();
- if (Callee && Callee->getBuiltinID()) {
- auto EntityName = getEntityNameForReturn(Callee);
- EXPECT_FALSE(EntityName.has_value());
- }
-}
-
-TEST(ASTEntityMappingTest, DifferentFunctionsDifferentNames) {
- auto AST = tooling::buildASTFromCode(R"cpp(
- void foo() {}
- void bar() {}
- )cpp");
- auto &Ctx = AST->getASTContext();
-
- const auto *Foo = findFnByName("foo", Ctx);
- const auto *Bar = findFnByName("bar", Ctx);
- ASSERT_NE(Foo, nullptr);
- ASSERT_NE(Bar, nullptr);
-
- auto FooName = getEntityName(Foo);
- auto BarName = getEntityName(Bar);
- ASSERT_TRUE(FooName.has_value());
- ASSERT_TRUE(BarName.has_value());
-
- EXPECT_NE(*FooName, *BarName);
-}
-
-// Redeclaration tests
-
-TEST(ASTEntityMappingTest, FunctionRedeclaration) {
- auto AST = tooling::buildASTFromCode(R"cpp(
- void foo();
- void foo() {}
- )cpp");
- auto &Ctx = AST->getASTContext();
-
- auto Matcher = functionDecl(hasName("foo")).bind("decl");
- auto Matches = match(Matcher, Ctx);
- ASSERT_GE(Matches.size(), 2u);
-
- const auto *FirstDecl = Matches[0].getNodeAs<FunctionDecl>("decl");
- ASSERT_NE(FirstDecl, nullptr);
-
- auto FirstName = getEntityName(FirstDecl);
- ASSERT_TRUE(FirstName.has_value());
-
- for (size_t I = 1; I < Matches.size(); ++I) {
- const auto *Decl = Matches[I].getNodeAs<FunctionDecl>("decl");
- ASSERT_NE(Decl, nullptr);
-
- auto Name = getEntityName(Decl);
- ASSERT_TRUE(Name.has_value());
- EXPECT_EQ(*FirstName, *Name);
- }
-}
-
-TEST(ASTEntityMappingTest, VarRedeclaration) {
- auto AST = tooling::buildASTFromCode(R"cpp(
- extern int x;
- int x = 42;
- )cpp");
- auto &Ctx = AST->getASTContext();
-
- auto Matcher = varDecl(hasName("x")).bind("decl");
- auto Matches = match(Matcher, Ctx);
- ASSERT_EQ(Matches.size(), 2u);
-
- const auto *FirstDecl = Matches[0].getNodeAs<VarDecl>("decl");
- ASSERT_NE(FirstDecl, nullptr);
-
- auto FirstName = getEntityName(FirstDecl);
- ASSERT_TRUE(FirstName.has_value());
-
- for (size_t I = 1; I < Matches.size(); ++I) {
- const auto *Decl = Matches[I].getNodeAs<VarDecl>("decl");
- ASSERT_NE(Decl, nullptr);
-
- auto Name = getEntityName(Decl);
- ASSERT_TRUE(Name.has_value());
- EXPECT_EQ(*FirstName, *Name);
- }
-}
-
-TEST(ASTEntityMappingTest, RecordRedeclaration) {
- auto AST = tooling::buildASTFromCode(R"cpp(
- struct S;
- struct S {};
- )cpp");
- auto &Ctx = AST->getASTContext();
-
- auto Matcher = recordDecl(hasName("S"), unless(isImplicit())).bind("decl");
- auto Matches = match(Matcher, Ctx);
- ASSERT_GE(Matches.size(), 2u);
-
- const auto *FirstDecl = Matches[0].getNodeAs<RecordDecl>("decl");
- ASSERT_NE(FirstDecl, nullptr);
-
- auto FirstName = getEntityName(FirstDecl);
- ASSERT_TRUE(FirstName.has_value());
-
- for (size_t I = 1; I < Matches.size(); ++I) {
- const auto *Decl = Matches[I].getNodeAs<RecordDecl>("decl");
- ASSERT_NE(Decl, nullptr);
-
- auto Name = getEntityName(Decl);
- ASSERT_TRUE(Name.has_value());
- EXPECT_EQ(*FirstName, *Name);
- }
-}
-
-TEST(ASTEntityMappingTest, ParmVarDeclRedeclaration) {
- auto AST = tooling::buildASTFromCode(R"cpp(
- void foo(int);
- void foo(int x);
- void foo(int y);
- void foo(int x) {}
- )cpp");
- auto &Ctx = AST->getASTContext();
-
- auto Matcher = functionDecl(hasName("foo")).bind("decl");
- auto Matches = match(Matcher, Ctx);
- ASSERT_GE(Matches.size(), 2u);
-
- const auto *FirstFuncDecl = Matches[0].getNodeAs<FunctionDecl>("decl");
- ASSERT_NE(FirstFuncDecl, nullptr);
- ASSERT_GT(FirstFuncDecl->param_size(), 0u);
-
- auto ParamEName = getEntityName(FirstFuncDecl->getParamDecl(0));
- ASSERT_TRUE(ParamEName.has_value());
-
- for (size_t I = 1; I < Matches.size(); ++I) {
- const auto *FDecl = Matches[I].getNodeAs<FunctionDecl>("decl");
- ASSERT_NE(FDecl, nullptr);
- ASSERT_GT(FDecl->param_size(), 0u);
-
- auto ParamRedeclEName = getEntityName(FDecl->getParamDecl(0));
- EXPECT_EQ(*ParamEName, *ParamRedeclEName);
- }
-}
-
-TEST(ASTEntityMappingTest, FunctionReturnRedeclaration) {
- auto AST = tooling::buildASTFromCode(R"cpp(
- int foo();
- int foo() { return 42; }
- )cpp");
- auto &Ctx = AST->getASTContext();
-
- auto Matcher = functionDecl(hasName("foo")).bind("decl");
- auto Matches = match(Matcher, Ctx);
- ASSERT_EQ(Matches.size(), 2u);
-
- const auto *Decl1 = Matches[0].getNodeAs<FunctionDecl>("decl");
- ASSERT_NE(Decl1, nullptr);
- auto Name1 = getEntityNameForReturn(Decl1);
- ASSERT_TRUE(Name1.has_value());
-
- for (size_t I = 1; I < Matches.size(); ++I) {
- const auto *FDecl = Matches[I].getNodeAs<FunctionDecl>("decl");
- ASSERT_NE(FDecl, nullptr);
-
- auto Name = getEntityNameForReturn(Decl1);
- ASSERT_TRUE(Name.has_value());
- EXPECT_EQ(*Name1, *Name);
- }
-}
-
-} // namespace
-} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
deleted file mode 100644
index 0a3685c4f1057..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphExtractorTest.cpp
+++ /dev/null
@@ -1,517 +0,0 @@
-//===- CallGraphExtractorTest.cpp -----------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "TestFixture.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include "clang/Frontend/SSAFOptions.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/CallGraph/CallGraphSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/ASTEntityMapping.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <cassert>
-
-using namespace clang;
-using namespace ssaf;
-
-namespace {
-AST_MATCHER(FunctionDecl, isPrimaryTemplate) {
- return Node.getDescribedFunctionTemplate() != nullptr;
-}
-} // namespace
-
-static llvm::Expected<const NamedDecl *> findDecl(ASTContext &Ctx,
- StringRef FnName) {
- using namespace ast_matchers;
- auto Matcher =
- functionDecl(hasName(FnName), unless(isPrimaryTemplate())).bind("decl");
- auto Matches = match(Matcher, Ctx);
- if (Matches.empty())
- return llvm::createStringError("No definition was found with name '" +
- FnName + "'");
- auto *ND = Matches[0].template getNodeAs<NamedDecl>("decl");
- assert(ND);
- return cast<NamedDecl>(ND->getCanonicalDecl());
-}
-
-// ============================================================================
-// PrintTo overload for readable failure messages.
-// Must live in the same namespace as Location (clang::ssaf) for ADL.
-// ============================================================================
-
-namespace clang::ssaf {
-void PrintTo(const CallGraphSummary::Location &Loc, std::ostream *OS) {
- *OS << Loc.File << ":" << Loc.Line << ":" << Loc.Column;
-}
-void PrintTo(const CallGraphSummary &S, std::ostream *OS) {
- *OS << "CallGraphSummary { PrettyName: '" << S.PrettyName << "'"
- << ", Definition: ";
- PrintTo(S.Definition, OS);
- *OS << ", DirectCallees: " << S.DirectCallees.size()
- << ", VirtualCallees: " << S.VirtualCallees.size() << " }";
-}
-} // namespace clang::ssaf
-
-namespace {
-
-MATCHER_P3(DefinedAt, File, Line, Column,
- std::string(negation ? "is not" : "is") + " defined at " +
- std::string(File) + ":" + testing::PrintToString(Line) + ":" +
- testing::PrintToString(Column)) {
- const auto &D = arg.Definition;
- if (D.File != File || D.Line != Line || D.Column != Column) {
- *result_listener << "defined at " << D.File << ":" << D.Line << ":"
- << D.Column;
- return false;
- }
- return true;
-}
-
-MATCHER_P(HasPrettyName, Name,
- std::string(negation ? "doesn't have" : "has") + " pretty name '" +
- testing::PrintToString(Name) + "'") {
- if (arg.PrettyName != std::string(Name)) {
- *result_listener << "has pretty name '" << arg.PrettyName << "'";
- return false;
- }
- return true;
-}
-
-MATCHER(HasNoDirectCallees,
- std::string(negation ? "has" : "has no") + " direct callees") {
- if (!arg.DirectCallees.empty()) {
- *result_listener << "has " << arg.DirectCallees.size()
- << " direct callee(s)";
- return false;
- }
- return true;
-}
-
-MATCHER(HasNoVirtualCallees,
- std::string(negation ? "has" : "has no") + " virtual callees") {
- if (!arg.VirtualCallees.empty()) {
- *result_listener << "has " << arg.VirtualCallees.size()
- << " virtual callee(s)";
- return false;
- }
- return true;
-}
-
-template <typename... Matchers> auto hasSummaryThat(const Matchers &...Ms) {
- using namespace testing;
- return llvm::HasValue(Pointee(AllOf(std::move(Ms)...)));
-}
-
-// ============================================================================
-// Test fixture
-// ============================================================================
-
-static const SummaryName CallGraphName{CallGraphSummary::Name.str()};
-
-struct CallGraphExtractorTest : ssaf::TestFixture {
- SSAFOptions Opts;
- TUSummary Summary{
- llvm::Triple("arm64-apple-macosx"),
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")};
- TUSummaryBuilder Builder = TUSummaryBuilder(Summary, Opts);
-
- /// Creates the AST and extractor, then extracts the summaries from the AST.
- /// This will update the \c AST \c Builder and \c Summary data members.
- void runExtractor(StringRef Code, ArrayRef<std::string> Args = {}) {
- AST = tooling::buildASTFromCodeWithArgs(Code, Args);
- auto Consumer = makeTUSummaryExtractor(CallGraphName.str(), Builder);
- Consumer->HandleTranslationUnit(AST->getASTContext());
- }
-
- /// Tries to find the \c CallGraphSummary for the \p FnName function.
- llvm::Expected<const CallGraphSummary *>
- findSummary(llvm::StringRef FnName) const;
-
- /// Matcher factory: matches a summary whose direct callees are exactly the
- /// given set of function names (resolved to USRs via the entity table).
- /// Uses \c testing::ResultOf to transform the summary's EntityId set into
- /// USR strings before comparing with \c testing::ContainerEq.
- auto hasDirectCallees(llvm::ArrayRef<StringRef> Names)
- -> testing::Matcher<const CallGraphSummary &> {
- auto MaybeUSRs = asUSRs(Names);
- if (!MaybeUSRs) {
- ADD_FAILURE() << "Failed to resolve callee names to USRs: "
- << llvm::toString(MaybeUSRs.takeError());
- return testing::An<const CallGraphSummary &>();
- }
- std::set<std::string> ExpectedUSRs = std::move(*MaybeUSRs);
- return testing::ResultOf(
- "direct callees",
- [this](const CallGraphSummary &S) {
- return getUSRsForCallees(S.DirectCallees);
- },
- testing::ContainerEq(ExpectedUSRs));
- }
-
- /// Matcher factory: same as \c hasDirectCallees but for virtual callees.
- auto hasVirtualCallees(llvm::ArrayRef<StringRef> Names)
- -> testing::Matcher<const CallGraphSummary &> {
- auto MaybeUSRs = asUSRs(Names);
- if (!MaybeUSRs) {
- ADD_FAILURE() << "Failed to resolve callee names to USRs: "
- << llvm::toString(MaybeUSRs.takeError());
- return testing::A<const CallGraphSummary &>();
- }
- std::set<std::string> ExpectedUSRs = std::move(*MaybeUSRs);
- return testing::ResultOf(
- "virtual callees",
- [this](const CallGraphSummary &S) {
- return getUSRsForCallees(S.VirtualCallees);
- },
- testing::ContainerEq(ExpectedUSRs));
- }
-
-private:
- std::unique_ptr<ASTUnit> AST;
-
- std::set<std::string>
- getUSRsForCallees(const std::set<EntityId> &Callees) const;
-
- /// Looks up the Decls for \p FnNames, and then transforms those into USRs.
- llvm::Expected<std::set<std::string>>
- asUSRs(llvm::ArrayRef<StringRef> FnNames);
-};
-
-llvm::Expected<const CallGraphSummary *>
-CallGraphExtractorTest::findSummary(llvm::StringRef FnName) const {
- auto MaybeDecl = findDecl(AST->getASTContext(), FnName);
- if (!MaybeDecl)
- return MaybeDecl.takeError();
-
- std::optional<EntityName> EntName = getEntityName(*MaybeDecl);
- if (!EntName.has_value()) {
- return llvm::createStringError("Failed to create an entity name for '" +
- FnName + "'");
- }
-
- const auto &EntitiesTable = getEntities(getIdTable(Summary));
- auto It = EntitiesTable.find(EntName.value());
- if (It == EntitiesTable.end()) {
- return llvm::createStringError(
- "No entity ID was present in the entity table for '" + FnName + "'");
- }
- EntityId ID = It->second;
- auto &Data = getData(Summary);
- auto SummaryIt = Data.find(CallGraphName);
- if (SummaryIt == Data.end())
- return llvm::createStringError("There is no 'CallGraph' summary");
- auto EntityIt = SummaryIt->second.find(ID);
- if (EntityIt == SummaryIt->second.end()) {
- return llvm::createStringError(
- "There is no 'CallGraph' summary for entity ID " +
- std::to_string(getIndex(ID)) + " aka. '" + FnName + "'");
- }
- return static_cast<const CallGraphSummary *>(EntityIt->second.get());
-}
-
-std::set<std::string> CallGraphExtractorTest::getUSRsForCallees(
- const std::set<EntityId> &Callees) const {
- std::set<std::string> USRs;
-
- auto GatherCalleeUSRs = [&](const EntityName &Name, EntityId Id) {
- if (llvm::is_contained(Callees, Id))
- USRs.insert(TestFixture::getUSR(Name));
- };
- TestFixture::getIdTable(Summary).forEach(GatherCalleeUSRs);
- assert(Callees.size() == USRs.size());
- return USRs;
-}
-
-llvm::Expected<std::set<std::string>>
-CallGraphExtractorTest::asUSRs(llvm::ArrayRef<StringRef> FnNames) {
- std::set<std::string> USRs;
- ASTContext &Ctx = AST->getASTContext();
- for (StringRef FnName : FnNames) {
- auto MaybeDecl = findDecl(Ctx, FnName);
- if (!MaybeDecl)
- return MaybeDecl.takeError();
- std::optional<EntityName> Name = getEntityName(MaybeDecl.get());
- if (!Name.has_value()) {
- return llvm::createStringError("Failed to get the USR of '" + FnName +
- "'");
- }
- USRs.insert(getUSR(Name.value()));
- }
- assert(USRs.size() == FnNames.size());
- return USRs;
-}
-
-// ============================================================================
-// Tests
-// ============================================================================
-
-TEST_F(CallGraphExtractorTest, SimpleFunctionCalls) {
- runExtractor(R"cpp(
- void a();
- void b();
- void calls_a_and_b(bool coin) {
- if (coin)
- a();
- else
- b();
- }
- )cpp");
-
- ASSERT_THAT_EXPECTED(
- findSummary("calls_a_and_b"),
- hasSummaryThat(hasDirectCallees({"a", "b"}), HasNoVirtualCallees()));
-}
-
-TEST_F(CallGraphExtractorTest, NoCallees) {
- runExtractor(R"cpp(
- void leaf() {}
- )cpp");
-
- ASSERT_THAT_EXPECTED(
- findSummary("leaf"),
- hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
-}
-
-TEST_F(CallGraphExtractorTest, TransitiveCalls) {
- runExtractor(R"cpp(
- void c() { /*empty*/ }
- void b() { c(); }
- void a() { b(); }
- )cpp");
-
- // a calls b (not c — we only record direct callees).
- ASSERT_THAT_EXPECTED(findSummary("a"), hasSummaryThat(hasDirectCallees({"b"}),
- HasNoVirtualCallees()));
-
- // b calls c.
- ASSERT_THAT_EXPECTED(findSummary("b"), hasSummaryThat(hasDirectCallees({"c"}),
- HasNoVirtualCallees()));
-
- // c calls nothing.
- ASSERT_THAT_EXPECTED(findSummary("c"), hasSummaryThat(HasNoDirectCallees(),
- HasNoVirtualCallees()));
-}
-
-TEST_F(CallGraphExtractorTest, VirtualCallsAreImprecise) {
- runExtractor(R"cpp(
- struct Base {
- virtual void virt();
- };
- struct Derived : Base {
- void virt() override;
- };
- void caller(Base &Obj) {
- Obj.virt();
- }
- )cpp");
-
- ASSERT_THAT_EXPECTED(
- findSummary("caller"),
- hasSummaryThat(HasNoDirectCallees(), hasVirtualCallees({"Base::virt"})));
-}
-
-TEST_F(CallGraphExtractorTest, MixedDirectAndVirtualCalls) {
- runExtractor(R"cpp(
- void direct_target();
- struct Base {
- virtual void virt();
- };
- void caller(Base &Obj) {
- direct_target();
- Obj.virt();
- }
- )cpp");
-
- ASSERT_THAT_EXPECTED(findSummary("caller"),
- hasSummaryThat(hasDirectCallees({"direct_target"}),
- hasVirtualCallees({"Base::virt"})));
-}
-
-TEST_F(CallGraphExtractorTest, DeclarationsOnlyNoSummary) {
- runExtractor(R"cpp(
- void declared_only();
- )cpp");
-
- // No summary for functions without definitions.
- EXPECT_FALSE(llvm::is_contained(getData(Summary), CallGraphName));
-}
-
-TEST_F(CallGraphExtractorTest, DuplicateCallees) {
- runExtractor(R"cpp(
- void target();
- void caller() {
- target();
- target();
- target();
- }
- )cpp");
-
- // Despite three calls, there's only one unique callee.
- ASSERT_THAT_EXPECTED(
- findSummary("caller"),
- hasSummaryThat(hasDirectCallees({"target"}), HasNoVirtualCallees()));
-}
-
-TEST_F(CallGraphExtractorTest, NonVirtualMethodCalls) {
- runExtractor(R"cpp(
- struct S {
- void method();
- };
- void caller() {
- S s;
- s.method();
- }
- )cpp");
-
- ASSERT_THAT_EXPECTED(
- findSummary("caller"),
- hasSummaryThat(hasDirectCallees({"method"}), HasNoVirtualCallees()));
-}
-
-TEST_F(CallGraphExtractorTest, StaticMethodCalls) {
- runExtractor(R"cpp(
- struct S {
- static void staticMethod();
- };
- void caller() {
- S::staticMethod();
- }
- )cpp");
-
- ASSERT_THAT_EXPECTED(findSummary("caller"),
- hasSummaryThat(hasDirectCallees({"staticMethod"}),
- HasNoVirtualCallees()));
-}
-
-TEST_F(CallGraphExtractorTest, FunctionPtrCall) {
- runExtractor(R"cpp(
- void caller(int (&fptr)()) {
- fptr();
- }
- )cpp");
-
- ASSERT_THAT_EXPECTED(
- findSummary("caller"),
- hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
-}
-
-TEST_F(CallGraphExtractorTest, ObjCMessageExprs) {
- runExtractor(R"cpp(
- @interface NSString
- - (id)stringByAppendingString:(id)str;
- @end
-
- void caller(void) {
- id msg = [@"Hello" stringByAppendingString:@", World!"];
- }
- )cpp",
- {"-x", "objective-c"});
-
- ASSERT_THAT_EXPECTED(
- findSummary("caller"),
- hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
-}
-
-TEST_F(CallGraphExtractorTest, ObjCMessageToLocallyImplementedMethod) {
- // When the receiver class is implemented in the same TU, `clang::CallGraph`
- // resolves the ObjCMessageExpr (via `lookupPrivateMethod`) to an
- // ObjCMethodDecl and adds it as a callee. The extractor must not abort on
- // these — ObjC dispatch is dynamic and we don't model it as a direct callee.
- runExtractor(R"cpp(
- @interface NSObject @end
- @interface Inner : NSObject
- - (int) val;
- @end
- @implementation Inner
- - (int) val { return 42; }
- @end
- int caller(Inner *x) { return [x val]; }
- )cpp",
- {"-x", "objective-c"});
-
- ASSERT_THAT_EXPECTED(
- findSummary("caller"),
- hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
-}
-
-TEST_F(CallGraphExtractorTest, ObjCPropertyDotSyntax) {
- // Property dot-syntax (`x.val`) desugars to an ObjCMessageExpr to the
- // synthesized getter; same dynamic dispatch as bracket syntax. Cover it
- // explicitly because real-world hits often come through dot-syntax.
- runExtractor(R"cpp(
- @interface NSObject @end
- @interface Inner : NSObject
- @property (readonly) int val;
- @end
- @implementation Inner
- @end
- int caller(Inner *x) { return x.val; }
- )cpp",
- {"-x", "objective-c"});
-
- ASSERT_THAT_EXPECTED(
- findSummary("caller"),
- hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
-}
-
-TEST_F(CallGraphExtractorTest, DefinitionLocation) {
- runExtractor(R"cpp(
- void callee_with_def() {}
- void callee_without_def();
- void caller(int n) {
- if (n == 0) return;
- callee_with_def();
- callee_without_def();
- caller(n - 1);
- }
- )cpp");
-
- ASSERT_THAT_EXPECTED(
- findSummary("caller"),
- hasSummaryThat(
- hasDirectCallees({"caller", "callee_with_def", "callee_without_def"}),
- HasNoVirtualCallees(), DefinedAt("input.cc", 4U, 10U)));
-
- ASSERT_THAT_EXPECTED(findSummary("callee_with_def"),
- hasSummaryThat(HasNoDirectCallees(),
- HasNoVirtualCallees(),
- DefinedAt("input.cc", 2U, 10U)));
-}
-
-TEST_F(CallGraphExtractorTest, PrettyName) {
- runExtractor(R"cpp(
- template <class T, int N>
- void templated_function(int *) {}
- void caller(int n) {
- templated_function<struct TypeTag, 404>(&n);
- }
- )cpp");
-
- ASSERT_THAT_EXPECTED(findSummary("caller"),
- hasSummaryThat(hasDirectCallees({"templated_function"}),
- HasNoVirtualCallees(),
- HasPrettyName("caller(int)")));
-
- // FIXME: The template arguments are not spelled here.
- ASSERT_THAT_EXPECTED(
- findSummary("templated_function"),
- hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees(),
- HasPrettyName("templated_function(int *)")));
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
deleted file mode 100644
index 49e7bdc21738b..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowTest.cpp
+++ /dev/null
@@ -1,1443 +0,0 @@
-//===- PointerFlowTest.cpp ------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
-#include "TestFixture.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DynamicRecursiveASTVisitor.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/SSAFOptions.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/SaveAndRestore.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <memory>
-#include <type_traits>
-#include <variant>
-
-using namespace clang;
-using namespace ssaf;
-
-namespace {
-// Use FindEntityByName to identify entities in unit tests.
-// Unit tests are simple enough to meet the following assumptions:
-// - Named declarations should have unique names, they can be found by comparing
-// names with strings;
-// - Lambdas should initialize a variable named "X", they can be found using
-// "LambdaOfVar("X")";
-// - CXX Ctors should have unique combination of names and number of parameters,
-// they can be found using "CXXCtorOfNumParms(name, numParms)".
-struct LambdaOfVar {
- StringRef VarName;
-};
-
-struct CXXCtorOfNumParms {
- StringRef CXXCtorName;
- unsigned NumParms;
-};
-
-using FindEntityByName =
- std::variant<StringRef, CXXCtorOfNumParms, LambdaOfVar>;
-
-template <typename... Ts> struct Overloaded : Ts... {
- using Ts::operator()...;
-};
-template <typename... Ts> Overloaded(Ts...) -> Overloaded<Ts...>;
-
-StringRef toStringRef(const FindEntityByName &N) {
- return std::visit(
- Overloaded{
- [](StringRef S) -> StringRef { return S; },
- [](const CXXCtorOfNumParms &L) -> StringRef { return L.CXXCtorName; },
- [](const LambdaOfVar &L) -> StringRef { return L.VarName; },
- },
- N);
-}
-
-const NamedDecl *matchNamedDeclByFindEntityByName(const FindEntityByName &N,
- const NamedDecl *D) {
- return std::visit(
- Overloaded{
- [&D](StringRef S) -> const NamedDecl * {
- if (D->getNameAsString() == S)
- return D;
- return nullptr;
- },
- [&D](const CXXCtorOfNumParms &L) -> const NamedDecl * {
- if (auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
- if (CD->getNameAsString() == L.CXXCtorName &&
- CD->getNumParams() == L.NumParms)
- return D;
- }
- return nullptr;
- },
- [&D](const LambdaOfVar &L) -> const NamedDecl * {
- if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->getInit()) {
- const Expr *Init = VD->getInit()->IgnoreUnlessSpelledInSource();
- if (isa<LambdaExpr>(Init) && VD->getNameAsString() == L.VarName)
- return cast<LambdaExpr>(Init)->getCallOperator();
- }
- return nullptr;
- },
- },
- N);
-}
-
-template <typename SomeDecl = NamedDecl,
- typename = std::enable_if_t<std::is_base_of_v<NamedDecl, SomeDecl>>>
-const SomeDecl *findEntityByName(FindEntityByName Name, ASTContext &Ctx) {
- class NamedDeclFinder : public DynamicRecursiveASTVisitor {
- public:
- FindEntityByName SearchingName;
- const SomeDecl *FoundDecl = nullptr;
-
- NamedDeclFinder(FindEntityByName SearchingName)
- : SearchingName(SearchingName) {
- ShouldVisitTemplateInstantiations = true;
- }
-
- bool VisitDecl(Decl *D) override {
- if (D->isTemplated())
- return true;
- if (auto *ND = dyn_cast<NamedDecl>(D)) {
- FoundDecl = llvm::dyn_cast_or_null<SomeDecl>(
- matchNamedDeclByFindEntityByName(SearchingName, ND));
- if (FoundDecl)
- return false;
- }
- return true;
- }
- };
-
- NamedDeclFinder Finder(Name);
-
- Finder.TraverseDecl(Ctx.getTranslationUnitDecl());
- return dyn_cast_or_null<SomeDecl>(Finder.FoundDecl);
-}
-
-const FunctionDecl *findFnByName(FindEntityByName Name, ASTContext &Ctx) {
- return findEntityByName<FunctionDecl>(Name, Ctx);
-}
-
-// Same as `std::pair<StringName, unsigned>` for a pair of entity declaration
-// name and a pointer level with an extra optional flag for whether the entity
-// represents a function return value. This structure is used to explicitly
-// spell out components of an EPL such as "{"p", 1}" or "{"foo_fn", 2, true}".
-struct EPLPair {
- EPLPair(FindEntityByName Name, unsigned Lv, bool isFunRet = false)
- : Name(Name), Lv(Lv), isFunRet(isFunRet) {}
-
- FindEntityByName Name;
- unsigned Lv;
- bool isFunRet;
-};
-
-class PointerFlowTest : public TestFixture {
-protected:
- SSAFOptions Opts;
- TUSummary TUSum;
- TUSummaryBuilder Builder;
- std::unique_ptr<TUSummaryExtractor> Extractor;
- std::unique_ptr<ASTUnit> AST;
-
- PointerFlowTest()
- : TUSum(llvm::Triple("arm64-apple-macosx"),
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")),
- Builder(TUSum, Opts), Extractor(nullptr) {}
-
- template <typename ContributorDecl = NamedDecl,
- typename =
- std::enable_if_t<std::is_base_of_v<NamedDecl, ContributorDecl>>>
- bool setUpTest(StringRef Code) {
- AST = tooling::buildASTFromCodeWithArgs(
- Code, {"-Wno-unused-value", "-Wno-int-to-pointer-cast"});
-
- 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 =
- findEntityByName<ContributorDecl>(Name, AST->getASTContext());
-
- if (!ContributorDefn) {
- ADD_FAILURE() << "failed to find Decl of \"" << toStringRef(Name) << "\"";
- return nullptr;
- }
-
- std::optional<EntityId> ContributorEntityId =
- Extractor->addEntity(ContributorDefn);
-
- if (!ContributorEntityId) {
- ADD_FAILURE() << "failed to get EntityName for contributor \""
- << toStringRef(Name) << "\"";
- return nullptr;
- }
-
- auto &TUSumData = getData(TUSum);
- auto EntitiesSumIter =
- TUSumData.find(PointerFlowEntitySummary::summaryName());
-
- // If none entity summary was collected, it may not be an entry in
- // `TUSumData`:
- if (EntitiesSumIter == TUSumData.end())
- return nullptr;
-
- auto EntitySumIter = EntitiesSumIter->second.find(*ContributorEntityId);
-
- // If entity summary is empty, it may not exist:
- if (EntitySumIter == EntitiesSumIter->second.end())
- return nullptr;
- return static_cast<const PointerFlowEntitySummary *>(
- EntitySumIter->second.get());
- }
-
-public:
- std::optional<EntityId> getEntityId(FindEntityByName Name) {
- if (const auto *D = findEntityByName(Name, AST->getASTContext())) {
- return Extractor->addEntity(D);
- }
- return std::nullopt;
- }
-
- std::optional<EntityId> getEntityIdForReturn(FindEntityByName FunName) {
- if (const auto *D = findFnByName(FunName, AST->getASTContext())) {
- return Extractor->addEntityForReturn(D);
- }
- return std::nullopt;
- }
-
- EdgeSet makeEdges(unsigned Line, ArrayRef<std::pair<EPLPair, EPLPair>> Edges);
-};
-
-// 'ToEPL(Test, Line)' is a lambda that converts a 'EPLPair' to a
-// 'EntityPointerLevel':
-static constexpr auto ToEPL =
- [](PointerFlowTest *Test,
- unsigned Line) -> std::function<EntityPointerLevel(const EPLPair &)> {
- return [Test, Line](const EPLPair &Pair) -> EntityPointerLevel {
- std::optional<EntityId> Entity = Pair.isFunRet
- ? Test->getEntityIdForReturn(Pair.Name)
- : Test->getEntityId(Pair.Name);
- if (!Entity) {
- ADD_FAILURE_AT(__FILE__, Line)
- << "Entity not found: " << toStringRef(Pair.Name);
- }
- return buildEntityPointerLevel(*Entity, Pair.Lv);
- };
-};
-
-EdgeSet
-PointerFlowTest::makeEdges(unsigned Line,
- ArrayRef<std::pair<EPLPair, EPLPair>> Edges) {
- EdgeSet Result;
- for (auto Edge : Edges)
- Result[ToEPL(this, Line)(Edge.first)].insert(
- ToEPL(this, Line)(Edge.second));
- return Result;
-}
-
-TEST_F(PointerFlowTest, IsExtractorRegisteredTest) {
- EXPECT_TRUE(isTUSummaryExtractorRegistered("PointerFlow"));
-}
-
-//////////////////////////////////////////////////////////////
-// Simple Assign Tests //
-//////////////////////////////////////////////////////////////
-TEST_F(PointerFlowTest, SimpleAssign) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p, int *q) {
- q = p;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, AssignWithSubscriptLHS) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int **q, int *p, int x) {
- q[x] = p;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 2U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, AssignWithPtrArithRHS) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p, int *q) {
- q = p + 5;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, AssignInSubscript) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p, int *q) {
- (q = p)[5];
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, MultipleAssign) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p, int *q, int *r) {
- q = p;
- r = q;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"q", 1U}, {"p", 1U}},
- {{"r", 1U}, {"q", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, ChainedAssign) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p, int *q, int *r) {
- r = q = p;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"q", 1U}, {"p", 1U}},
- {{"r", 1U}, {"q", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, CastToRValue) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p, int *q) {
- q = static_cast<int *&&>(p);
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, AssignToMember) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S { int *field; };
- void foo(S s, int *p) {
- s.field = p;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"field", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, AssignToMember2) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S { int *field; };
- void foo(S *s, int *p) {
- s->field = p;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"field", 1U}, {"p", 1U}}}));
-}
-
-//////////////////////////////////////////////////////////////
-// Call Expr Tests. //
-//////////////////////////////////////////////////////////////
-TEST_F(PointerFlowTest, CallArg) {
- ASSERT_EQ(setUpTest(R"cpp(
- void bar(int *param);
- void foo(int *p) {
- bar(p);
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"param", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, CallMultiArgs) {
- ASSERT_EQ(setUpTest(R"cpp(
- void bar(int *param1, int y, int *param2);
- void foo(int *p, int x, int *q) {
- bar(p, x, q);
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"param1", 1U}, {"p", 1U}},
- {{"param2", 1U}, {"q", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, CallAsCallArg) {
- ASSERT_EQ(setUpTest(R"cpp(
-
- int *bar(int * w);
- void foo(int * p) {
- foo(bar(p));
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"w", 1U}, {"p", 1U}},
- {{"p", 1U}, {"bar", 1U, true}}}));
-}
-
-TEST_F(PointerFlowTest, CXXOperatorCallMultiArgs) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S {
- int* operator()(int *a, int *b);
- };
- void foo(S obj, int *p, int *q) {
- foo(obj, obj(p, q), obj(p, q));
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"q", 1U}},
- {{"p", 1U}, {"operator()", 1U, true}},
- {{"q", 1U}, {"operator()", 1U, true}},
- }));
-}
-
-TEST_F(PointerFlowTest, CXXMemberCall) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S {
- int* method(int *a, int *b);
- };
- void foo(S obj, int *p, int *q) {
- foo(obj, obj.method(p, q), obj.method(p, q));
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"q", 1U}},
- {{"p", 1U}, {"method", 1U, true}},
- {{"q", 1U}, {"method", 1U, true}}}));
-}
-
-TEST_F(PointerFlowTest, VirtualMethodCall) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct Base {
- virtual void method(int *a);
- };
- void foo(Base &obj, int *p) {
- obj.method(p);
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"a", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, StaticMethodCall) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S {
- static void method(int *a, int *b);
- };
- void foo(int *p, int *q) {
- S::method(p, q);
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"q", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, DefaultArg) {
- ASSERT_EQ(setUpTest(R"cpp(
- int *g;
- void bar(int *a, int *b = g);
- void foo(int *p) {
- bar(p);
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__,
- {{{"a", 1U}, {"p", 1U}}, {{"b", 1U}, {"g", 1U}}}));
-}
-
-// Counter-example for the concern that matchArgsWithParams could go OOB
-// when fewer explicit args are provided than params (due to default args).
-// In Clang's AST, CallExpr::getNumArgs() always includes CXXDefaultArgExpr
-// nodes for defaulted parameters, so getNumArgs() >= getNumParams() holds.
-TEST_F(PointerFlowTest, AllArgsDefaulted) {
- ASSERT_EQ(setUpTest(R"cpp(
- int *g1, *g2;
- void bar(int *a = g1, int *b = g2);
- void foo() {
- bar();
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"g1", 1U}},
- {{"b", 1U}, {"g2", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, DefaultArg2) {
- ASSERT_EQ(setUpTest(R"cpp(
- int *g;
- void bar(int *a, int *b = g);
- void foo(int *p) {
- bar(p, p);
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"p", 1U}},
- }));
-}
-
-//////////////////////////////////////////////////////////////
-// CXX Ctor Tests. //
-//////////////////////////////////////////////////////////////
-TEST_F(PointerFlowTest, CXXCtorCallMultiArgs) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S {
- S(int *a, int *b) {}
- };
- void foo(int *p, int *q) {
- S s{p, q};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"q", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, CXXCtorCallMultiArgs2) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S {
- S(int *a, int x, int *b) {}
- };
- void foo(int *p, int x, int *q) {
- S s{p, x, q};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"q", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, CXXCtorCallAsCallArg) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct Wrapper {
- Wrapper(int *q) {}
- };
- void bar(Wrapper w);
- void foo(int *p) {
- bar(Wrapper{p});
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, DelegatingCXXCtorCall) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S {
- S(int *a, int *b) {}
- S(int *p) : S(p, p) {}
- };
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary<CXXConstructorDecl>(CXXCtorOfNumParms{"S", 1});
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"p", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, CXXCtorBaseInit) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct Base {
- Base(int *a) {}
- };
- struct Derived : Base {
- Derived(int *p) : Base(p) {}
- };
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary<CXXConstructorDecl>("Derived");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"a", 1U}, {"p", 1U}}}));
-}
-
-//////////////////////////////////////////////////////////////
-// Initializers Tests. //
-//////////////////////////////////////////////////////////////
-TEST_F(PointerFlowTest, LocalVarDeclInit) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p) {
- int *q = p;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, LocalVarDeclInit2) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int (*arr)[10]) {
- int (*p)[10] = arr;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"p", 1U}, {"arr", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, FieldInit) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p) {
- struct Bar {
- int *field = p;
- };
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("Bar");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"field", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, CXXCtorMemberInit) {
- StringRef Code = R"cpp(
- void foo(int *p) {
- struct Bar {
- int *member;
- Bar(int *q) : member(q) {}
- };
- Bar B{p};
- }
- )cpp";
-
- ASSERT_EQ(setUpTest(Code), true);
- auto *Sum = getEntitySummary<CXXConstructorDecl>("Bar");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"member", 1U}, {"q", 1U}}}));
-
- Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, GlobalVarInit) {
- ASSERT_EQ(setUpTest(R"cpp(
- int *q;
- int *g = q;
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary<VarDecl>("g");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"g", 1U}, {"q", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, StaticLocalInit) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p) {
- static int *s = p;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"s", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, StaticMemberInit) {
- ASSERT_EQ(setUpTest(R"cpp(
- int *g;
- struct S { static int *member; };
- int *S::member = g;
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary<VarDecl>("member");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"member", 1U}, {"g", 1U}}}));
-}
-
-//////////////////////////////////////////////////////////////
-// InitList Tests. //
-//////////////////////////////////////////////////////////////
-
-TEST_F(PointerFlowTest, ArrayInitList) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p, int *q) {
- int *arr[] = {p, q};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"arr", 2U}, {"p", 1U}},
- {{"arr", 2U}, {"q", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, StructInitList) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S { int *a; int *b; };
- void foo(int *p, int *q) {
- S s = {p, q};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"q", 1U}},
- }));
-}
-
-// A union initialized with a brace-enclosed initializer:
-TEST_F(PointerFlowTest, UnionInitList) {
- ASSERT_EQ(setUpTest(R"cpp(
- union U { int *x; int y; };
- void foo(int *p) {
- U u = {p};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"x", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, NestedInitList) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct Inner { int * a; int * b; };
- struct S { Inner c; int * d; };
- void foo(int *p, int *q, int *r) {
- S s = {{p, q}, r};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"q", 1U}},
- {{"d", 1U}, {"r", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, NestedInitList2) {
- ASSERT_EQ(setUpTest(R"cpp(
- union Inner { int * a; int b; };
- struct S { Inner c; int * d; };
- void foo(int *p, int *q) {
- S s = {{p}, q};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"d", 1U}, {"q", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, NestedInitList3) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct Inner { int * a; int * b; };
- union S { Inner c; int * d; };
- void foo(int *p, int *q) {
- S s = {{p, q}};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"q", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, NestedArrayInitList) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p, int *q, int *r, int *s) {
- int *arr[][2] = {{p, q}, {r, s}};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"arr", 3U}, {"p", 1U}},
- {{"arr", 3U}, {"q", 1U}},
- {{"arr", 3U}, {"r", 1U}},
- {{"arr", 3U}, {"s", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, MixedNestedArrayStructInitList) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct T { int *arr[2]; };
- void foo(int *p, int *q, int *r, int *s) {
- T t[2] = {{p, q}, {r, s}};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"arr", 2U}, {"p", 1U}},
- {{"arr", 2U}, {"q", 1U}},
- {{"arr", 2U}, {"r", 1U}},
- {{"arr", 2U}, {"s", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, ArrayOfStructInitList) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S { int *a; int *b; };
- void foo(int *p, int *q, int *r, int *s) {
- S arr[] = {{p, q}, {r, s}};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"a", 1U}, {"p", 1U}},
- {{"b", 1U}, {"q", 1U}},
- {{"a", 1U}, {"r", 1U}},
- {{"b", 1U}, {"s", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, ScalarPointerBraceInit) {
- ASSERT_TRUE(setUpTest(R"cpp(
- int *q;
- void foo() {
- int *p{q};
- }
- )cpp"));
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"p", 1U}, {"q", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, EmptyInitsScalarInt) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo() {
- int x{};
- int y = {};
- int *p{};
- int *q = {};
- }
- )cpp"));
-
- // No pointer-flow edge for 0-initialized scalar.
- ASSERT_FALSE(getEntitySummary("foo"));
-}
-
-TEST_F(PointerFlowTest, EmptyInitsUnion) {
- ASSERT_TRUE(setUpTest(R"cpp(
- union U { int x; int *p; };
- void foo() {
- U u{};
- U uu = {};
- }
- )cpp"));
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_EQ(Sum, nullptr);
-}
-
-TEST_F(PointerFlowTest, EmptyInitsStruct) {
- ASSERT_TRUE(setUpTest(R"cpp(
- struct S { int x; int *p; };
- void foo() {
- S s{};
- S ss = {};
- }
- )cpp"));
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_EQ(Sum, nullptr);
-}
-
-TEST_F(PointerFlowTest, EmptyInitsClass) {
- ASSERT_TRUE(setUpTest(R"cpp(
- class C { public: int x; int *p; };
- void foo() {
- C c{};
- C cc = {};
- }
- )cpp"));
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_EQ(Sum, nullptr);
-}
-
-//////////////////////////////////////////////////////////////
-// Return Tests. //
-//////////////////////////////////////////////////////////////
-
-TEST_F(PointerFlowTest, ReturnEdge) {
- ASSERT_EQ(setUpTest(R"cpp(
- int *foo(int *p) {
- return p;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"foo", 1U, true}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, MultipleReturnEdges) {
- ASSERT_EQ(setUpTest(R"cpp(
- int *foo(int *p, int *q, bool cond) {
- if (cond)
- return p;
- return q;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {
- {{"foo", 1U, true}, {"p", 1U}},
- {{"foo", 1U, true}, {"q", 1U}},
- }));
-}
-
-TEST_F(PointerFlowTest, NoReturnEdgeForNonPointerReturnType) {
- ASSERT_EQ(setUpTest(R"cpp(
- int foo(int *p, int x) {
- return x;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- EXPECT_THAT(Sum, testing::AnyOf(testing::IsNull(),
- testing::Pointee(makeEdges(__LINE__, {}))));
-}
-
-TEST_F(PointerFlowTest, ReturnEdgeNotFromNestedFunction) {
- StringRef Code = R"cpp(
- int *foo(int *p) {
- struct Inner {
- int *bar(int *q) { return q; }
- };
- return p;
- }
- )cpp";
-
- ASSERT_EQ(setUpTest(Code), true);
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"foo", 1U, true}, {"p", 1U}}}));
-
- Sum = getEntitySummary("bar");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"bar", 1U, true}, {"q", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, ReturnEdgeInClassMethod) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo() {
- struct S {
- int *method(int *p, int *q) { return p; }
- };
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("method");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"method", 1U, true}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, NoEdgeFromIndirectCall) {
- ASSERT_EQ(setUpTest(R"cpp(
- void bar(int *param1);
- void baz(int *param2);
-
- void foo(int *p, void (*fp)(int *)) {
- fp(p);
- }
-
- int main() {
- int *q;
- foo(q, bar);
- foo(q, baz);
- return 0;
- }
- )cpp"),
- true);
-
- /* FIXME or TBD: Currently indirect calls produce no edge: */
- auto *Sum = getEntitySummary("foo");
-
- EXPECT_THAT(Sum, testing::AnyOf(testing::IsNull(),
- testing::Pointee(makeEdges(__LINE__, {}))));
-}
-
-//////////////////////////////////////////////////////////////
-// Lambda Tests. //
-//////////////////////////////////////////////////////////////
-
-TEST_F(PointerFlowTest, ReturnInLambda) {
- StringRef Code = R"cpp(
- int* foo(int *p) {
- auto local = [](int *r) { return r; };
- return local(p);
- }
- )cpp";
-
- ASSERT_EQ(setUpTest(Code), true);
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"r", 1U}, {"p", 1U}},
- {{"foo", 1U, true},
- {LambdaOfVar{"local"}, 1U, true}}}));
-
- Sum = getEntitySummary(LambdaOfVar{"local"});
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__,
- {{{LambdaOfVar{"local"}, 1U, true}, {"r", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, NestedLambdaAssign) {
- StringRef Code = R"cpp(
- void foo() {
- auto outer_lambda = [](int *r, int *s) {
- s = r;
- auto inner_lambda = [](int *x, int *y) { y = x; };
- };
- }
- )cpp";
-
- ASSERT_EQ(setUpTest(Code), true);
- auto *Sum = getEntitySummary(LambdaOfVar{"outer_lambda"});
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"s", 1U}, {"r", 1U}}}));
-
- Sum = getEntitySummary(LambdaOfVar{"inner_lambda"});
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"y", 1U}, {"x", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, ImplicitValueInit) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S { int *a; int *b; };
- void foo(int *p) {
- S s = {p}; // ImplicitValueInit inits 'b'
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"a", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, InitListExpr) {
- ASSERT_EQ(setUpTest(R"cpp(
- void foo(int *p) {
- int *q = {p};
- int *r = {};
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, CXXDefaultInitExpr) {
- ASSERT_EQ(setUpTest(R"cpp(
- int *g;
- struct S {
- int *field = g;
- };
- void foo(int *p) {
- S s;
- s.field = p;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary<RecordDecl>("S");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"field", 1U}, {"g", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, CXXConstructExprArrayInit) {
- ASSERT_EQ(setUpTest(
- R"cpp(
- struct S {};
- void foo(S *q) {
- S arr[3]; // -VarDecl <...> arr 'S[3]' callinit
- // `-CXXConstructExpr <...> 'S[3]' 'void () noexcept'
- q = arr;
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"arr", 1U}}}));
-}
-
-//////////////////////////////////////////////////////////////
-// Template is ignored but instantiations are visited. //
-//////////////////////////////////////////////////////////////
-TEST_F(PointerFlowTest, FunctionTemplate) {
- ASSERT_TRUE(setUpTest(R"cpp(
- template <typename T>
- T* f(T *p) {
- int *q = p;
- return q;
- }
- )cpp"));
- ASSERT_FALSE(findEntityByName("f", AST->getASTContext()));
-}
-
-TEST_F(PointerFlowTest, MethodInClassTemplate) {
- ASSERT_TRUE(setUpTest(R"cpp(
- template <typename T>
- struct Wrapper {
- T *ptr;
- void set(T *p) { ptr = p; }
- };
- )cpp"));
- ASSERT_FALSE(findEntityByName("set", AST->getASTContext()));
-}
-
-TEST_F(PointerFlowTest, FunctionTemplateInstantiation) {
- ASSERT_TRUE(setUpTest(R"cpp(
- template <typename T>
- T* f(T *p) {
- int *q = p;
- return q;
- }
-
- void test(int *p) {
- f(p);
- }
- )cpp"));
-
- auto *Sum = getEntitySummary<FunctionDecl>("f");
-
- ASSERT_TRUE(Sum);
- ASSERT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}},
- {{"f", 1U, 1}, {"q", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, MethodInClassTemplateInstantiation) {
- ASSERT_TRUE(setUpTest(R"cpp(
- template <typename T>
- struct Wrapper {
- T *ptr;
- void set(T *p) { ptr = p; }
- };
-
- void test(int *p) {
- Wrapper<int> W;
-
- W.set(p);
- }
- )cpp"));
-
- auto *Sum = getEntitySummary<FunctionDecl>("set");
-
- ASSERT_TRUE(Sum);
- ASSERT_EQ(*Sum, makeEdges(__LINE__, {{{"ptr", 1U}, {"p", 1U}}}));
-}
-
-//////////////////////////////////////////////////////////////
-// Robustness Tests (No Crash Tests) //
-//////////////////////////////////////////////////////////////
-
-#ifndef NDEBUG
-TEST_F(PointerFlowTest, StructuredBindingWithPointers) {
- StringRef Code = R"cpp(
- void foo() {
- int *a[2];
- auto [ptr1, ptr2] = a;
- ptr1[5];
- ptr2[3];
- }
- )cpp";
-
- // BindingDecl may not be fully supported, but should not crash.
- llvm::SaveAndRestore<bool> DebugFlag(llvm::DebugFlag, true);
- llvm::setCurrentDebugType("ssaf-analyses");
- testing::internal::CaptureStderr();
-
- ASSERT_TRUE(setUpTest(Code));
- // Verify the warning was logged
- ASSERT_TRUE(StringRef(testing::internal::GetCapturedStderr())
- .contains("failed to create EntityId for Decomposition"));
-}
-#endif
-
-TEST_F(PointerFlowTest, RHSResultsInNoEntityPointerLevel) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void f() {
- int *p = new int[10];
- const char *q = "hello";
- }
- struct S {
- int *p;
- void g() { p = (int *)this; }
- };
- )cpp"));
- ASSERT_FALSE(getEntitySummary<FunctionDecl>("f"));
- ASSERT_FALSE(getEntitySummary<CXXMethodDecl>("g"));
-}
-
-//////////////////////////////////////////////////////////////
-// Reference-to-pointer Tests //
-//////////////////////////////////////////////////////////////
-
-TEST_F(PointerFlowTest, ArgToRefParam) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void callee(int *&rp);
- void caller(int *p) {
- callee(p);
- }
- )cpp"));
-
- auto *Sum = getEntitySummary("caller");
-
- ASSERT_TRUE(Sum);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"rp", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, ArgToRefParamLevel2) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void callee(int **&rp);
- void caller(int **pp) {
- callee(pp);
- }
- )cpp"));
-
- auto *Sum = getEntitySummary("caller");
-
- ASSERT_TRUE(Sum);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"rp", 1U}, {"pp", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, InitRefPtr) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p) {
- int *&rp = p;
- int * const & crp = p;
- }
- )cpp"));
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_TRUE(Sum);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"rp", 1U}, {"p", 1U}},
- {{"crp", 1U}, {"p", 1U}}}));
-}
-
-TEST_F(PointerFlowTest, ReturnRefPtr) {
- ASSERT_TRUE(setUpTest(R"cpp(
- int *& f();
- int *& foo() {
- return f();
- }
- )cpp"));
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_TRUE(Sum);
- EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"foo", 1U, true}, {"f", 1U, true}}}));
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowWPATest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowWPATest.cpp
deleted file mode 100644
index c2b906d715695..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowWPATest.cpp
+++ /dev/null
@@ -1,141 +0,0 @@
-//===- PointerFlowWPATest.cpp ---------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <memory>
-
-using namespace clang;
-using namespace ssaf;
-using testing::IsEmpty;
-using testing::UnorderedElementsAre;
-
-PointerFlowEntitySummary ssaf::buildPointerFlowEntitySummary(EdgeSet Edges);
-
-namespace {
-
-class PointerFlowWPATest : public TestFixture {
-protected:
- static constexpr EntityLinkage ExternalLinkage =
- EntityLinkage(EntityLinkageType::External);
-
- std::unique_ptr<LUSummary> makeLUSummary() {
- NestedBuildNamespace NS(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
- return std::make_unique<LUSummary>(llvm::Triple("arm64-apple-macosx"),
- std::move(NS));
- }
-
- EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
- NestedBuildNamespace NS(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
- EntityName Name(USR.str(), "", NS);
- EntityId Id = getIdTable(LU).getId(Name);
- getLinkageTable(LU).insert({Id, ExternalLinkage});
- return Id;
- }
-
- void insertSummary(LUSummary &LU, EntityId Id, EdgeSet Edges) {
- getData(LU)[PointerFlowEntitySummary::summaryName()][Id] =
- std::make_unique<PointerFlowEntitySummary>(
- buildPointerFlowEntitySummary(std::move(Edges)));
- }
-
- const PointerFlowAnalysisResult &
- runAnalysisForResult(std::unique_ptr<LUSummary> LU) {
- AnalysisDriver Driver(std::move(LU));
- auto WPAOrErr = Driver.run<PointerFlowAnalysisResult>();
- EXPECT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
- WPA = std::move(*WPAOrErr);
- auto ROrErr = WPA.get<PointerFlowAnalysisResult>();
- EXPECT_THAT_EXPECTED(ROrErr, llvm::Succeeded());
- return *ROrErr;
- }
-
-private:
- WPASuite WPA = makeWPASuite();
-};
-
-TEST_F(PointerFlowWPATest, SingleEntitySummary) {
- auto LU = makeLUSummary();
- EntityId Foo = addEntity(*LU, "c:@F at foo");
- EntityId Src = addEntity(*LU, "c:@F at foo@src");
- EntityId Dest = addEntity(*LU, "c:@F at foo@dest");
- auto Src1 = buildEntityPointerLevel(Src, 1);
- auto Dest1 = buildEntityPointerLevel(Dest, 1);
- auto Dest2 = buildEntityPointerLevel(Dest, 2);
- EdgeSet Edges;
-
- Edges[Src1] = {Dest1, Dest2};
- insertSummary(*LU, Foo, std::move(Edges));
-
- const auto &Result = runAnalysisForResult(std::move(LU));
-
- ASSERT_EQ(Result.Edges.size(), 1u);
- EXPECT_EQ(Result.Edges.at(Foo).size(), 1u);
- EXPECT_THAT(Result.Edges.at(Foo).at(Src1),
- UnorderedElementsAre(Dest1, Dest2));
-}
-
-TEST_F(PointerFlowWPATest, MultiEntitySummaries) {
- auto LU = makeLUSummary();
- EntityId Foo = addEntity(*LU, "c:@F at foo");
- EntityId Bar = addEntity(*LU, "c:@F at bar");
- EntityId FooSrc = addEntity(*LU, "c:@F at foo@src");
- EntityId FooDest = addEntity(*LU, "c:@F at foo@dest");
- EntityId BarSrc = addEntity(*LU, "c:@F at bar@src");
- EntityId BarDest = addEntity(*LU, "c:@F at bar@dest");
- auto FooSrc1 = buildEntityPointerLevel(FooSrc, 1);
- auto BarSrc1 = buildEntityPointerLevel(BarSrc, 1);
- EntityPointerLevelSet FooDests, BarDests;
-
- for (unsigned I = 0; I < 5; ++I) {
- FooDests.insert(buildEntityPointerLevel(FooDest, I));
- BarDests.insert(buildEntityPointerLevel(BarDest, I));
- }
-
- EdgeSet FooEdges;
- FooEdges[FooSrc1] = FooDests;
- insertSummary(*LU, Foo, std::move(FooEdges));
-
- EdgeSet BarEdges;
- BarEdges[BarSrc1] = BarDests;
- insertSummary(*LU, Bar, std::move(BarEdges));
-
- const auto &R = runAnalysisForResult(std::move(LU));
-
- EXPECT_EQ(R.Edges.size(), 2u);
- EXPECT_EQ(R.Edges.at(Foo).at(FooSrc1), FooDests);
- EXPECT_EQ(R.Edges.at(Bar).at(BarSrc1), BarDests);
-}
-
-TEST_F(PointerFlowWPATest, EmptySummary) {
- auto LU = makeLUSummary();
- EntityId Foo = addEntity(*LU, "c:@F at foo");
-
- insertSummary(*LU, Foo, {});
-
- const auto &R = runAnalysisForResult(std::move(LU));
-
- ASSERT_EQ(R.Edges.count(Foo), 1u);
- EXPECT_THAT(R.Edges.at(Foo), IsEmpty());
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
deleted file mode 100644
index 5b9bd94ec2014..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
+++ /dev/null
@@ -1,783 +0,0 @@
-//===- UnsafeBufferUsageTest.cpp ------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "FindDecl.h"
-#include "TestFixture.h"
-#include "clang/Frontend/ASTUnit.h"
-#include "clang/Frontend/SSAFOptions.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/SaveAndRestore.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <initializer_list>
-#include <memory>
-#include <optional>
-
-using namespace clang;
-using namespace ssaf;
-using testing::UnorderedElementsAre;
-
-namespace {
-class UnsafeBufferUsageTest : public TestFixture {
-protected:
- SSAFOptions Opts;
- TUSummary TUSum;
- TUSummaryBuilder Builder;
- std::unique_ptr<TUSummaryExtractor> Extractor;
- std::unique_ptr<ASTUnit> AST;
-
- UnsafeBufferUsageTest()
- : TUSum(llvm::Triple("arm64-apple-macosx"),
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")),
- Builder(TUSum, Opts) {}
-
- bool setUpTest(StringRef Code) {
- AST = tooling::buildASTFromCodeWithArgs(
- Code, {"-Wno-unused-value", "-Wno-int-to-pointer-cast"});
-
- Extractor =
- makeTUSummaryExtractor(UnsafeBufferUsageEntitySummary::Name, Builder);
-
- if (!Extractor) {
- ADD_FAILURE() << "failed to find UnsafeBufferUsageTUSummaryExtractor";
- return false;
- }
- Extractor->HandleTranslationUnit(AST->getASTContext());
- return true;
- }
-
- template <typename ContributorDecl = NamedDecl>
- const UnsafeBufferUsageEntitySummary *
- getEntitySummary(StringRef ContributorEntityName) {
- auto *ContributorDefn = findDeclByName<ContributorDecl>(
- ContributorEntityName, AST->getASTContext());
-
- if (!ContributorDefn) {
- ADD_FAILURE() << "failed to find Decl of \"" << ContributorEntityName
- << "\"";
- return nullptr;
- }
-
- std::optional<EntityId> ContributorEntityId =
- Extractor->addEntity(ContributorDefn);
- if (!ContributorEntityId) {
- ADD_FAILURE() << "failed to get EntityName for contributor \""
- << ContributorEntityName << "\"";
- return nullptr;
- }
-
- auto &TUSumData = getData(TUSum);
- auto EntitiesSumIter =
- TUSumData.find(UnsafeBufferUsageEntitySummary::summaryName());
-
- // If none entity summary was collected, it may not be an entry in
- // `TUSumData`:
- if (EntitiesSumIter == TUSumData.end())
- return nullptr;
-
- auto EntitySumIter = EntitiesSumIter->second.find(*ContributorEntityId);
-
- // If entity summary is empty, it may not exist:
- if (EntitySumIter == EntitiesSumIter->second.end())
- return nullptr;
- return static_cast<const UnsafeBufferUsageEntitySummary *>(
- EntitySumIter->second.get());
- }
-
- std::optional<EntityId> getEntityId(StringRef Name) {
- if (const auto *D = findDeclByName(Name, AST->getASTContext()))
- return Extractor->addEntity(D);
- return std::nullopt;
- }
-
- std::optional<EntityId> getEntityIdForReturn(StringRef FunName) {
- if (const auto *D = findFnByName(FunName, AST->getASTContext()))
- return Extractor->addEntityForReturn(D);
- return std::nullopt;
- }
-
- // Same as `std::pair<StringName, unsigned>` for a pair of entity declaration
- // name and a pointer level with an extra optional flag for whether the entity
- // represents a function return value:
- struct EPLPair {
- EPLPair(StringRef Name, unsigned Lv, bool isFunRet = false)
- : Name(Name), Lv(Lv), isFunRet(isFunRet) {}
-
- StringRef Name;
- unsigned Lv;
- bool isFunRet;
- };
-
- EntityPointerLevelSet makeSet(unsigned Line, ArrayRef<EPLPair> Pairs) {
- auto EPLs = llvm::map_range(
- Pairs, [this, Line](const EPLPair &Pair) -> EntityPointerLevel {
- std::optional<EntityId> Entity = Pair.isFunRet
- ? getEntityIdForReturn(Pair.Name)
- : getEntityId(Pair.Name);
- if (!Entity)
- ADD_FAILURE_AT(__FILE__, Line) << "Entity not found: " << Pair.Name;
- return buildEntityPointerLevel(*Entity, Pair.Lv);
- });
- return EntityPointerLevelSet{EPLs.begin(), EPLs.end()};
- }
-};
-
-//////////////////////////////////////////////////////////////
-// Data Structure Tests //
-//////////////////////////////////////////////////////////////
-
-static llvm::iterator_range<EntityPointerLevelSet::iterator>
-getSubsetOf(const EntityPointerLevelSet &Set, EntityId Entity) {
- return llvm::make_range(Set.equal_range(Entity));
-}
-
-TEST_F(UnsafeBufferUsageTest, EntityPointerLevelComparison) {
- EntityIdTable Table;
- EntityId E1 = Table.getId({"c:@F at foo", "", {}});
- EntityId E2 = Table.getId({"c:@F at bar", "", {}});
-
- auto P1 = buildEntityPointerLevel(E1, 2);
- auto P2 = buildEntityPointerLevel(E1, 2);
- auto P3 = buildEntityPointerLevel(E1, 1);
- auto P4 = buildEntityPointerLevel(E2, 2);
-
- EXPECT_EQ(P1, P2);
- EXPECT_NE(P1, P3);
- EXPECT_NE(P1, P4);
- EXPECT_NE(P3, P4);
- EXPECT_TRUE(P3 < P2);
- EXPECT_TRUE(P3 < P4);
- EXPECT_FALSE(P1 < P2);
- EXPECT_FALSE(P2 < P1);
-}
-
-TEST_F(UnsafeBufferUsageTest, UnsafeBufferUsageEntityPointerLevelSetTest) {
- EntityIdTable Table;
- EntityId E1 = Table.getId({"c:@F at foo", "", {}});
- EntityId E2 = Table.getId({"c:@F at bar", "", {}});
- EntityId E3 = Table.getId({"c:@F at baz", "", {}});
-
- auto P1 = buildEntityPointerLevel(E1, 1);
- auto P2 = buildEntityPointerLevel(E1, 2);
- auto P3 = buildEntityPointerLevel(E2, 1);
- auto P4 = buildEntityPointerLevel(E2, 2);
- auto P5 = buildEntityPointerLevel(E3, 1);
-
- EntityPointerLevelSet Set{P1, P2, P3, P4, P5};
-
- EXPECT_THAT(Set, UnorderedElementsAre(P1, P2, P3, P4, P5));
- EXPECT_THAT(getSubsetOf(Set, E1), UnorderedElementsAre(P1, P2));
- EXPECT_THAT(getSubsetOf(Set, E2), UnorderedElementsAre(P3, P4));
- EXPECT_THAT(getSubsetOf(Set, E3), UnorderedElementsAre(P5));
-}
-
-//////////////////////////////////////////////////////////////
-// Extractor Tests //
-//////////////////////////////////////////////////////////////
-
-TEST_F(UnsafeBufferUsageTest, SimpleFunctionWithUnsafePointer) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p) {
- p[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, PointerArithmetic) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p, int *q) {
- *(p + 5);
- *(q - 3);
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, PointerIncrementDecrement) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p, int *q, int *r, int *s) {
- (++p)[5];
- (q++)[5];
- (--r)[5];
- (s--)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum,
- makeSet(__LINE__, {{"p", 1U}, {"q", 1U}, {"r", 1U}, {"s", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, PointerAssignment) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p, int *q) {
- (p = q + 5)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, CompoundAssignment) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p, int *q) {
- (p += 5)[5];
- (q -= 3)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, MultiLevelPointer) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int **p, int **q, int **r) {
- (*p)[5];
- *(*q);
- *(q[5]);
- r[5][5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum,
- makeSet(__LINE__, {{"p", 2U}, {"q", 1U}, {"r", 1U}, {"r", 2U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, ConditionalOperator) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int **p, int **q, int cond) {
- (cond ? *p : *q)[5];
- cond ? p[5] : q[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum,
- makeSet(__LINE__, {{"p", 1U}, {"q", 1U}, {"p", 2U}, {"q", 2U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, CastExpression) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(void *p, int q) {
- ((int*)p)[5];
- ((int*)q)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, CommaOperator) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p, int x) {
- (x++, p)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, CommaOperator2) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int **p, int **q, int x) {
- (p[x] = 0, q[x] = 0)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}, {"q", 2U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, ParenthesizedExpression) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p) {
- (((p)))[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, ArrayParameter) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int arr[], int arr2[][10]) {
- int n = 5;
- arr[100];
- arr2[5][n];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"arr", 1U}, {"arr2", 1U}, {"arr2", 2U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, FunctionCall) {
- ASSERT_TRUE(setUpTest(R"cpp(
- int ** (*fp)();
- int ** foo() {
- fp = &foo;
- foo()[5];
- (*fp())[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- // No (foo, 2) because indirect calls are ignored.
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"foo", 1U, true}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, StructMemberAccess) {
- ASSERT_TRUE(setUpTest(R"cpp(
- struct S {
- int *ptr;
- int (*ptr_to_arr)[10];
- };
- void foo(struct S obj) {
- int n = 5;
- obj.ptr[5];
- (*obj.ptr_to_arr)[n];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"ptr", 1U}, {"ptr_to_arr", 2U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, StringLiteralSubscript) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo() {
- "hello"[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- // String literals should not generate pointer kind variables
- EXPECT_EQ(Sum, nullptr);
-}
-
-TEST_F(UnsafeBufferUsageTest, OpaqueValueExpr) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p, int *q) {
- (p ?: q)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, AddressOfOperator) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int x) {
- (&x)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
- // Address-of should not generate pointer kind variables for 'x':
- EXPECT_EQ(Sum, nullptr);
-}
-
-TEST_F(UnsafeBufferUsageTest, AddressOfThenDereference) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p, int *q) {
- (*(&p))[5];
- (&(*q))[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1}, {"q", 1}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, PointerToArrayOfPointers) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo() {
- int * arr[10];
- int * (*p)[10] = &arr;
-
- (*p)[5][5]; // '(*p)[5]' is unsafe
- // '(*p)' is fine because 5 < 10
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 3}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, UnsafePointerInGlobalVariableInitializer) {
- ASSERT_TRUE(setUpTest(R"cpp(
- int *gp;
- int x = gp[5];
- )cpp"));
- const auto *Sum = getEntitySummary("x");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, UnsafePointerInFieldInitializer) {
- ASSERT_TRUE(setUpTest(R"cpp(
- int *gp;
- struct Foo {
- int field = gp[5];
- };
- )cpp"));
- const auto *Sum = getEntitySummary("Foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, UnsafePointerInFieldInitializer2) {
- ASSERT_TRUE(setUpTest(R"cpp(
- int *gp;
- union Foo {
- int field = gp[5];
- int x;
- };
- )cpp"));
- const auto *Sum = getEntitySummary("Foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, InitializerList) {
- ASSERT_TRUE(setUpTest(R"cpp(
- int *gp;
- struct Foo {
- int field;
- int x;
- };
- Foo FooObj{gp[5], 0};
- )cpp"));
- const auto *Sum = getEntitySummary("FooObj");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, UnsafePointerInCXXCtorInitializer) {
- ASSERT_TRUE(setUpTest(R"cpp(
- struct Foo {
- int member;
- Foo(int *p) : member(p[5]) {}
- };
- )cpp"));
- const auto *Sum = getEntitySummary<CXXConstructorDecl>("Foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, UnsafePointerInDefaultArg) {
- ASSERT_TRUE(setUpTest(R"cpp(
- int * gp;
- void foo(int x = gp[5]);
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, NestedDefinitions) {
- ASSERT_TRUE(setUpTest(R"cpp(
- int * a = [](){
- struct Foo {
- void bar(int * ptr) { ptr[3] = 0; }
- };
- return nullptr;
- }();
- )cpp"));
- const auto *Sum = getEntitySummary("bar");
-
- EXPECT_NE(Sum, nullptr);
- // The closest contributor owns the fact:
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"ptr", 1U}}));
-
- Sum = getEntitySummary("Foo");
-
- EXPECT_EQ(Sum, nullptr);
-
- Sum = getEntitySummary("a");
-
- EXPECT_EQ(Sum, nullptr);
-}
-
-TEST_F(UnsafeBufferUsageTest, NestedDefinitions2) {
- bool SetupSuccess = setUpTest(R"cpp(
- int main(void) {
- struct Foo {
- void bar(int * ptr) { ptr[3] = 0; }
- };
- }
- )cpp");
-
- ASSERT_TRUE(SetupSuccess);
-
- const auto *Sum = getEntitySummary("bar");
-
- EXPECT_NE(Sum, nullptr);
- // The closest contributor owns the fact:
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"ptr", 1U}}));
-
- Sum = getEntitySummary("Foo");
-
- EXPECT_EQ(Sum, nullptr);
-
- Sum = getEntitySummary("main");
-
- EXPECT_EQ(Sum, nullptr);
-}
-
-TEST_F(UnsafeBufferUsageTest, UnaryPlusSubscript) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int *p) {
- (+p)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, PredefinedExprSubscript) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo() {
- __func__[100];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_EQ(Sum, nullptr);
-}
-
-TEST_F(UnsafeBufferUsageTest, IntegerLiteralCastSubscript) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo() {
- ((int *)0)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_EQ(Sum, nullptr);
-}
-
-TEST_F(UnsafeBufferUsageTest, CXXNewArraySubscript) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo() {
- (new int[10])[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_EQ(Sum, nullptr);
-}
-
-TEST_F(UnsafeBufferUsageTest, CXXNullPtrSubscript) {
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo() {
- ((int*)nullptr)[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_EQ(Sum, nullptr);
-}
-
-TEST_F(UnsafeBufferUsageTest, CXXThisSubscript) {
- ASSERT_TRUE(setUpTest(R"cpp(
- struct S {
- void foo() {
- this[5];
- }
- };
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_EQ(Sum, nullptr);
-}
-
-TEST_F(UnsafeBufferUsageTest, ExprWithCleanupsSubscript) {
- ASSERT_TRUE(setUpTest(R"cpp(
- struct Guard { ~Guard(); };
- int *getPtr(Guard);
- void foo() {
- getPtr(Guard{})[5];
- }
- )cpp"));
- const auto *Sum = getEntitySummary("foo");
-
- EXPECT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"getPtr", 1U, true}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, MaterializeTemporaryExpr) {
- ASSERT_EQ(setUpTest(R"cpp(
- struct S { int *get(); };
- void foo(int *p) {
- S{}.get()[5];
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"get", 1U, true}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, CXXScalarValueInitExpr) {
- ASSERT_EQ(setUpTest(R"cpp(
- using IntPtr = int*;
-
- void foo(int *q) {
- int p = IntPtr()[5]; // no EPL created for CXXScalarValueInitExpr
- q[5];
- }
- )cpp"),
- true);
-
- auto *Sum = getEntitySummary("foo");
-
- ASSERT_NE(Sum, nullptr);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"q", 1U}}));
-}
-
-//////////////////////////////////////////////////////////////
-// Template is ignored but instantiations are visited. //
-//////////////////////////////////////////////////////////////
-
-TEST_F(UnsafeBufferUsageTest, FunctionTemplate) {
- ASSERT_TRUE(setUpTest(R"cpp(
- template <typename T>
- T* f(T *p) {
- return &p[5];
- }
- )cpp"));
- ASSERT_FALSE(findDeclByName("f", AST->getASTContext()));
-}
-
-TEST_F(UnsafeBufferUsageTest, MethodInClassTemplate) {
- ASSERT_TRUE(setUpTest(R"cpp(
- template <typename T>
- struct Wrapper {
- T *ptr;
- void set(T *p) { ptr = p[5]; }
- };
- )cpp"));
- ASSERT_FALSE(findDeclByName("set", AST->getASTContext()));
-}
-
-TEST_F(UnsafeBufferUsageTest, FunctionTemplateInstantiation) {
- ASSERT_TRUE(setUpTest(R"cpp(
- template<typename T>
- void unsafe(T p) {
- p[1] = p[2] + p[3];
- }
-
- void f(int *p) {
- unsafe(p);
- }
- )cpp"));
-
- auto *Sum = getEntitySummary("unsafe");
-
- ASSERT_TRUE(Sum);
- ASSERT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
-}
-
-TEST_F(UnsafeBufferUsageTest, MethodInClassTemplateInstantiation) {
- ASSERT_TRUE(setUpTest(R"cpp(
- template<typename T>
- struct UnsafeClass {
- T p;
- void unsafe_method() {
- p[1] = p[2] + p[3];
- }
- };
-
- void f(int *p) {
- UnsafeClass<int *> UC;
-
- UC.unsafe_method();
- }
- )cpp"));
-
- auto *Sum = getEntitySummary("unsafe_method");
-
- ASSERT_TRUE(Sum);
- EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
-}
-// Robustness test: unsupported constructs will not cause crash
-#ifndef NDEBUG
-TEST_F(UnsafeBufferUsageTest, StmtExprArrayAccess) {
- // GNU statement expressions are not supported, but should not crash and
- // should log a warning.
- llvm::SaveAndRestore<bool> DebugFlag(llvm::DebugFlag, true);
-
- llvm::setCurrentDebugType("ssaf-analyses");
- testing::internal::CaptureStderr();
-
- ASSERT_TRUE(setUpTest(R"cpp(
- void foo(int i) {
- ({ int *p = 0; p; })[i];
- }
- )cpp"));
-
- // The only unsafe pointer is unsupported, so no summary should be produced.
- ASSERT_FALSE(getEntitySummary("foo"));
- // Verify the warning was logged
- EXPECT_TRUE(
- StringRef(testing::internal::GetCapturedStderr())
- .contains("attempt to translate StmtExpr to EntityPointerLevels"));
-}
-#endif
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp
deleted file mode 100644
index 80f09f9765fe1..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-//===- UnsafeBufferUsageWPATest.cpp ---------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <memory>
-
-using namespace clang;
-using namespace ssaf;
-using testing::IsEmpty;
-using testing::UnorderedElementsAre;
-
-UnsafeBufferUsageEntitySummary
-ssaf::buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers);
-
-namespace {
-
-class UnsafeBufferUsageWPATest : public TestFixture {
-protected:
- static constexpr EntityLinkage ExternalLinkage =
- EntityLinkage(EntityLinkageType::External);
-
- std::unique_ptr<LUSummary> makeLUSummary() {
- NestedBuildNamespace NS(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
- return std::make_unique<LUSummary>(llvm::Triple("arm64-apple-macosx"),
- std::move(NS));
- }
-
- EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
- NestedBuildNamespace NS(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
- EntityName Name(USR.str(), "", NS);
- EntityId Id = getIdTable(LU).getId(Name);
- getLinkageTable(LU).insert({Id, ExternalLinkage});
- return Id;
- }
-
- void insertSummary(LUSummary &LU, EntityId Id, EntityPointerLevelSet EPLs) {
- getData(LU)[UnsafeBufferUsageEntitySummary::summaryName()][Id] =
- std::make_unique<UnsafeBufferUsageEntitySummary>(
- buildUnsafeBufferUsageEntitySummary(std::move(EPLs)));
- }
-
- const UnsafeBufferUsageAnalysisResult &
- runAnalysisForResult(std::unique_ptr<LUSummary> LU) {
- AnalysisDriver Driver(std::move(LU));
- auto WPAOrErr = Driver.run<UnsafeBufferUsageAnalysisResult>();
- EXPECT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
- WPA = std::move(*WPAOrErr);
- auto ROrErr = WPA.get<UnsafeBufferUsageAnalysisResult>();
- EXPECT_THAT_EXPECTED(ROrErr, llvm::Succeeded());
- return *ROrErr;
- }
-
-private:
- WPASuite WPA = makeWPASuite();
-};
-
-TEST_F(UnsafeBufferUsageWPATest, SingleEntitySummary) {
- auto LU = makeLUSummary();
- EntityId Foo = addEntity(*LU, "c:@F at foo");
- EntityId P = addEntity(*LU, "c:@F at foo@p");
-
- EntityPointerLevelSet EPLs{buildEntityPointerLevel(P, 1),
- buildEntityPointerLevel(P, 2),
- buildEntityPointerLevel(P, 3)};
- insertSummary(*LU, Foo, EPLs);
-
- const auto &R = runAnalysisForResult(std::move(LU));
-
- ASSERT_EQ(R.UnsafeBuffers.count(Foo), 1u);
- EXPECT_THAT(R.UnsafeBuffers.at(Foo),
- UnorderedElementsAre(buildEntityPointerLevel(P, 1),
- buildEntityPointerLevel(P, 2),
- buildEntityPointerLevel(P, 3)));
-}
-
-TEST_F(UnsafeBufferUsageWPATest, MultiEntitySummaries) {
- auto LU = makeLUSummary();
- EntityId Foo = addEntity(*LU, "c:@F at foo");
- EntityId Bar = addEntity(*LU, "c:@F at bar");
- EntityId P = addEntity(*LU, "c:@F at foo@p");
- EntityId Q = addEntity(*LU, "c:@F at bar@q");
-
- insertSummary(*LU, Foo,
- {buildEntityPointerLevel(P, 1), buildEntityPointerLevel(P, 2),
- buildEntityPointerLevel(P, 3)});
- insertSummary(*LU, Bar,
- {buildEntityPointerLevel(Q, 1), buildEntityPointerLevel(Q, 2)});
-
- const auto &R = runAnalysisForResult(std::move(LU));
-
- EXPECT_EQ(R.UnsafeBuffers.size(), 2u);
- EXPECT_THAT(R.UnsafeBuffers.at(Foo),
- UnorderedElementsAre(buildEntityPointerLevel(P, 1),
- buildEntityPointerLevel(P, 2),
- buildEntityPointerLevel(P, 3)));
- EXPECT_THAT(R.UnsafeBuffers.at(Bar),
- UnorderedElementsAre(buildEntityPointerLevel(Q, 1),
- buildEntityPointerLevel(Q, 2)));
-}
-
-TEST_F(UnsafeBufferUsageWPATest, EmptySummary) {
- auto LU = makeLUSummary();
- EntityId Foo = addEntity(*LU, "c:@F at foo");
-
- insertSummary(*LU, Foo, {});
-
- const auto &R = runAnalysisForResult(std::move(LU));
-
- ASSERT_EQ(R.UnsafeBuffers.count(Foo), 1u);
- EXPECT_THAT(R.UnsafeBuffers.at(Foo), IsEmpty());
-}
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/BuildNamespaceTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/BuildNamespaceTest.cpp
deleted file mode 100644
index 0fe8bb6f18122..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/BuildNamespaceTest.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-//===- BuildNamespaceTest.cpp ---------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-
-namespace clang::ssaf {
-namespace {
-
-TEST(BuildNamespaceTest, Equality) {
- auto BN1 = BuildNamespace::makeCompilationUnit("test.cpp");
- auto BN2 = BuildNamespace::makeCompilationUnit("test.cpp");
- auto BN3 = BuildNamespace::makeCompilationUnit("other.cpp");
-
- EXPECT_EQ(BN1, BN2);
- EXPECT_NE(BN1, BN3);
-}
-
-TEST(BuildNamespaceTest, DifferentKinds) {
- BuildNamespace CU(BuildNamespaceKind::CompilationUnit, "test");
- BuildNamespace LU(BuildNamespaceKind::LinkUnit, "test");
-
- EXPECT_NE(CU, LU);
-}
-
-// NestedBuildNamespace Tests
-
-TEST(NestedBuildNamespaceTest, DefaultConstruction) {
- NestedBuildNamespace NBN;
- EXPECT_TRUE(NBN.empty());
-}
-
-TEST(NestedBuildNamespaceTest, SingleNamespaceConstruction) {
- auto BN = BuildNamespace::makeCompilationUnit("test.cpp");
- NestedBuildNamespace NBN(BN);
-
- EXPECT_FALSE(NBN.empty());
-}
-
-TEST(NestedBuildNamespaceTest, MakeTU) {
- auto NBN = NestedBuildNamespace::makeCompilationUnit("test.cpp");
- EXPECT_FALSE(NBN.empty());
-}
-
-TEST(NestedBuildNamespaceTest, Equality) {
- auto NBN1 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
- auto NBN2 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
- auto NBN3 = NestedBuildNamespace::makeCompilationUnit("other.cpp");
-
- EXPECT_EQ(NBN1, NBN2);
- EXPECT_NE(NBN1, NBN3);
-}
-
-TEST(NestedBuildNamespaceTest, MakeQualified) {
- auto NBN1 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
- BuildNamespace LinkNS(BuildNamespaceKind::LinkUnit, "app");
- NestedBuildNamespace NBN2(LinkNS);
-
- auto Qualified = NBN1.makeQualified(NBN2);
-
- EXPECT_NE(Qualified, NBN1);
- EXPECT_NE(Qualified, NBN2);
-}
-
-TEST(NestedBuildNamespaceTest, EmptyQualified) {
- NestedBuildNamespace Empty;
- auto NBN = NestedBuildNamespace::makeCompilationUnit("test.cpp");
-
- auto Qualified = Empty.makeQualified(NBN);
- EXPECT_EQ(Qualified, NBN);
-}
-
-TEST(BuildNamespaceKindTest, FormatProvider) {
- EXPECT_EQ(llvm::formatv("{0}", BuildNamespaceKind::CompilationUnit).str(),
- "CompilationUnit");
- EXPECT_EQ(llvm::formatv("{0}", BuildNamespaceKind::LinkUnit).str(),
- "LinkUnit");
-}
-
-TEST(BuildNamespaceKindTest, StreamOutputCompilationUnit) {
- std::string S;
- llvm::raw_string_ostream(S) << BuildNamespaceKind::CompilationUnit;
- EXPECT_EQ(S, "CompilationUnit");
-}
-
-TEST(BuildNamespaceKindTest, StreamOutputLinkUnit) {
- std::string S;
- llvm::raw_string_ostream(S) << BuildNamespaceKind::LinkUnit;
- EXPECT_EQ(S, "LinkUnit");
-}
-
-TEST(BuildNamespaceTest, FormatProvider) {
- EXPECT_EQ(
- llvm::formatv("{0}", BuildNamespace(BuildNamespaceKind::CompilationUnit,
- "test.cpp"))
- .str(),
- "BuildNamespace(CompilationUnit, test.cpp)");
-}
-
-TEST(NestedBuildNamespaceTest, FormatProvider) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
- EXPECT_EQ(
- llvm::formatv("{0}", NBN).str(),
- "NestedBuildNamespace([BuildNamespace(CompilationUnit, test.cpp)])");
-}
-
-TEST(BuildNamespaceTest, StreamOutputCompilationUnit) {
- BuildNamespace BN(BuildNamespaceKind::CompilationUnit, "test.cpp");
- std::string S;
- llvm::raw_string_ostream(S) << BN;
- EXPECT_EQ(S, "BuildNamespace(CompilationUnit, test.cpp)");
-}
-
-TEST(BuildNamespaceTest, StreamOutputLinkUnit) {
- BuildNamespace BN(BuildNamespaceKind::LinkUnit, "app");
- std::string S;
- llvm::raw_string_ostream(S) << BN;
- EXPECT_EQ(S, "BuildNamespace(LinkUnit, app)");
-}
-
-TEST(NestedBuildNamespaceTest, StreamOutputEmpty) {
- NestedBuildNamespace NBN;
- std::string S;
- llvm::raw_string_ostream(S) << NBN;
- EXPECT_EQ(S, "NestedBuildNamespace([])");
-}
-
-TEST(NestedBuildNamespaceTest, StreamOutputSingle) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
- std::string S;
- llvm::raw_string_ostream(S) << NBN;
- EXPECT_EQ(
- S, "NestedBuildNamespace([BuildNamespace(CompilationUnit, test.cpp)])");
-}
-
-TEST(NestedBuildNamespaceTest, StreamOutputMultiple) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
- NBN = NBN.makeQualified(NestedBuildNamespace(
- BuildNamespace(BuildNamespaceKind::LinkUnit, "app")));
- std::string S;
- llvm::raw_string_ostream(S) << NBN;
- EXPECT_EQ(S, "NestedBuildNamespace([BuildNamespace(CompilationUnit, "
- "test.cpp), BuildNamespace(LinkUnit, app)])");
-}
-
-} // namespace
-} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt b/clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt
deleted file mode 100644
index 216fa1cf2b8b8..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/CMakeLists.txt
+++ /dev/null
@@ -1,56 +0,0 @@
-add_distinct_clang_unittest(ClangScalableAnalysisTests
- Analyses/PointerFlow/PointerFlowTest.cpp
- Analyses/PointerFlow/PointerFlowWPATest.cpp
- Analyses/CallGraph/CallGraphExtractorTest.cpp
- Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
- Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp
- ASTEntityMappingTest.cpp
- BuildNamespaceTest.cpp
- EntityIdTableTest.cpp
- EntityIdTest.cpp
- EntityLinkageTest.cpp
- EntityLinkerTest.cpp
- EntityNameTest.cpp
- ErrorBuilderTest.cpp
- Frontend/TUSummaryExtractorFrontendActionTest.cpp
- LUSummaryTest.cpp
- ModelStringConversionsTest.cpp
- Registries/FancyAnalysisData.cpp
- Registries/MockSerializationFormat.cpp
- Registries/MockSummaryExtractor1.cpp
- Registries/MockSummaryExtractor2.cpp
- Registries/SerializationFormatRegistryTest.cpp
- Registries/SummaryExtractorRegistryTest.cpp
- Serialization/JSONFormatTest/JSONFormatTest.cpp
- Serialization/JSONFormatTest/LUSummaryTest.cpp
- Serialization/JSONFormatTest/TUSummaryTest.cpp
- SourceTransformation/EmitterTest.cpp
- SourceTransformation/RegistryTest.cpp
- SummaryData/SummaryDataTest.cpp
- SummaryNameTest.cpp
- TestFixture.cpp
- TUSummaryBuilderTest.cpp
- WholeProgramAnalysis/AnalysisDriverTest.cpp
- WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp
-
- CLANG_LIBS
- clangAST
- clangASTMatchers
- clangBasic
- clangFrontend
- clangScalableStaticAnalysisFrameworkAnalyses
- clangScalableStaticAnalysisFrameworkCore
- clangScalableStaticAnalysisFrameworkFrontend
- clangScalableStaticAnalysisFrameworkSourceTransformation
- clangSerialization
- clangTooling
- clangToolingCore
-
- LINK_LIBS
- LLVMTestingSupport
-
- LLVM_COMPONENTS
- FrontendOpenMP
- Support
- TargetParser
- )
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTableTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTableTest.cpp
deleted file mode 100644
index 7afa4943bcb79..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTableTest.cpp
+++ /dev/null
@@ -1,142 +0,0 @@
-//===- EntityIdTableTest.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "gtest/gtest.h"
-
-namespace clang {
-namespace ssaf {
-namespace {
-
-TEST(EntityIdTableTest, CreateNewEntity) {
- EntityIdTable Table;
-
- EntityName Entity("c:@F at foo", "", {});
- Table.getId(Entity);
-
- EXPECT_TRUE(Table.contains(Entity));
-}
-
-TEST(EntityIdTableTest, Idempotency) {
- EntityIdTable Table;
-
- EntityName Entity("c:@F at foo", "", {});
- EntityName EntityCopy = Entity;
-
- EntityId Id1 = Table.getId(Entity);
- EntityId Id2 = Table.getId(Entity);
- EntityId Id3 = Table.getId(EntityCopy);
-
- EXPECT_EQ(Id1, Id2);
- EXPECT_EQ(Id2, Id3);
- EXPECT_EQ(Id1, Id3);
-}
-
-TEST(EntityIdTableTest, ExistsTrue) {
- EntityIdTable Table;
-
- EntityName Entity1("c:@F at foo", "", {});
- EntityName Entity2("c:@V at bar", "", {});
-
- Table.getId(Entity1);
- Table.getId(Entity2);
-
- EXPECT_TRUE(Table.contains(Entity1));
- EXPECT_TRUE(Table.contains(Entity2));
-}
-
-TEST(EntityIdTableTest, ExistsFalse) {
- EntityIdTable Table;
-
- EntityName Entity1("c:@F at foo", "", {});
- EntityName Entity2("c:@F at bar", "", {});
-
- Table.getId(Entity1);
-
- EXPECT_TRUE(Table.contains(Entity1));
- EXPECT_FALSE(Table.contains(Entity2));
-}
-
-TEST(EntityIdTableTest, MultipleEntities) {
- EntityIdTable Table;
-
- EntityName Entity1("c:@F at foo", "", {});
- EntityName Entity2("c:@F at bar", "", {});
- EntityName Entity3("c:@V at baz", "", {});
-
- EntityId Id1 = Table.getId(Entity1);
- EntityId Id2 = Table.getId(Entity2);
- EntityId Id3 = Table.getId(Entity3);
-
- EXPECT_NE(Id1, Id2);
- EXPECT_NE(Id1, Id3);
- EXPECT_NE(Id2, Id3);
-}
-
-TEST(EntityIdTableTest, WithBuildNamespace) {
- EntityIdTable Table;
-
- NestedBuildNamespace NS = NestedBuildNamespace::makeCompilationUnit("test.o");
-
- EntityName Entity1("c:@F at foo", "", NS);
- EntityName Entity2("c:@F at foo", "",
- NestedBuildNamespace::makeCompilationUnit("other.o"));
-
- EntityId Id1 = Table.getId(Entity1);
- EntityId Id2 = Table.getId(Entity2);
-
- EXPECT_NE(Id1, Id2);
-}
-
-TEST(EntityIdTableTest, ForEachEmptyTable) {
- EntityIdTable Table;
-
- int CallbackCount = 0;
- Table.forEach(
- [&CallbackCount](const EntityName &, EntityId) { CallbackCount++; });
-
- EXPECT_EQ(CallbackCount, 0);
-}
-
-TEST(EntityIdTableTest, ForEachMultipleEntities) {
- EntityIdTable Table;
-
- EntityName Entity1("c:@F at foo", "", {});
- EntityName Entity2("c:@F at bar", "", {});
- EntityName Entity3("c:@V at baz", "", {});
-
- EntityId Id1 = Table.getId(Entity1);
- EntityId Id2 = Table.getId(Entity2);
- EntityId Id3 = Table.getId(Entity3);
-
- std::set<EntityId> VisitedIds;
- std::set<EntityName> VisitedNames;
-
- Table.forEach([&](const EntityName &Name, EntityId Id) {
- VisitedIds.insert(Id);
- VisitedNames.insert(Name);
- });
-
- EXPECT_EQ(VisitedIds.size(), 3u);
- EXPECT_EQ(VisitedNames.size(), 3u);
-
- EXPECT_TRUE(VisitedIds.count(Id1));
- EXPECT_TRUE(VisitedIds.count(Id2));
- EXPECT_TRUE(VisitedIds.count(Id3));
-
- EXPECT_TRUE(VisitedNames.count(Entity1));
- EXPECT_TRUE(VisitedNames.count(Entity2));
- EXPECT_TRUE(VisitedNames.count(Entity3));
-}
-
-} // namespace
-} // namespace ssaf
-} // namespace clang
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTest.cpp
deleted file mode 100644
index 9a07aed13a432..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/EntityIdTest.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-//===- EntityIdTest.cpp ---------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-#include <cctype>
-
-namespace clang::ssaf {
-namespace {
-
-static bool isNonNegativeInteger(llvm::StringRef S) {
- return !S.empty() &&
- llvm::all_of(S, [](unsigned char C) { return std::isdigit(C); });
-}
-
-TEST(EntityIdTest, Equality) {
- EntityIdTable Table;
-
- EntityName Entity1("c:@F at foo", "", {});
- EntityName Entity2("c:@F at bar", "", {});
-
- EntityId Id1 = Table.getId(Entity1);
- EntityId Id2 = Table.getId(Entity2);
- EntityId Id1Copy = Table.getId(Entity1);
-
- EXPECT_EQ(Id1, Id1Copy);
- EXPECT_FALSE(Id1 != Id1Copy);
- EXPECT_FALSE(Id1 < Id1Copy);
- EXPECT_FALSE(Id1Copy < Id1);
-
- EXPECT_NE(Id1, Id2);
- EXPECT_FALSE(Id1 == Id2);
- EXPECT_TRUE(Id1 < Id2 || Id2 < Id1);
-}
-
-TEST(EntityIdTest, LessThan) {
- EntityIdTable Table;
-
- EntityName Entity1("c:@F at aaa", "", {});
- EntityName Entity2("c:@F at bbb", "", {});
-
- EntityId Id1 = Table.getId(Entity1);
- EntityId Id2 = Table.getId(Entity2);
-
- EXPECT_TRUE(Id1 < Id2 || Id2 < Id1);
-}
-
-TEST(EntityIdTest, Transitivity) {
- EntityIdTable Table;
-
- EntityName Entity1("c:@F at xxx", "", {});
- EntityName Entity2("c:@F at yyy", "", {});
- EntityName Entity3("c:@F at zzz", "", {});
-
- EntityId Ids[3] = {Table.getId(Entity1), Table.getId(Entity2),
- Table.getId(Entity3)};
-
- std::sort(Ids, Ids + 3);
-
- EXPECT_TRUE(Ids[0] < Ids[1] && Ids[1] < Ids[2]);
-}
-
-TEST(EntityIdTest, FormatProvider) {
- EntityIdTable Table;
- EntityName Entity("c:@F at foo", "", {});
- EntityId Id = Table.getId(Entity);
-
- std::string S = llvm::formatv("{0}", Id).str();
- llvm::StringRef Ref(S);
- ASSERT_TRUE(Ref.consume_front("EntityId("));
- ASSERT_TRUE(Ref.consume_back(")"));
- EXPECT_TRUE(isNonNegativeInteger(Ref));
-}
-
-TEST(EntityIdTest, StreamOutput) {
- EntityIdTable Table;
- EntityName Entity("c:@F at foo", "", {});
- EntityId Id = Table.getId(Entity);
-
- std::string S;
- llvm::raw_string_ostream(S) << Id;
-
- llvm::StringRef Ref(S);
- ASSERT_TRUE(Ref.consume_front("EntityId("));
- ASSERT_TRUE(Ref.consume_back(")"));
- EXPECT_TRUE(isNonNegativeInteger(Ref));
-}
-
-} // namespace
-} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkageTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkageTest.cpp
deleted file mode 100644
index a435f2f2c8974..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkageTest.cpp
+++ /dev/null
@@ -1,117 +0,0 @@
-//===- EntityLinkageTest.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-
-using clang::ssaf::EntityLinkage;
-using clang::ssaf::EntityLinkageType;
-
-namespace {
-
-constexpr inline auto None = EntityLinkageType::None;
-constexpr inline auto Internal = EntityLinkageType::Internal;
-constexpr inline auto External = EntityLinkageType::External;
-
-TEST(EntityLinkageTest, Constructor) {
- EntityLinkage NoneLinkage(None);
- EntityLinkage InternalLinkage(Internal);
- EntityLinkage ExternalLinkage(External);
-
- EXPECT_EQ(NoneLinkage.getLinkage(), None);
- EXPECT_EQ(InternalLinkage.getLinkage(), Internal);
- EXPECT_EQ(ExternalLinkage.getLinkage(), External);
-}
-
-TEST(EntityLinkageTest, CopyConstructor) {
- EntityLinkage Original(External);
- EntityLinkage Copy = Original;
-
- EXPECT_EQ(Copy.getLinkage(), External);
- EXPECT_EQ(Copy.getLinkage(), Original.getLinkage());
-}
-
-TEST(EntityLinkageTest, AssignmentOperator) {
- EntityLinkage Linkage1(None);
- EntityLinkage Linkage2(External);
-
- Linkage1 = Linkage2;
-
- EXPECT_EQ(Linkage1.getLinkage(), External);
- EXPECT_EQ(Linkage1.getLinkage(), Linkage2.getLinkage());
-}
-
-TEST(EntityLinkageTest, EqualityOperatorReflexive) {
- EXPECT_EQ(EntityLinkage(None), EntityLinkage(None));
- EXPECT_EQ(EntityLinkage(Internal), EntityLinkage(Internal));
- EXPECT_EQ(EntityLinkage(External), EntityLinkage(External));
-}
-
-TEST(EntityLinkageTest, EqualityOperatorDistinct) {
- EXPECT_NE(EntityLinkage(None), EntityLinkage(Internal));
- EXPECT_NE(EntityLinkage(None), EntityLinkage(External));
- EXPECT_NE(EntityLinkage(Internal), EntityLinkage(External));
-}
-
-TEST(EntityLinkageTypeTest, FormatProvider) {
- EXPECT_EQ(llvm::formatv("{0}", EntityLinkageType::None).str(), "None");
- EXPECT_EQ(llvm::formatv("{0}", EntityLinkageType::Internal).str(),
- "Internal");
- EXPECT_EQ(llvm::formatv("{0}", EntityLinkageType::External).str(),
- "External");
-}
-
-TEST(EntityLinkageTypeTest, StreamOutputNone) {
- std::string S;
- llvm::raw_string_ostream(S) << EntityLinkageType::None;
- EXPECT_EQ(S, "None");
-}
-
-TEST(EntityLinkageTypeTest, StreamOutputInternal) {
- std::string S;
- llvm::raw_string_ostream(S) << EntityLinkageType::Internal;
- EXPECT_EQ(S, "Internal");
-}
-
-TEST(EntityLinkageTypeTest, StreamOutputExternal) {
- std::string S;
- llvm::raw_string_ostream(S) << EntityLinkageType::External;
- EXPECT_EQ(S, "External");
-}
-
-TEST(EntityLinkageTest, FormatProvider) {
- EXPECT_EQ(llvm::formatv("{0}", EntityLinkage(None)).str(),
- "EntityLinkage(None)");
- EXPECT_EQ(llvm::formatv("{0}", EntityLinkage(Internal)).str(),
- "EntityLinkage(Internal)");
- EXPECT_EQ(llvm::formatv("{0}", EntityLinkage(External)).str(),
- "EntityLinkage(External)");
-}
-
-TEST(EntityLinkageTest, StreamOutputNone) {
- std::string S;
- llvm::raw_string_ostream(S) << EntityLinkage(None);
- EXPECT_EQ(S, "EntityLinkage(None)");
-}
-
-TEST(EntityLinkageTest, StreamOutputInternal) {
- std::string S;
- llvm::raw_string_ostream(S) << EntityLinkage(Internal);
- EXPECT_EQ(S, "EntityLinkage(Internal)");
-}
-
-TEST(EntityLinkageTest, StreamOutputExternal) {
- std::string S;
- llvm::raw_string_ostream(S) << EntityLinkage(External);
- EXPECT_EQ(S, "EntityLinkage(External)");
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkerTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkerTest.cpp
deleted file mode 100644
index a3759703a48b3..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/EntityLinkerTest.cpp
+++ /dev/null
@@ -1,667 +0,0 @@
-//===- EntityLinkerTest.cpp -----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntityLinker.h"
-#include "TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/EntitySummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <memory>
-
-using namespace clang::ssaf;
-using namespace llvm;
-using ::testing::HasSubstr;
-using ::testing::Not;
-using ::testing::PrintToString;
-
-namespace {
-
-class MockEntitySummaryEncoding : public EntitySummaryEncoding {
-public:
- MockEntitySummaryEncoding() : Id(++Index) {}
-
- size_t getId() const { return Id; }
-
- llvm::Error
- patch(const std::map<EntityId, EntityId> &EntityResolutionTable) override {
- PatchedIds = EntityResolutionTable;
- return llvm::Error::success();
- }
-
- const std::map<EntityId, EntityId> &getPatchedIds() const {
- return PatchedIds;
- }
-
- static size_t Index;
-
-private:
- size_t Id;
- std::map<EntityId, EntityId> PatchedIds;
-};
-
-size_t MockEntitySummaryEncoding::Index = 0;
-
-class EntityLinkerTest : public TestFixture {
-protected:
- static constexpr EntityLinkage NoneLinkage =
- EntityLinkage(EntityLinkageType::None);
- static constexpr EntityLinkage InternalLinkage =
- EntityLinkage(EntityLinkageType::Internal);
- static constexpr EntityLinkage ExternalLinkage =
- EntityLinkage(EntityLinkageType::External);
-
- void SetUp() override {
- // This ensures that the MockEntitySummary id assignment does not
- // accidentally depend on test execution order.
- MockEntitySummaryEncoding::Index = 0;
- }
-
- std::unique_ptr<TUSummaryEncoding> createTUSummaryEncoding(
- BuildNamespaceKind Kind, llvm::StringRef Name,
- llvm::Triple TargetTriple = llvm::Triple("arm64-apple-macosx")) {
- return std::make_unique<TUSummaryEncoding>(std::move(TargetTriple),
- BuildNamespace(Kind, Name));
- }
-
- size_t addSummaryData(TUSummaryEncoding &TU, EntityId EId,
- llvm::StringRef SummaryNameStr) {
- SummaryName SN(SummaryNameStr.str());
- auto Summary = std::make_unique<MockEntitySummaryEncoding>();
- const size_t ESId = Summary->getId();
- getData(TU)[SN][EId] = std::move(Summary);
- return ESId;
- }
-
- EntityId addEntity(TUSummaryEncoding &TU, llvm::StringRef USR,
- EntityLinkage Linkage) {
- EntityName Name(USR, "", NestedBuildNamespace());
- EntityId Id = getIdTable(TU).getId(Name);
- getLinkageTable(TU).insert({Id, Linkage});
- return Id;
- }
-};
-
-// ============================================================================
-// Entity ID Table Matchers
-// ============================================================================
-
-MATCHER_P(ContainsEntity, EntityName,
- std::string(negation ? "does not contain" : "contains") +
- " entity '" + PrintToString(EntityName) + "'") {
- return arg.contains(EntityName);
-}
-
-MATCHER_P(IdTableHasSize, ExpectedCount,
- std::string("has ") + PrintToString(ExpectedCount) + " entities") {
- if (arg.count() != ExpectedCount) {
- *result_listener << "has " << arg.count() << " entities";
- return false;
- }
- return true;
-}
-
-// ============================================================================
-// Linkage Table Matchers
-// ============================================================================
-
-MATCHER_P2(EntityHasLinkage, EId, ExpectedLinkage,
- std::string("entity has ") + PrintToString(ExpectedLinkage) +
- " linkage") {
- auto It = arg.find(EId);
- if (It == arg.end()) {
- *result_listener << "entity " << PrintToString(EId)
- << " not found in linkage table";
- return false;
- }
-
- const EntityLinkage &ActualLinkage = It->second;
- if (ActualLinkage != ExpectedLinkage) {
- *result_listener << "entity " << PrintToString(EId) << " has linkage "
- << PrintToString(ActualLinkage);
- return false;
- }
-
- return true;
-}
-
-MATCHER_P(LinkageTableHasSize, ExpectedSize,
- std::string("linkage table has size ") +
- PrintToString(ExpectedSize)) {
- if (arg.size() != ExpectedSize) {
- *result_listener << "has size " << arg.size();
- return false;
- }
- return true;
-}
-
-// ============================================================================
-// Summary Data Matchers
-// ============================================================================
-
-MATCHER_P3(HasSummaryData, EId, ExpectedMockId, ExpectedResolutionMapping,
- std::string("has summary data for entity with expected mock ID ") +
- PrintToString(ExpectedMockId)) {
-
- auto It = arg.find(EId);
- if (It == arg.end()) {
- *result_listener << "entity " << PrintToString(EId)
- << " not found in summary data";
- return false;
- }
-
- auto *Mock = static_cast<const MockEntitySummaryEncoding *>(It->second.get());
-
- if (Mock->getId() != ExpectedMockId) {
- *result_listener << "entity " << PrintToString(EId) << " has mock ID "
- << Mock->getId() << " (expected " << ExpectedMockId << ")";
- return false;
- }
-
- if (Mock->getPatchedIds() != ExpectedResolutionMapping) {
- *result_listener << "entity " << PrintToString(EId)
- << " has different resolution mapping";
- return false;
- }
-
- return true;
-}
-
-MATCHER_P(SummaryDataHasSize, ExpectedSize,
- std::string("summary data has size ") + PrintToString(ExpectedSize)) {
- if (arg.size() != ExpectedSize) {
- *result_listener << "has size " << arg.size();
- return false;
- }
- return true;
-}
-
-// ============================================================================
-// ENTITY LINKER TESTS
-// ============================================================================
-
-TEST_F(EntityLinkerTest, CreatesEmptyLinker) {
- NestedBuildNamespace LUNamespace(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "LU")});
-
- EntityLinker Linker(llvm::Triple("arm64-apple-macosx"), LUNamespace);
-
- const auto Output = std::move(Linker).takeOutput();
- EXPECT_EQ(getIdTable(Output).count(), 0u);
- EXPECT_EQ(getLinkageTable(Output).size(), 0u);
- EXPECT_EQ(getData(Output).size(), 0u);
-}
-
-TEST_F(EntityLinkerTest, LinksEmptyTranslationUnit) {
- NestedBuildNamespace LUNamespace(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "LU")});
-
- EntityLinker Linker(llvm::Triple("arm64-apple-macosx"), LUNamespace);
-
- auto TUEmpty =
- createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TUEmpty");
-
- EXPECT_THAT_ERROR(Linker.link(std::move(TUEmpty)), llvm::Succeeded());
-
- const auto Output = std::move(Linker).takeOutput();
- EXPECT_EQ(getIdTable(Output).count(), 0u);
- EXPECT_EQ(getLinkageTable(Output).size(), 0u);
- EXPECT_EQ(getData(Output).size(), 0u);
-}
-
-TEST_F(EntityLinkerTest, LinksOneTranslationUnit) {
- NestedBuildNamespace LUNamespace(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "LU")});
-
- EntityLinker Linker(llvm::Triple("arm64-apple-macosx"), LUNamespace);
-
- auto TU = createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TU");
-
- const auto TU_A_Id = addEntity(*TU, "A", NoneLinkage);
- const auto TU_A_S1_Data = addSummaryData(*TU, TU_A_Id, "S1");
- const auto TU_A_S2_Data = addSummaryData(*TU, TU_A_Id, "S2");
-
- const auto TU_B_Id = addEntity(*TU, "B", InternalLinkage);
- const auto TU_B_S1_Data = addSummaryData(*TU, TU_B_Id, "S1");
- const auto TU_B_S2_Data = addSummaryData(*TU, TU_B_Id, "S2");
-
- const auto TU_C_Id = addEntity(*TU, "C", ExternalLinkage);
- const auto TU_C_S1_Data = addSummaryData(*TU, TU_C_Id, "S1");
-
- const auto TU_D_Id = addEntity(*TU, "D", ExternalLinkage);
- const auto TU_D_S2_Data = addSummaryData(*TU, TU_D_Id, "S2");
-
- const BuildNamespace TUNamespace = getTUNamespace(*TU);
-
- ASSERT_THAT_ERROR(Linker.link(std::move(TU)), llvm::Succeeded());
-
- const auto Output = std::move(Linker).takeOutput();
- const auto &IdTable = getIdTable(Output);
- const auto &Entities = getEntities(IdTable);
- const auto &LinkageTable = getLinkageTable(Output);
- const auto &Data = getData(Output);
-
- NestedBuildNamespace LocalNamespace =
- NestedBuildNamespace(TUNamespace).makeQualified(LUNamespace);
-
- EntityName LU_A_Name("A", "", LocalNamespace);
- EntityName LU_B_Name("B", "", LocalNamespace);
- EntityName LU_C_Name("C", "", LUNamespace);
- EntityName LU_D_Name("D", "", LUNamespace);
-
- // EntityIdTable Tests.
- {
- ASSERT_THAT(IdTable, IdTableHasSize(4u));
- ASSERT_THAT(IdTable, ContainsEntity(LU_A_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_B_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_C_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_D_Name));
- }
-
- // This is safe since we confirmed that these entities are present in the
- // block above.
- const auto LU_A_Id = Entities.at(LU_A_Name);
- const auto LU_B_Id = Entities.at(LU_B_Name);
- const auto LU_C_Id = Entities.at(LU_C_Name);
- const auto LU_D_Id = Entities.at(LU_D_Name);
-
- // LinkageTable Tests.
- {
- ASSERT_THAT(LinkageTable, LinkageTableHasSize(4u));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_A_Id, NoneLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_B_Id, InternalLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_C_Id, ExternalLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_D_Id, ExternalLinkage));
- }
-
- std::map<EntityId, EntityId> Resolution = {{TU_A_Id, LU_A_Id},
- {TU_B_Id, LU_B_Id},
- {TU_C_Id, LU_C_Id},
- {TU_D_Id, LU_D_Id}};
-
- // Data Tests.
- {
- ASSERT_EQ(Data.size(), 2u);
-
- // S1 Data Tests.
- {
- SummaryName S1("S1");
- ASSERT_NE(Data.find(S1), Data.end());
- const auto &S1Data = Data.at(S1);
-
- ASSERT_THAT(S1Data, SummaryDataHasSize(3u));
- ASSERT_THAT(S1Data, HasSummaryData(LU_A_Id, TU_A_S1_Data, Resolution));
- ASSERT_THAT(S1Data, HasSummaryData(LU_B_Id, TU_B_S1_Data, Resolution));
- ASSERT_THAT(S1Data, HasSummaryData(LU_C_Id, TU_C_S1_Data, Resolution));
- }
-
- // S2 Data Tests.
- {
- SummaryName S2("S2");
- ASSERT_NE(Data.find(S2), Data.end());
- const auto &S2Data = Data.at(S2);
-
- ASSERT_THAT(S2Data, SummaryDataHasSize(3u));
- ASSERT_THAT(S2Data, HasSummaryData(LU_A_Id, TU_A_S2_Data, Resolution));
- ASSERT_THAT(S2Data, HasSummaryData(LU_B_Id, TU_B_S2_Data, Resolution));
- ASSERT_THAT(S2Data, HasSummaryData(LU_D_Id, TU_D_S2_Data, Resolution));
- }
- }
-}
-
-TEST_F(EntityLinkerTest, LinksTwoTranslationUnits) {
- NestedBuildNamespace LUNamespace(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "LU")});
-
- EntityLinker Linker(llvm::Triple("arm64-apple-macosx"), LUNamespace);
-
- auto TU1 =
- createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TU1");
-
- // None linkage entities in TU1
- const auto TU1_X_Id = addEntity(*TU1, "X", NoneLinkage);
- const auto TU1_X_S1_Data = addSummaryData(*TU1, TU1_X_Id, "S1");
-
- const auto TU1_Y_Id = addEntity(*TU1, "Y", NoneLinkage);
- const auto TU1_Y_S2_Data = addSummaryData(*TU1, TU1_Y_Id, "S2");
-
- const auto TU1_Z_Id = addEntity(*TU1, "Z", NoneLinkage);
- const auto TU1_Z_S1_Data = addSummaryData(*TU1, TU1_Z_Id, "S1");
- const auto TU1_Z_S2_Data = addSummaryData(*TU1, TU1_Z_Id, "S2");
-
- // Internal linkage entities in TU1
- const auto TU1_A_Id = addEntity(*TU1, "A", InternalLinkage);
- const auto TU1_A_S1_Data = addSummaryData(*TU1, TU1_A_Id, "S1");
-
- const auto TU1_B_Id = addEntity(*TU1, "B", InternalLinkage);
- const auto TU1_B_S2_Data = addSummaryData(*TU1, TU1_B_Id, "S2");
-
- const auto TU1_C_Id = addEntity(*TU1, "C", InternalLinkage);
- const auto TU1_C_S1_Data = addSummaryData(*TU1, TU1_C_Id, "S1");
- const auto TU1_C_S2_Data = addSummaryData(*TU1, TU1_C_Id, "S2");
-
- // External linkage entities in TU1
- const auto TU1_P_Id = addEntity(*TU1, "P", ExternalLinkage);
- const auto TU1_P_S1_Data = addSummaryData(*TU1, TU1_P_Id, "S1");
-
- const auto TU1_Q_Id = addEntity(*TU1, "Q", ExternalLinkage);
- const auto TU1_Q_S2_Data = addSummaryData(*TU1, TU1_Q_Id, "S2");
-
- const auto TU1_R_Id = addEntity(*TU1, "R", ExternalLinkage);
- const auto TU1_R_S1_Data = addSummaryData(*TU1, TU1_R_Id, "S1");
- const auto TU1_R_S2_Data = addSummaryData(*TU1, TU1_R_Id, "S2");
-
- const BuildNamespace TU1Namespace = getTUNamespace(*TU1);
-
- ASSERT_THAT_ERROR(Linker.link(std::move(TU1)), llvm::Succeeded());
-
- auto TU2 =
- createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TU2");
-
- // None linkage entities in TU2 - includes duplicates and uniques
- const auto TU2_X_Id = addEntity(*TU2, "X", NoneLinkage);
- const auto TU2_X_S2_Data = addSummaryData(*TU2, TU2_X_Id, "S2");
-
- const auto TU2_Y_Id = addEntity(*TU2, "Y", NoneLinkage);
- const auto TU2_Y_S1_Data = addSummaryData(*TU2, TU2_Y_Id, "S1");
-
- const auto TU2_W_Id = addEntity(*TU2, "W", NoneLinkage);
- const auto TU2_W_S1_Data = addSummaryData(*TU2, TU2_W_Id, "S1");
- const auto TU2_W_S2_Data = addSummaryData(*TU2, TU2_W_Id, "S2");
-
- // Internal linkage entities in TU2 - includes duplicates and unique
- const auto TU2_A_Id = addEntity(*TU2, "A", InternalLinkage);
- const auto TU2_A_S2_Data = addSummaryData(*TU2, TU2_A_Id, "S2");
-
- const auto TU2_B_Id = addEntity(*TU2, "B", InternalLinkage);
- const auto TU2_B_S1_Data = addSummaryData(*TU2, TU2_B_Id, "S1");
-
- const auto TU2_D_Id = addEntity(*TU2, "D", InternalLinkage);
- const auto TU2_D_S1_Data = addSummaryData(*TU2, TU2_D_Id, "S1");
- const auto TU2_D_S2_Data = addSummaryData(*TU2, TU2_D_Id, "S2");
-
- // External linkage entities in TU2 - includes duplicates (will be dropped)
- // and uniques
- const auto TU2_P_Id = addEntity(*TU2, "P", ExternalLinkage);
- const auto TU2_P_S2_Data = addSummaryData(*TU2, TU2_P_Id, "S2");
-
- const auto TU2_Q_Id = addEntity(*TU2, "Q", ExternalLinkage);
- const auto TU2_Q_S1_Data = addSummaryData(*TU2, TU2_Q_Id, "S1");
-
- const auto TU2_R_Id = addEntity(*TU2, "R", ExternalLinkage);
- const auto TU2_R_S1_Data = addSummaryData(*TU2, TU2_R_Id, "S1");
- const auto TU2_R_S2_Data = addSummaryData(*TU2, TU2_R_Id, "S2");
-
- const auto TU2_S_Id = addEntity(*TU2, "S", ExternalLinkage);
- const auto TU2_S_S1_Data = addSummaryData(*TU2, TU2_S_Id, "S1");
- const auto TU2_S_S2_Data = addSummaryData(*TU2, TU2_S_Id, "S2");
-
- const BuildNamespace TU2Namespace = getTUNamespace(*TU2);
-
- ASSERT_THAT_ERROR(Linker.link(std::move(TU2)), llvm::Succeeded());
-
- const auto Output = std::move(Linker).takeOutput();
- const auto &IdTable = getIdTable(Output);
- const auto &Entities = getEntities(IdTable);
- const auto &LinkageTable = getLinkageTable(Output);
- const auto &Data = getData(Output);
-
- NestedBuildNamespace TU1LocalNamespace =
- NestedBuildNamespace(TU1Namespace).makeQualified(LUNamespace);
-
- NestedBuildNamespace TU2LocalNamespace =
- NestedBuildNamespace(TU2Namespace).makeQualified(LUNamespace);
-
- // None linkage entities use local namespace (TU scoped)
- EntityName LU_TU1_X_Name("X", "", TU1LocalNamespace);
- EntityName LU_TU1_Y_Name("Y", "", TU1LocalNamespace);
- EntityName LU_TU1_Z_Name("Z", "", TU1LocalNamespace);
- EntityName LU_TU2_X_Name("X", "", TU2LocalNamespace);
- EntityName LU_TU2_Y_Name("Y", "", TU2LocalNamespace);
- EntityName LU_TU2_W_Name("W", "", TU2LocalNamespace);
-
- // Internal linkage entities use local namespace (TU scoped)
- EntityName LU_TU1_A_Name("A", "", TU1LocalNamespace);
- EntityName LU_TU1_B_Name("B", "", TU1LocalNamespace);
- EntityName LU_TU1_C_Name("C", "", TU1LocalNamespace);
- EntityName LU_TU2_A_Name("A", "", TU2LocalNamespace);
- EntityName LU_TU2_B_Name("B", "", TU2LocalNamespace);
- EntityName LU_TU2_D_Name("D", "", TU2LocalNamespace);
-
- // External linkage entities use LU namespace (shared across TUs)
- EntityName LU_P_Name("P", "", LUNamespace);
- EntityName LU_Q_Name("Q", "", LUNamespace);
- EntityName LU_R_Name("R", "", LUNamespace);
- EntityName LU_S_Name("S", "", LUNamespace);
-
- // EntityIdTable Tests.
- {
- // Should have 6 None + 6 Internal + 4 External = 16 entities total
- ASSERT_THAT(IdTable, IdTableHasSize(16u));
-
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_X_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_Y_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_Z_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_X_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_Y_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_W_Name));
-
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_A_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_B_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_C_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_A_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_B_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_D_Name));
-
- ASSERT_THAT(IdTable, ContainsEntity(LU_P_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_Q_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_R_Name));
- ASSERT_THAT(IdTable, ContainsEntity(LU_S_Name));
- }
-
- // This is safe since we confirmed that these entities are present in the
- // block above.
- const auto LU_TU1_X_Id = Entities.at(LU_TU1_X_Name);
- const auto LU_TU1_Y_Id = Entities.at(LU_TU1_Y_Name);
- const auto LU_TU1_Z_Id = Entities.at(LU_TU1_Z_Name);
- const auto LU_TU2_X_Id = Entities.at(LU_TU2_X_Name);
- const auto LU_TU2_Y_Id = Entities.at(LU_TU2_Y_Name);
- const auto LU_TU2_W_Id = Entities.at(LU_TU2_W_Name);
- const auto LU_TU1_A_Id = Entities.at(LU_TU1_A_Name);
- const auto LU_TU1_B_Id = Entities.at(LU_TU1_B_Name);
- const auto LU_TU1_C_Id = Entities.at(LU_TU1_C_Name);
- const auto LU_TU2_A_Id = Entities.at(LU_TU2_A_Name);
- const auto LU_TU2_B_Id = Entities.at(LU_TU2_B_Name);
- const auto LU_TU2_D_Id = Entities.at(LU_TU2_D_Name);
- const auto LU_P_Id = Entities.at(LU_P_Name);
- const auto LU_Q_Id = Entities.at(LU_Q_Name);
- const auto LU_R_Id = Entities.at(LU_R_Name);
- const auto LU_S_Id = Entities.at(LU_S_Name);
-
- // LinkageTable Tests.
- {
- ASSERT_THAT(LinkageTable, LinkageTableHasSize(16u));
-
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_X_Id, NoneLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_Y_Id, NoneLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_Z_Id, NoneLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_X_Id, NoneLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_Y_Id, NoneLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_W_Id, NoneLinkage));
-
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_A_Id, InternalLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_B_Id, InternalLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_C_Id, InternalLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_A_Id, InternalLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_B_Id, InternalLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_D_Id, InternalLinkage));
-
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_P_Id, ExternalLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_Q_Id, ExternalLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_R_Id, ExternalLinkage));
- ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_S_Id, ExternalLinkage));
- }
-
- // Data Tests.
- {
- ASSERT_EQ(Data.size(), 2u);
-
- // Build entity resolution mappings for each TU.
- std::map<EntityId, EntityId> TU1Resolution = {
- {TU1_X_Id, LU_TU1_X_Id}, {TU1_Y_Id, LU_TU1_Y_Id},
- {TU1_Z_Id, LU_TU1_Z_Id}, {TU1_A_Id, LU_TU1_A_Id},
- {TU1_B_Id, LU_TU1_B_Id}, {TU1_C_Id, LU_TU1_C_Id},
- {TU1_P_Id, LU_P_Id}, {TU1_Q_Id, LU_Q_Id},
- {TU1_R_Id, LU_R_Id}};
-
- std::map<EntityId, EntityId> TU2Resolution = {
- {TU2_X_Id, LU_TU2_X_Id}, {TU2_Y_Id, LU_TU2_Y_Id},
- {TU2_W_Id, LU_TU2_W_Id}, {TU2_A_Id, LU_TU2_A_Id},
- {TU2_B_Id, LU_TU2_B_Id}, {TU2_D_Id, LU_TU2_D_Id},
- {TU2_P_Id, LU_P_Id}, {TU2_Q_Id, LU_Q_Id},
- {TU2_R_Id, LU_R_Id}, {TU2_S_Id, LU_S_Id}};
-
- // S1 Data Tests.
- {
- SummaryName S1("S1");
- ASSERT_NE(Data.find(S1), Data.end());
- const auto &S1Data = Data.at(S1);
-
- // S1 should contain: TU1(X,Z,A,C,P,R) + TU2(Y,W,B,D,Q,S) = 12 entities.
- ASSERT_THAT(S1Data, SummaryDataHasSize(12u));
-
- // TU1 entities in S1.
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_TU1_X_Id, TU1_X_S1_Data, TU1Resolution));
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_TU1_Z_Id, TU1_Z_S1_Data, TU1Resolution));
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_TU1_A_Id, TU1_A_S1_Data, TU1Resolution));
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_TU1_C_Id, TU1_C_S1_Data, TU1Resolution));
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_P_Id, TU1_P_S1_Data, TU1Resolution));
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_R_Id, TU1_R_S1_Data, TU1Resolution));
-
- // TU2 entities in S1.
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_TU2_Y_Id, TU2_Y_S1_Data, TU2Resolution));
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_TU2_W_Id, TU2_W_S1_Data, TU2Resolution));
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_TU2_B_Id, TU2_B_S1_Data, TU2Resolution));
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_TU2_D_Id, TU2_D_S1_Data, TU2Resolution));
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_Q_Id, TU2_Q_S1_Data, TU2Resolution));
- ASSERT_THAT(S1Data,
- Not(HasSummaryData(LU_R_Id, TU2_R_S1_Data, TU2Resolution)));
- ASSERT_THAT(S1Data,
- HasSummaryData(LU_S_Id, TU2_S_S1_Data, TU2Resolution));
- }
-
- // S2 Data Tests.
- {
- SummaryName S2("S2");
- ASSERT_NE(Data.find(S2), Data.end());
- const auto &S2Data = Data.at(S2);
-
- // S2 should contain: TU1(Y,Z,B,C,Q,R) + TU2(X,W,A,D,P,S) = 12 entities.
- ASSERT_THAT(S2Data, SummaryDataHasSize(12u));
-
- // TU1 entities in S2.
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_TU1_Y_Id, TU1_Y_S2_Data, TU1Resolution));
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_TU1_Z_Id, TU1_Z_S2_Data, TU1Resolution));
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_TU1_B_Id, TU1_B_S2_Data, TU1Resolution));
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_TU1_C_Id, TU1_C_S2_Data, TU1Resolution));
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_Q_Id, TU1_Q_S2_Data, TU1Resolution));
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_R_Id, TU1_R_S2_Data, TU1Resolution));
-
- // TU2 entities in S2.
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_TU2_X_Id, TU2_X_S2_Data, TU2Resolution));
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_TU2_W_Id, TU2_W_S2_Data, TU2Resolution));
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_TU2_A_Id, TU2_A_S2_Data, TU2Resolution));
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_TU2_D_Id, TU2_D_S2_Data, TU2Resolution));
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_P_Id, TU2_P_S2_Data, TU2Resolution));
- ASSERT_THAT(S2Data,
- Not(HasSummaryData(LU_R_Id, TU2_R_S2_Data, TU2Resolution)));
- ASSERT_THAT(S2Data,
- HasSummaryData(LU_S_Id, TU2_S_S2_Data, TU2Resolution));
- }
- }
-}
-
-TEST_F(EntityLinkerTest, RejectsDuplicateTUSummary) {
- NestedBuildNamespace LUNamespace(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "LU")});
-
- EntityLinker Linker(llvm::Triple("arm64-apple-macosx"), LUNamespace);
-
- auto TU1 = createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TU");
-
- ASSERT_THAT_ERROR(Linker.link(std::move(TU1)), llvm::Succeeded());
-
- auto TU2 = createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TU");
-
- ASSERT_THAT_ERROR(Linker.link(std::move(TU2)),
- llvm::FailedWithMessage(
- HasSubstr("failed to link TU summary: duplicate "
- "BuildNamespace(CompilationUnit, TU)")));
-}
-
-// Reproduces a crash when linking internal-linkage entities
-// (e.g. "static inline" functions) that share the same USR across TUs.
-TEST_F(EntityLinkerTest, InternalLinkageWithEmptyNamespaceAcrossTUs) {
- constexpr auto LinkUnit = BuildNamespaceKind::LinkUnit;
- constexpr auto CompilationUnit = BuildNamespaceKind::CompilationUnit;
- EntityLinker Linker(llvm::Triple("arm64-apple-macosx"),
- NestedBuildNamespace{BuildNamespace(LinkUnit, "LU")});
-
- auto TU1 = createTUSummaryEncoding(CompilationUnit, "TU1");
- addEntity(*TU1, "some_static_inline", InternalLinkage);
- ASSERT_THAT_ERROR(Linker.link(std::move(TU1)), llvm::Succeeded());
-
- auto TU2 = createTUSummaryEncoding(CompilationUnit, "TU2");
- addEntity(*TU2, "some_static_inline", InternalLinkage);
- ASSERT_THAT_ERROR(Linker.link(std::move(TU2)), llvm::Succeeded());
-
- // Check that the two internal symbols are not merged.
- const auto Output = std::move(Linker).takeOutput();
- const auto &IdTable = getIdTable(Output);
-
- NestedBuildNamespace TU1NS{{{CompilationUnit, "TU1"}, {LinkUnit, "LU"}}};
- NestedBuildNamespace TU2NS{{{CompilationUnit, "TU2"}, {LinkUnit, "LU"}}};
- EntityName ExpectedTU1Name("some_static_inline", "", TU1NS);
- EntityName ExpectedTU2Name("some_static_inline", "", TU2NS);
-
- ASSERT_EQ(IdTable.count(), 2u);
- EXPECT_THAT(IdTable, ContainsEntity(ExpectedTU1Name));
- EXPECT_THAT(IdTable, ContainsEntity(ExpectedTU2Name));
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/EntityNameTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/EntityNameTest.cpp
deleted file mode 100644
index 651b43744ed35..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/EntityNameTest.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-//===- EntityNameTest.cpp -------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-
-namespace clang::ssaf {
-namespace {
-
-TEST(EntityNameTest, Equality) {
- auto NBN1 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
- auto NBN2 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
-
- EntityName EN1("c:@F at foo", "", NBN1);
- EntityName EN2("c:@F at foo", "", NBN2);
- EntityName EN3("c:@F at bar", "", NBN1);
-
- EXPECT_EQ(EN1, EN2);
- EXPECT_NE(EN1, EN3);
-}
-
-TEST(EntityNameTest, EqualityWithDifferentSuffix) {
- auto NBN = NestedBuildNamespace::makeCompilationUnit("test.cpp");
-
- EntityName EN1("c:@F at foo", "1", NBN);
- EntityName EN2("c:@F at foo", "2", NBN);
-
- EXPECT_NE(EN1, EN2);
-}
-
-TEST(EntityNameTest, EqualityWithDifferentNamespace) {
- auto NBN1 = NestedBuildNamespace::makeCompilationUnit("test1.cpp");
- auto NBN2 = NestedBuildNamespace::makeCompilationUnit("test2.cpp");
-
- EntityName EN1("c:@F at foo", "", NBN1);
- EntityName EN2("c:@F at foo", "", NBN2);
-
- EXPECT_NE(EN1, EN2);
-}
-
-TEST(EntityNameTest, MakeQualified) {
- auto NBN1 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
- EntityName EN("c:@F at foo", "", NBN1);
-
- BuildNamespace LinkNS(BuildNamespaceKind::LinkUnit, "app");
- NestedBuildNamespace NBN2(LinkNS);
-
- auto Qualified = EN.makeQualified(NBN2);
-
- EXPECT_NE(Qualified, EN);
-}
-
-TEST(EntityNameTest, FormatProvider) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
- EntityName EN("c:@F at foo", "", NBN);
- EXPECT_EQ(
- llvm::formatv("{0}", EN).str(),
- "EntityName(c:@F at foo, , "
- "NestedBuildNamespace([BuildNamespace(CompilationUnit, test.cpp)]))");
-}
-
-TEST(EntityNameTest, StreamOutputNoSuffix) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
- EntityName EN("c:@F at foo", "", NBN);
- std::string S;
- llvm::raw_string_ostream(S) << EN;
- EXPECT_EQ(
- S, "EntityName(c:@F at foo, , "
- "NestedBuildNamespace([BuildNamespace(CompilationUnit, test.cpp)]))");
-}
-
-TEST(EntityNameTest, StreamOutputWithSuffix) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
- EntityName EN("c:@F at foo", "1", NBN);
- std::string S;
- llvm::raw_string_ostream(S) << EN;
- EXPECT_EQ(
- S, "EntityName(c:@F at foo, 1, "
- "NestedBuildNamespace([BuildNamespace(CompilationUnit, test.cpp)]))");
-}
-
-} // namespace
-} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/ErrorBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/ErrorBuilderTest.cpp
deleted file mode 100644
index 65db17416b965..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/ErrorBuilderTest.cpp
+++ /dev/null
@@ -1,196 +0,0 @@
-//===- ErrorBuilderTest.cpp -----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
-#include "gtest/gtest.h"
-#include <system_error>
-
-using namespace llvm;
-
-namespace clang::ssaf {
-
-namespace {
-
-class ErrorBuilderTest : public ::testing::Test {
-protected:
- struct ErrorInfo {
- std::error_code Code;
- std::string Message;
- };
-
- ErrorInfo extractErrorInfo(Error Err) {
- ErrorInfo Info;
-
- handleAllErrors(std::move(Err), [&](const StringError &SE) {
- Info.Code = SE.convertToErrorCode();
- Info.Message = SE.getMessage();
- });
-
- return Info;
- }
-};
-
-TEST_F(ErrorBuilderTest, CreatesSimpleError) {
- auto Err =
- ErrorBuilder::create(std::errc::invalid_argument, "test error").build();
-
- auto Info = extractErrorInfo(std::move(Err));
-
- EXPECT_EQ(Info.Code, std::errc::invalid_argument);
- EXPECT_EQ(Info.Message, "test error");
-}
-
-TEST_F(ErrorBuilderTest, CreatesErrorWithErrorCode) {
- auto EC = std::make_error_code(std::errc::no_such_file_or_directory);
- auto Err = ErrorBuilder::create(EC, "file not found").build();
-
- auto Info = extractErrorInfo(std::move(Err));
-
- EXPECT_EQ(Info.Code, std::errc::no_such_file_or_directory);
- EXPECT_EQ(Info.Message, "file not found");
-}
-
-TEST_F(ErrorBuilderTest, CreatesErrorWithFormattedMessage) {
- auto Err = ErrorBuilder::create(std::errc::invalid_argument,
- "field '{0}' has value {1}", "age", 150)
- .build();
-
- auto Info = extractErrorInfo(std::move(Err));
-
- EXPECT_EQ(Info.Code, std::errc::invalid_argument);
- EXPECT_EQ(Info.Message, "field 'age' has value 150");
-}
-
-TEST_F(ErrorBuilderTest, AddsPlainContext) {
- auto Err = ErrorBuilder::create(std::errc::invalid_argument, "inner error")
- .context("outer context")
- .build();
-
- auto Info = extractErrorInfo(std::move(Err));
-
- EXPECT_EQ(Info.Code, std::errc::invalid_argument);
- EXPECT_EQ(Info.Message, "outer context\ninner error");
-}
-
-TEST_F(ErrorBuilderTest, AddsMultipleContextLayers) {
- auto Err = ErrorBuilder::create(std::errc::invalid_argument,
- "expected {0} but got {1} in field '{2}'",
- "string", "number", "value")
- .context("parsing line {0}", 42)
- .context("reading file '{0}'", "config.json")
- .build();
-
- auto Info = extractErrorInfo(std::move(Err));
-
- EXPECT_EQ(Info.Code, std::errc::invalid_argument);
- EXPECT_EQ(Info.Message, "reading file 'config.json'\n"
- "parsing line 42\n"
- "expected string but got number in field 'value'");
-}
-
-TEST_F(ErrorBuilderTest, HandlesSpecialCharactersInContext) {
- auto Err = ErrorBuilder::create(std::errc::invalid_argument,
- "special chars: {0}", "test\nwith\nnewlines")
- .context("tab\tseparated\tvalues")
- .build();
-
- auto Info = extractErrorInfo(std::move(Err));
-
- EXPECT_EQ(Info.Code, std::errc::invalid_argument);
- EXPECT_EQ(Info.Message, "tab\tseparated\tvalues\n"
- "special chars: test\n"
- "with\n"
- "newlines");
-}
-
-TEST_F(ErrorBuilderTest, WrapsExistingError) {
- auto OriginalErr =
- createStringError(std::errc::invalid_argument, "original error message");
-
- auto WrappedErr = ErrorBuilder::wrap(std::move(OriginalErr))
- .context("additional context")
- .build();
-
- auto Info = extractErrorInfo(std::move(WrappedErr));
-
- EXPECT_EQ(Info.Code, std::errc::invalid_argument);
- EXPECT_EQ(Info.Message, "additional context\noriginal error message");
-}
-
-TEST_F(ErrorBuilderTest, WrapsMultipleJoinedErrors) {
- auto Err1 = createStringError(std::errc::invalid_argument, "first");
- auto Err2 = createStringError(std::errc::argument_list_too_long, "second");
- auto Err3 = createStringError(std::errc::filename_too_long, "third");
-
- auto JoinedErr =
- joinErrors(std::move(Err1), joinErrors(std::move(Err2), std::move(Err3)));
-
- auto WrappedErr = ErrorBuilder::wrap(std::move(JoinedErr))
- .context("wrapping three joined errors")
- .build();
-
- auto Info = extractErrorInfo(std::move(WrappedErr));
-
- EXPECT_EQ(Info.Code, std::errc::invalid_argument);
- // All three messages combined with " + " in the order they were handled
- EXPECT_EQ(Info.Message,
- "wrapping three joined errors\nfirst + second + third");
-}
-
-TEST_F(ErrorBuilderTest, WrapsErrorWithEmptyMessage) {
- auto EmptyErr = createStringError(std::errc::invalid_argument, "");
-
- auto WrappedErr = ErrorBuilder::wrap(std::move(EmptyErr))
- .context("")
- .context("wrapping error with empty message")
- .context("")
- .build();
-
- auto Info = extractErrorInfo(std::move(WrappedErr));
-
- EXPECT_EQ(Info.Code, std::errc::invalid_argument);
- EXPECT_EQ(Info.Message, "wrapping error with empty message");
-}
-
-TEST_F(ErrorBuilderTest, CreatesErrorWithEmptyMessage) {
- auto Err = ErrorBuilder::create(std::errc::invalid_argument, "")
- .context("")
- .context("creating error with empty message")
- .context("")
- .build();
-
- auto Info = extractErrorInfo(std::move(Err));
-
- EXPECT_EQ(Info.Code, std::errc::invalid_argument);
- EXPECT_EQ(Info.Message, "creating error with empty message");
-}
-
-#ifndef NDEBUG
-// Death test only works in debug builds where assertions are enabled
-TEST_F(ErrorBuilderTest, TriggersAssertionOnWrappingSuccessError) {
- EXPECT_DEATH(
- {
- auto SuccessErr = Error::success();
- ErrorBuilder::wrap(std::move(SuccessErr));
- },
- "Cannot wrap a success error - check for success before calling wrap");
-}
-#endif // !NDEBUG
-
-TEST_F(ErrorBuilderTest, FatalTerminatesExecution) {
- EXPECT_DEATH(
- {
- ErrorBuilder::fatal("Entity {0} with {1} linkage already exists", 42,
- "Internal");
- },
- "Entity 42 with Internal linkage already exists");
-}
-
-} // namespace
-
-} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/FindDecl.h b/clang/unittests/ScalableStaticAnalysisFramework/FindDecl.h
deleted file mode 100644
index 5ce50fe538cda..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/FindDecl.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//===- FindDecl.h -----------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_FINDDECL_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_FINDDECL_H
-
-#include "clang/AST/Decl.h"
-#include "clang/AST/DynamicRecursiveASTVisitor.h"
-
-namespace clang::ssaf {
-
-template <typename SomeDecl = clang::NamedDecl>
-const SomeDecl *findDeclByName(StringRef Name, ASTContext &Ctx) {
- class NamedDeclFinder : public DynamicRecursiveASTVisitor {
- public:
- StringRef SearchingName;
- const NamedDecl *FoundDecl = nullptr;
-
- NamedDeclFinder(StringRef SearchingName) : SearchingName(SearchingName) {
- ShouldVisitTemplateInstantiations = true;
- }
-
- bool VisitDecl(Decl *D) override {
- if (D->isTemplated())
- return true;
- if (const auto *ND = dyn_cast<SomeDecl>(D)) {
- if (ND->getNameAsString() == SearchingName) {
- FoundDecl = ND;
- return false;
- }
- }
- return true;
- }
- };
-
- NamedDeclFinder Finder(Name);
-
- Finder.TraverseDecl(Ctx.getTranslationUnitDecl());
- return dyn_cast_or_null<SomeDecl>(Finder.FoundDecl);
-}
-
-inline const FunctionDecl *findFnByName(StringRef Name, ASTContext &Ctx) {
- return findDeclByName<FunctionDecl>(Name, Ctx);
-}
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_FINDDECL_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/LUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/LUSummaryTest.cpp
deleted file mode 100644
index 55ae20ce97ca7..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/LUSummaryTest.cpp
+++ /dev/null
@@ -1,25 +0,0 @@
-//===- LUSummaryTest.cpp --------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "gtest/gtest.h"
-
-namespace clang::ssaf {
-namespace {
-
-TEST(LUSummaryTest, GetNamespace) {
- BuildNamespace LU(BuildNamespaceKind::LinkUnit, "app");
- NestedBuildNamespace NS(LU);
- LUSummary Summary(llvm::Triple("arm64-apple-macosx"), NS);
-
- EXPECT_EQ(Summary.getNamespace(), NS);
-}
-
-} // namespace
-} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/ModelStringConversionsTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/ModelStringConversionsTest.cpp
deleted file mode 100644
index aff5140f26c2f..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/ModelStringConversionsTest.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-//===- ModelStringConversionsTest.cpp -------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../../lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h"
-#include "gtest/gtest.h"
-
-using namespace clang::ssaf;
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// BuildNamespaceKind
-//===----------------------------------------------------------------------===//
-
-TEST(BuildNamespaceKindStringTest, ToStringCompilationUnit) {
- EXPECT_EQ(buildNamespaceKindToString(BuildNamespaceKind::CompilationUnit),
- "CompilationUnit");
-}
-
-TEST(BuildNamespaceKindStringTest, ToStringLinkUnit) {
- EXPECT_EQ(buildNamespaceKindToString(BuildNamespaceKind::LinkUnit),
- "LinkUnit");
-}
-
-TEST(BuildNamespaceKindStringTest, FromStringCompilationUnit) {
- EXPECT_EQ(buildNamespaceKindFromString("CompilationUnit"),
- BuildNamespaceKind::CompilationUnit);
-}
-
-TEST(BuildNamespaceKindStringTest, FromStringLinkUnit) {
- EXPECT_EQ(buildNamespaceKindFromString("LinkUnit"),
- BuildNamespaceKind::LinkUnit);
-}
-
-TEST(BuildNamespaceKindStringTest, FromStringUnknown) {
- EXPECT_EQ(buildNamespaceKindFromString("compilation_unit"), std::nullopt);
- EXPECT_EQ(buildNamespaceKindFromString("link_unit"), std::nullopt);
- EXPECT_EQ(buildNamespaceKindFromString(""), std::nullopt);
- EXPECT_EQ(buildNamespaceKindFromString("unknown"), std::nullopt);
-}
-
-TEST(BuildNamespaceKindStringTest, RoundTrip) {
- EXPECT_EQ(buildNamespaceKindFromString(buildNamespaceKindToString(
- BuildNamespaceKind::CompilationUnit)),
- BuildNamespaceKind::CompilationUnit);
- EXPECT_EQ(buildNamespaceKindFromString(
- buildNamespaceKindToString(BuildNamespaceKind::LinkUnit)),
- BuildNamespaceKind::LinkUnit);
-}
-
-//===----------------------------------------------------------------------===//
-// EntityLinkageType
-//===----------------------------------------------------------------------===//
-
-TEST(EntityLinkageTypeStringTest, ToStringNone) {
- EXPECT_EQ(entityLinkageTypeToString(EntityLinkageType::None), "None");
-}
-
-TEST(EntityLinkageTypeStringTest, ToStringInternal) {
- EXPECT_EQ(entityLinkageTypeToString(EntityLinkageType::Internal), "Internal");
-}
-
-TEST(EntityLinkageTypeStringTest, ToStringExternal) {
- EXPECT_EQ(entityLinkageTypeToString(EntityLinkageType::External), "External");
-}
-
-TEST(EntityLinkageTypeStringTest, FromStringNone) {
- EXPECT_EQ(entityLinkageTypeFromString("None"), EntityLinkageType::None);
-}
-
-TEST(EntityLinkageTypeStringTest, FromStringInternal) {
- EXPECT_EQ(entityLinkageTypeFromString("Internal"),
- EntityLinkageType::Internal);
-}
-
-TEST(EntityLinkageTypeStringTest, FromStringExternal) {
- EXPECT_EQ(entityLinkageTypeFromString("External"),
- EntityLinkageType::External);
-}
-
-TEST(EntityLinkageTypeStringTest, FromStringUnknown) {
- EXPECT_EQ(entityLinkageTypeFromString("none"), std::nullopt);
- EXPECT_EQ(entityLinkageTypeFromString("internal"), std::nullopt);
- EXPECT_EQ(entityLinkageTypeFromString("external"), std::nullopt);
- EXPECT_EQ(entityLinkageTypeFromString(""), std::nullopt);
- EXPECT_EQ(entityLinkageTypeFromString("unknown"), std::nullopt);
-}
-
-TEST(EntityLinkageTypeStringTest, RoundTrip) {
- EXPECT_EQ(entityLinkageTypeFromString(
- entityLinkageTypeToString(EntityLinkageType::None)),
- EntityLinkageType::None);
- EXPECT_EQ(entityLinkageTypeFromString(
- entityLinkageTypeToString(EntityLinkageType::Internal)),
- EntityLinkageType::Internal);
- EXPECT_EQ(entityLinkageTypeFromString(
- entityLinkageTypeToString(EntityLinkageType::External)),
- EntityLinkageType::External);
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
deleted file mode 100644
index 084835190f7bd..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/FancyAnalysisData.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-//===- FancyAnalysisData.cpp ----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Registries/MockSerializationFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Registry.h"
-
-using namespace clang;
-using namespace ssaf;
-
-using SpecialFileRepresentation =
- MockSerializationFormat::SpecialFileRepresentation;
-
-namespace {
-struct FancyAnalysisData final : EntitySummary {
- SummaryName getSummaryName() const override {
- return SummaryName("FancyAnalysis");
- }
-
- std::string Text;
-};
-} // namespace
-
-static SpecialFileRepresentation
-serializeFancyAnalysis(const EntitySummary &Data,
- MockSerializationFormat &Format) {
- const auto &FancyAnalysis = static_cast<const FancyAnalysisData &>(Data);
- return SpecialFileRepresentation{/*MockRepresentation=*/FancyAnalysis.Text};
-}
-
-static std::unique_ptr<EntitySummary>
-deserializeFancyAnalysis(const SpecialFileRepresentation &File,
- EntityIdTable &) {
- auto Result = std::make_unique<FancyAnalysisData>();
- Result->Text = File.MockRepresentation;
- return std::move(Result);
-}
-
-namespace {
-using FormatInfo = MockSerializationFormat::FormatInfo;
-struct FancyAnalysisFormatInfo final : FormatInfo {
- FancyAnalysisFormatInfo()
- : FormatInfo{
- SummaryName("FancyAnalysis"),
- serializeFancyAnalysis,
- deserializeFancyAnalysis,
- } {}
-};
-} // namespace
-
-static llvm::Registry<FormatInfo>::Add<FancyAnalysisFormatInfo>
- RegisterFormatInfo("FancyAnalysisData",
- "Format info for FancyAnalysisData for the "
- "MockSerializationFormat format");
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
deleted file mode 100644
index 03ed471f86087..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp
+++ /dev/null
@@ -1,232 +0,0 @@
-//===- MockSerializationFormat.cpp ----------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "Registries/MockSerializationFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cassert>
-#include <functional>
-#include <memory>
-#include <set>
-
-using namespace clang;
-using namespace ssaf;
-
-LLVM_DEFINE_REGISTRY(llvm::Registry<MockSerializationFormat::FormatInfo>)
-
-MockSerializationFormat::MockSerializationFormat() {
- for (const auto &FormatInfoEntry : llvm::Registry<FormatInfo>::entries()) {
- std::unique_ptr<FormatInfo> Info = FormatInfoEntry.instantiate();
- bool Inserted = FormatInfos.try_emplace(Info->ForSummary, *Info).second;
- if (!Inserted) {
- llvm::report_fatal_error(
- "Format info was already registered for summary name: " +
- Info->ForSummary.str());
- }
- }
-}
-
-void MockSerializationFormat::forEachRegisteredAnalysis(
- llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> Callback) const {
- for (const auto &Entry : llvm::Registry<FormatInfo>::entries())
- Callback(Entry.getName(), Entry.getDesc());
-}
-
-llvm::Expected<TUSummary>
-MockSerializationFormat::readTUSummary(llvm::StringRef Path) {
- BuildNamespace NS(BuildNamespaceKind::CompilationUnit, "Mock.cpp");
- TUSummary Summary(llvm::Triple("arm64-apple-macosx"), NS);
-
- auto ManifestFile = llvm::MemoryBuffer::getFile(Path + "/analyses.txt");
- if (!ManifestFile) {
- return llvm::createStringError(ManifestFile.getError(),
- "Failed to read manifest file");
- }
- llvm::StringRef ManifestFileContent = (*ManifestFile)->getBuffer();
-
- llvm::SmallVector<llvm::StringRef, 5> Analyses;
- ManifestFileContent.split(Analyses, /*Separator=*/"\n", /*MaxSplit=*/-1,
- /*KeepEmpty=*/false);
-
- for (llvm::StringRef Analysis : Analyses) {
- SummaryName Name(Analysis.str());
- auto InputFile =
- llvm::MemoryBuffer::getFile(Path + "/" + Name.str() + ".special");
- if (!InputFile) {
- return llvm::createStringError(InputFile.getError(),
- "Failed to read analysis file");
- }
- auto InfoIt = FormatInfos.find(Name);
- if (InfoIt == FormatInfos.end()) {
- return llvm::createStringError(
- std::make_error_code(std::errc::invalid_argument),
- "No FormatInfo was registered for summary name: " + Name.str());
- }
- const auto &InfoEntry = InfoIt->second;
- assert(InfoEntry.ForSummary == Name);
-
- SpecialFileRepresentation Repr{(*InputFile)->getBuffer().str()};
- auto &Table = getIdTable(Summary);
-
- std::unique_ptr<EntitySummary> Result = InfoEntry.Deserialize(Repr, Table);
- if (!Result) {
- return llvm::createStringError(
- std::make_error_code(std::errc::invalid_argument),
- "Failed to deserialize EntitySummary for analysis: " + Name.str());
- }
-
- EntityId FooId = Table.getId(EntityName{"c:@F at foo", "", /*Namespace=*/{}});
- auto &IdMappings = getData(Summary).try_emplace(Name).first->second;
- [[maybe_unused]] bool Inserted =
- IdMappings.try_emplace(FooId, std::move(Result)).second;
- assert(Inserted);
- }
-
- return std::move(Summary);
-}
-
-llvm::Error MockSerializationFormat::writeTUSummary(const TUSummary &Summary,
- llvm::StringRef Path) {
- std::error_code EC;
-
- // Check if output directory exists, create if needed
- if (!llvm::sys::fs::exists(Path)) {
- EC = llvm::sys::fs::create_directories(Path);
- if (EC) {
- return llvm::createStringError(EC, "Failed to create output directory '" +
- Path + "': " + EC.message());
- }
- }
-
- std::set<SummaryName> Analyses;
- for (const auto &[SummaryName, EntityMappings] : getData(Summary)) {
- [[maybe_unused]] bool Inserted = Analyses.insert(SummaryName).second;
- assert(Inserted);
- for (const auto &Data : llvm::make_second_range(EntityMappings)) {
- auto InfoIt = FormatInfos.find(SummaryName);
- if (InfoIt == FormatInfos.end()) {
- return llvm::createStringError(
- std::make_error_code(std::errc::invalid_argument),
- "There was no FormatInfo registered for summary name '" +
- SummaryName.str() + "'");
- }
- const auto &InfoEntry = InfoIt->second;
- assert(InfoEntry.ForSummary == SummaryName);
-
- auto Output = InfoEntry.Serialize(*Data, *this);
-
- std::string AnalysisFilePath =
- (Path + "/" + SummaryName.str() + ".special").str();
- llvm::raw_fd_ostream AnalysisOutputFile(AnalysisFilePath, EC);
- if (EC) {
- return llvm::createStringError(
- EC, "Failed to create file '" + AnalysisFilePath +
- "': " + llvm::StringRef(EC.message()));
- }
- AnalysisOutputFile << Output.MockRepresentation;
- }
- }
-
- std::string ManifestFilePath = (Path + "/analyses.txt").str();
- llvm::raw_fd_ostream ManifestFile(ManifestFilePath, EC);
- if (EC) {
- return llvm::createStringError(
- EC, "Failed to create manifest file '" + ManifestFilePath +
- "': " + llvm::StringRef(EC.message()));
- }
-
- interleave(map_range(Analyses, std::mem_fn(&SummaryName::str)), ManifestFile,
- "\n");
- ManifestFile << "\n";
-
- return llvm::Error::success();
-}
-
-static SerializationFormatRegistry::Add<MockSerializationFormat>
- RegisterFormat("MockSerializationFormat",
- "A serialization format for testing");
-
-llvm::Expected<TUSummaryEncoding>
-MockSerializationFormat::readTUSummaryEncoding(llvm::StringRef Path) {
- llvm_unreachable(
- "MockSerializationFormat does not support TUSummaryEncoding");
-}
-
-llvm::Error MockSerializationFormat::writeTUSummaryEncoding(
- const TUSummaryEncoding &SummaryEncoding, llvm::StringRef Path) {
- llvm_unreachable(
- "MockSerializationFormat does not support TUSummaryEncoding");
-}
-
-llvm::Expected<LUSummary>
-MockSerializationFormat::readLUSummary(llvm::StringRef Path) {
- llvm_unreachable("MockSerializationFormat does not support LUSummary");
-}
-
-llvm::Error MockSerializationFormat::writeLUSummary(const LUSummary &Summary,
- llvm::StringRef Path) {
- llvm_unreachable("MockSerializationFormat does not support LUSummary");
-}
-
-llvm::Expected<LUSummaryEncoding>
-MockSerializationFormat::readLUSummaryEncoding(llvm::StringRef Path) {
- llvm_unreachable(
- "MockSerializationFormat does not support LUSummaryEncoding");
-}
-
-llvm::Error MockSerializationFormat::writeLUSummaryEncoding(
- const LUSummaryEncoding &SummaryEncoding, llvm::StringRef Path) {
- llvm_unreachable(
- "MockSerializationFormat does not support LUSummaryEncoding");
-}
-
-llvm::Expected<WPASuite>
-MockSerializationFormat::readWPASuite(llvm::StringRef Path) {
- llvm_unreachable("MockSerializationFormat does not support WPASuite");
-}
-
-llvm::Error MockSerializationFormat::writeWPASuite(const WPASuite &Suite,
- llvm::StringRef Path) {
- llvm_unreachable("MockSerializationFormat does not support WPASuite");
-}
-
-llvm::Expected<Artifact>
-MockSerializationFormat::readArtifact(llvm::StringRef Path) {
- llvm_unreachable("MockSerializationFormat does not support readArtifact");
-}
-
-llvm::Error MockSerializationFormat::writeArtifact(const Artifact &A,
- llvm::StringRef Path) {
- llvm_unreachable("MockSerializationFormat does not support writeArtifact");
-}
-
-llvm::Expected<ArtifactEncoding>
-MockSerializationFormat::readArtifactEncoding(llvm::StringRef Path) {
- llvm_unreachable(
- "MockSerializationFormat does not support readArtifactEncoding");
-}
-
-llvm::Error
-MockSerializationFormat::writeArtifactEncoding(const ArtifactEncoding &E,
- llvm::StringRef Path) {
- llvm_unreachable(
- "MockSerializationFormat does not support writeArtifactEncoding");
-}
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h
deleted file mode 100644
index 2f74f7216ba16..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h
+++ /dev/null
@@ -1,85 +0,0 @@
-//===- MockSerializationFormat.h --------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h"
-#include "clang/Support/Compiler.h"
-#include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/Support/Registry.h"
-#include <string>
-
-namespace clang::ssaf {
-
-class MockSerializationFormat final : public SerializationFormat {
-public:
- MockSerializationFormat();
-
- llvm::Expected<TUSummary> readTUSummary(llvm::StringRef Path) override;
-
- llvm::Error writeTUSummary(const TUSummary &Summary,
- llvm::StringRef Path) override;
-
- llvm::Expected<TUSummaryEncoding>
- readTUSummaryEncoding(llvm::StringRef Path) override;
-
- llvm::Error writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding,
- llvm::StringRef Path) override;
-
- llvm::Expected<LUSummary> readLUSummary(llvm::StringRef Path) override;
-
- llvm::Error writeLUSummary(const LUSummary &Summary,
- llvm::StringRef Path) override;
-
- llvm::Expected<LUSummaryEncoding>
- readLUSummaryEncoding(llvm::StringRef Path) override;
-
- llvm::Error writeLUSummaryEncoding(const LUSummaryEncoding &SummaryEncoding,
- llvm::StringRef Path) override;
-
- llvm::Expected<Artifact> readArtifact(llvm::StringRef Path) override;
-
- llvm::Error writeArtifact(const Artifact &A, llvm::StringRef Path) override;
-
- llvm::Expected<ArtifactEncoding>
- readArtifactEncoding(llvm::StringRef Path) override;
-
- llvm::Error writeArtifactEncoding(const ArtifactEncoding &E,
- llvm::StringRef Path) override;
-
- llvm::Expected<WPASuite> readWPASuite(llvm::StringRef Path) override;
-
- llvm::Error writeWPASuite(const WPASuite &Suite,
- llvm::StringRef Path) override;
-
- /// Lists what analyses implement this particular serialisation format.
- void forEachRegisteredAnalysis(
- llvm::function_ref<void(llvm::StringRef Name, llvm::StringRef Desc)>
- Callback) const override;
-
- struct SpecialFileRepresentation {
- std::string MockRepresentation;
- };
-
- using SerializerFn = llvm::function_ref<SpecialFileRepresentation(
- const EntitySummary &, MockSerializationFormat &)>;
- using DeserializerFn = llvm::function_ref<std::unique_ptr<EntitySummary>(
- const SpecialFileRepresentation &, EntityIdTable &)>;
-
- using FormatInfo = FormatInfoEntry<SerializerFn, DeserializerFn>;
- std::map<SummaryName, FormatInfo> FormatInfos;
-};
-
-} // namespace clang::ssaf
-
-LLVM_DECLARE_REGISTRY(
- llvm::Registry<clang::ssaf::MockSerializationFormat::FormatInfo>)
-
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
deleted file mode 100644
index 1d5a33900d3c2..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor1.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- MockSummaryExtractor1.cpp ------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "MockTUSummaryBuilder.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-
-using namespace clang;
-using namespace ssaf;
-
-namespace {
-class MockSummaryExtractor1 : public TUSummaryExtractor {
-public:
- MockSummaryExtractor1(TUSummaryBuilder &Builder)
- : TUSummaryExtractor(Builder) {
- getFakeBuilder().sendMessage(
- "MockSummaryExtractor1 constructor was invoked");
- }
-
- ~MockSummaryExtractor1() {
- getFakeBuilder().sendMessage(
- "MockSummaryExtractor1 destructor was invoked");
- }
-
- void HandleTranslationUnit(ASTContext &Ctx) override {
- getFakeBuilder().sendMessage(
- "MockSummaryExtractor1 HandleTranslationUnit was invoked");
- }
-
- MockTUSummaryBuilder &getFakeBuilder() {
- return static_cast<MockTUSummaryBuilder &>(SummaryBuilder);
- }
-};
-
-} // namespace
-
-static TUSummaryExtractorRegistry::Add<MockSummaryExtractor1>
- RegisterExtractor("MockSummaryExtractor1", "Mock summary extractor 1");
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
deleted file mode 100644
index ab78b5c135faa..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSummaryExtractor2.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-//===- MockSummaryExtractor2.cpp ------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "MockTUSummaryBuilder.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-
-using namespace clang;
-using namespace ssaf;
-
-namespace {
-class MockSummaryExtractor2 : public TUSummaryExtractor {
-public:
- MockSummaryExtractor2(TUSummaryBuilder &Builder)
- : TUSummaryExtractor(Builder) {
- getFakeBuilder().sendMessage(
- "MockSummaryExtractor2 constructor was invoked");
- }
-
- ~MockSummaryExtractor2() {
- getFakeBuilder().sendMessage(
- "MockSummaryExtractor2 destructor was invoked");
- }
-
- void HandleTranslationUnit(ASTContext &Ctx) override {
- getFakeBuilder().sendMessage(
- "MockSummaryExtractor2 HandleTranslationUnit was invoked");
- }
-
- MockTUSummaryBuilder &getFakeBuilder() {
- return static_cast<MockTUSummaryBuilder &>(SummaryBuilder);
- }
-};
-
-} // namespace
-
-static TUSummaryExtractorRegistry::Add<MockSummaryExtractor2>
- RegisterExtractor("MockSummaryExtractor2", "Mock summary extractor 2");
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockTUSummaryBuilder.h b/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockTUSummaryBuilder.h
deleted file mode 100644
index 389faed325050..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/MockTUSummaryBuilder.h
+++ /dev/null
@@ -1,31 +0,0 @@
-//===- MockTUSummaryBuilder.h -----------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKTUSUMMARYBUILDER_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKTUSUMMARYBUILDER_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace clang::ssaf {
-
-class MockTUSummaryBuilder : public TUSummaryBuilder {
-public:
- using TUSummaryBuilder::TUSummaryBuilder;
- void sendMessage(llvm::Twine Message) { Stream << Message << '\n'; }
- std::string consumeMessages() { return std::move(OutputBuffer); }
-
-private:
- std::string OutputBuffer;
- llvm::raw_string_ostream Stream = llvm::raw_string_ostream{OutputBuffer};
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_REGISTRIES_MOCKTUSUMMARYBUILDER_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/SerializationFormatRegistryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/SerializationFormatRegistryTest.cpp
deleted file mode 100644
index b55754a622e31..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/SerializationFormatRegistryTest.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-//===- SummaryExtractorRegistryTest.cpp -----------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/ScopeExit.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gtest/gtest.h"
-#include <memory>
-
-using namespace llvm;
-using namespace clang;
-using namespace ssaf;
-
-// Returns the file name and content in a map.
-static std::map<std::string, std::string> readFilesFromDir(StringRef DirPath) {
- std::map<std::string, std::string> Result;
- std::error_code EC;
-
- for (sys::fs::directory_iterator It(DirPath, EC), End; It != End && !EC;
- It.increment(EC)) {
- StringRef FilePath = It->path();
-
- if (sys::fs::is_directory(FilePath))
- continue;
-
- auto BufferOrErr = MemoryBuffer::getFile(FilePath);
- if (!BufferOrErr)
- continue;
-
- // Store only the filename (relative to DirPath).
- StringRef FileName = sys::path::filename(FilePath);
- Result[FileName.str()] = BufferOrErr.get()->getBuffer().str();
- }
-
- return Result;
-}
-namespace {
-
-TEST(SerializationFormatRegistryTest, isFormatRegistered) {
- EXPECT_FALSE(isFormatRegistered("Non-existent-format"));
- EXPECT_TRUE(isFormatRegistered("MockSerializationFormat"));
-}
-
-TEST(SerializationFormatRegistryTest, EnumeratingRegistryEntries) {
- auto Formats = SerializationFormatRegistry::entries();
- ASSERT_GE(std::distance(Formats.begin(), Formats.end()), 1U);
- EXPECT_TRUE(llvm::any_of(Formats, [](const auto &Entry) {
- return StringRef(Entry.getName()) == "MockSerializationFormat";
- }));
-}
-
-TEST(SerializationFormatRegistryTest, Roundtrip) {
- // Create temporary input directory
- SmallString<128> InputDir;
- std::error_code EC = sys::fs::createUniqueDirectory("ssaf-input", InputDir);
- ASSERT_FALSE(EC) << "Failed to create input directory: " << EC.message();
- llvm::scope_exit CleanupInputOnExit(
- [&] { sys::fs::remove_directories(InputDir); });
-
- // Create input files
- SmallString<128> AnalysesFile = InputDir;
- sys::path::append(AnalysesFile, "analyses.txt");
- {
- raw_fd_ostream OS(AnalysesFile, EC);
- ASSERT_FALSE(EC) << "Failed to create analyses.txt: " << EC.message();
- OS << "FancyAnalysis\n";
- }
-
- SmallString<128> FancyAnalysisFile = InputDir;
- sys::path::append(FancyAnalysisFile, "FancyAnalysis.special");
- {
- raw_fd_ostream OS(FancyAnalysisFile, EC);
- ASSERT_FALSE(EC) << "Failed to create FancyAnalysis.special: "
- << EC.message();
- OS << "Some FancyAnalysisData...";
- }
-
- std::unique_ptr<SerializationFormat> Format =
- makeFormat("MockSerializationFormat");
- ASSERT_TRUE(Format);
-
- auto LoadedSummaryOrErr = Format->readTUSummary(InputDir);
- ASSERT_THAT_EXPECTED(LoadedSummaryOrErr, Succeeded());
- TUSummary LoadedSummary = std::move(*LoadedSummaryOrErr);
-
- // Create a temporary output directory
- SmallString<128> OutputDir;
- EC = sys::fs::createUniqueDirectory("ssaf-test", OutputDir);
- ASSERT_FALSE(EC) << "Failed to create temporary directory: " << EC.message();
- llvm::scope_exit CleanupOnExit(
- [&] { sys::fs::remove_directories(OutputDir); });
-
- auto WriteErr = Format->writeTUSummary(LoadedSummary, OutputDir);
- ASSERT_THAT_ERROR(std::move(WriteErr), Succeeded());
-
- EXPECT_EQ(readFilesFromDir(OutputDir),
- (std::map<std::string, std::string>{
- {"analyses.txt", "FancyAnalysis\n"},
- {"FancyAnalysis.special", "Some FancyAnalysisData..."},
- }));
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Registries/SummaryExtractorRegistryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Registries/SummaryExtractorRegistryTest.cpp
deleted file mode 100644
index 2294c045d554b..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Registries/SummaryExtractorRegistryTest.cpp
+++ /dev/null
@@ -1,113 +0,0 @@
-//===- SummaryExtractorRegistryTest.cpp -----------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "MockTUSummaryBuilder.h"
-#include "clang/Frontend/MultiplexConsumer.h"
-#include "clang/Frontend/SSAFOptions.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/StringRef.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <memory>
-
-using namespace clang;
-using namespace ssaf;
-
-[[nodiscard]]
-static TUSummary makeFakeSummary() {
- return TUSummary(
- llvm::Triple("arm64-apple-macosx"),
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp"));
-}
-
-namespace {
-
-TEST(SummaryExtractorRegistryTest, isTUSummaryExtractorRegistered) {
- EXPECT_FALSE(isTUSummaryExtractorRegistered("Non-existent-extractor"));
- EXPECT_TRUE(isTUSummaryExtractorRegistered("MockSummaryExtractor1"));
- EXPECT_TRUE(isTUSummaryExtractorRegistered("MockSummaryExtractor2"));
-}
-
-TEST(SummaryExtractorRegistryTest, EnumeratingRegistryEntries) {
- std::set<llvm::StringRef> ActualNames;
- for (const auto &Entry : TUSummaryExtractorRegistry::entries()) {
- bool Inserted = ActualNames.insert(Entry.getName()).second;
- EXPECT_TRUE(Inserted);
- }
-
- EXPECT_THAT(ActualNames, testing::IsSupersetOf({"MockSummaryExtractor1",
- "MockSummaryExtractor2"}));
-}
-
-TEST(SummaryExtractorRegistryTest, InstantiatingExtractor1) {
- SSAFOptions Opts;
- TUSummary Summary = makeFakeSummary();
- MockTUSummaryBuilder FakeBuilder(Summary, Opts);
- {
- auto Consumer =
- makeTUSummaryExtractor("MockSummaryExtractor1", FakeBuilder);
- EXPECT_TRUE(Consumer);
- EXPECT_EQ(FakeBuilder.consumeMessages(),
- "MockSummaryExtractor1 constructor was invoked\n");
- }
- EXPECT_EQ(FakeBuilder.consumeMessages(),
- "MockSummaryExtractor1 destructor was invoked\n");
-}
-
-TEST(SummaryExtractorRegistryTest, InstantiatingExtractor2) {
- SSAFOptions Opts;
- TUSummary Summary = makeFakeSummary();
- MockTUSummaryBuilder FakeBuilder(Summary, Opts);
- {
- auto Consumer =
- makeTUSummaryExtractor("MockSummaryExtractor2", FakeBuilder);
- EXPECT_TRUE(Consumer);
- EXPECT_EQ(FakeBuilder.consumeMessages(),
- "MockSummaryExtractor2 constructor was invoked\n");
- }
- EXPECT_EQ(FakeBuilder.consumeMessages(),
- "MockSummaryExtractor2 destructor was invoked\n");
-}
-
-TEST(SummaryExtractorRegistryTest, InvokingExtractors) {
- SSAFOptions Opts;
- TUSummary Summary = makeFakeSummary();
- MockTUSummaryBuilder FakeBuilder(Summary, Opts);
- std::vector<std::unique_ptr<ASTConsumer>> Consumers;
- for (std::string Name : {"MockSummaryExtractor1", "MockSummaryExtractor2"}) {
- auto Consumer = makeTUSummaryExtractor(Name, FakeBuilder);
- ASSERT_TRUE(Consumer);
- Consumers.push_back(std::move(Consumer));
- }
- EXPECT_EQ(FakeBuilder.consumeMessages(),
- "MockSummaryExtractor1 constructor was invoked\n"
- "MockSummaryExtractor2 constructor was invoked\n");
-
- {
- MultiplexConsumer Multiplexer(std::move(Consumers));
- auto AST = tooling::buildASTFromCode(R"cpp(int x = 42;)cpp");
- ASSERT_TRUE(AST);
-
- Multiplexer.HandleTranslationUnit(AST->getASTContext());
- EXPECT_EQ(FakeBuilder.consumeMessages(),
- "MockSummaryExtractor1 HandleTranslationUnit was invoked\n"
- "MockSummaryExtractor2 HandleTranslationUnit was invoked\n");
- }
-
- std::string OwnedMessages = FakeBuilder.consumeMessages();
- StringRef View = OwnedMessages;
- EXPECT_EQ(View.count('\n'), 2u);
-
- // The destruction order is indeterminate.
- EXPECT_TRUE(View.contains("MockSummaryExtractor1 destructor was invoked\n"));
- EXPECT_TRUE(View.contains("MockSummaryExtractor2 destructor was invoked\n"));
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.cpp
deleted file mode 100644
index 57258145b5dd9..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.cpp
+++ /dev/null
@@ -1,639 +0,0 @@
-//===- JSONFormatTest.cpp -------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Shared normalization helpers for SSAF JSON serialization format unit tests.
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONFormatTest.h"
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/Registry.h"
-#include "llvm/Testing/Support/Error.h"
-#ifndef _WIN32
-#include <unistd.h>
-#endif
-
-using namespace clang::ssaf;
-using namespace llvm;
-using PathString = JSONFormatTest::PathString;
-
-// ============================================================================
-// Test Fixture
-// ============================================================================
-
-void JSONFormatTest::SetUp() {
- std::error_code EC =
- llvm::sys::fs::createUniqueDirectory("json-format-test", TestDir);
- ASSERT_FALSE(EC) << "Failed to create temp directory: " << EC.message();
-}
-
-void JSONFormatTest::TearDown() { llvm::sys::fs::remove_directories(TestDir); }
-
-JSONFormatTest::PathString
-JSONFormatTest::makePath(llvm::StringRef FileOrDirectoryName) const {
- PathString FullPath = TestDir;
- llvm::sys::path::append(FullPath, FileOrDirectoryName);
-
- return FullPath;
-}
-
-PathString JSONFormatTest::makePath(llvm::StringRef Dir,
- llvm::StringRef FileName) const {
- PathString FullPath = TestDir;
- llvm::sys::path::append(FullPath, Dir, FileName);
-
- return FullPath;
-}
-
-llvm::Expected<PathString>
-JSONFormatTest::makeDirectory(llvm::StringRef DirectoryName) const {
- PathString DirPath = makePath(DirectoryName);
-
- std::error_code EC = llvm::sys::fs::create_directory(DirPath);
- if (EC) {
- return llvm::createStringError(EC, "Failed to create directory '%s': %s",
- DirPath.c_str(), EC.message().c_str());
- }
-
- return DirPath;
-}
-
-llvm::Expected<PathString>
-JSONFormatTest::makeSymlink(llvm::StringRef TargetFileName,
- llvm::StringRef SymlinkFileName) const {
- PathString TargetPath = makePath(TargetFileName);
- PathString SymlinkPath = makePath(SymlinkFileName);
-
- std::error_code EC = llvm::sys::fs::create_link(TargetPath, SymlinkPath);
- if (EC) {
- return llvm::createStringError(
- EC, "Failed to create symlink '%s' -> '%s': %s", SymlinkPath.c_str(),
- TargetPath.c_str(), EC.message().c_str());
- }
-
- return SymlinkPath;
-}
-
-llvm::Error JSONFormatTest::setPermission(llvm::StringRef FileName,
- llvm::sys::fs::perms Perms) const {
- PathString Path = makePath(FileName);
-
- std::error_code EC = llvm::sys::fs::setPermissions(Path, Perms);
- if (EC) {
- return llvm::createStringError(EC, "Failed to set permissions on '%s': %s",
- Path.c_str(), EC.message().c_str());
- }
-
- return llvm::Error::success();
-}
-
-bool JSONFormatTest::permissionsAreEnforced() const {
-#ifdef _WIN32
- return false;
-#else
- if (getuid() == 0) {
- return false;
- }
-
- // Write a probe file, remove read permission, and try to open it.
- PathString ProbePath = makePath("perm-probe.json");
-
- {
- std::error_code EC;
- llvm::raw_fd_ostream OS(ProbePath, EC);
- if (EC) {
- return true; // Probe setup failed; assume enforced to avoid
- // silently suppressing the test.
- }
- OS << "{}";
- }
-
- std::error_code PermEC = llvm::sys::fs::setPermissions(
- ProbePath, llvm::sys::fs::perms::owner_write);
- if (PermEC) {
- return true; // Probe setup failed; assume enforced to avoid
- // silently suppressing the test.
- }
-
- auto Buffer = llvm::MemoryBuffer::getFile(ProbePath, /*IsText=*/true);
- bool Enforced = !Buffer; // If open failed, permissions are enforced.
-
- // Restore permissions so TearDown can clean up the temp directory.
- llvm::sys::fs::setPermissions(ProbePath, llvm::sys::fs::perms::all_all);
-
- return Enforced;
-#endif
-}
-
-llvm::Expected<llvm::json::Value>
-JSONFormatTest::readJSONFromFile(llvm::StringRef FileName) const {
- PathString FilePath = makePath(FileName);
-
- auto BufferOrError = llvm::MemoryBuffer::getFile(FilePath, /*IsText=*/true);
- if (!BufferOrError) {
- return llvm::createStringError(BufferOrError.getError(),
- "Failed to read file: %s", FilePath.c_str());
- }
-
- llvm::Expected<llvm::json::Value> ExpectedValue =
- llvm::json::parse(BufferOrError.get()->getBuffer());
- if (!ExpectedValue) {
- return ExpectedValue.takeError();
- }
-
- return *ExpectedValue;
-}
-
-llvm::Expected<PathString>
-JSONFormatTest::writeJSON(llvm::StringRef JSON,
- llvm::StringRef FileName) const {
- PathString FilePath = makePath(FileName);
-
- std::error_code EC;
- llvm::raw_fd_ostream OS(FilePath, EC);
- if (EC) {
- return llvm::createStringError(EC, "Failed to create file '%s': %s",
- FilePath.c_str(), EC.message().c_str());
- }
-
- OS << JSON;
- OS.close();
-
- if (OS.has_error()) {
- return llvm::createStringError(
- OS.error(), "Failed to write to file '%s': %s", FilePath.c_str(),
- OS.error().message().c_str());
- }
-
- return FilePath;
-}
-
-// ============================================================================
-// Summary JSON Normalization Helpers
-// ============================================================================
-
-namespace {
-
-llvm::Error normalizeIDTable(json::Array &IDTable,
- llvm::StringRef SummaryClassName) {
- for (const auto &[Index, Entry] : llvm::enumerate(IDTable)) {
- const auto *EntryObj = Entry.getAsObject();
- if (!EntryObj) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: id_table entry at index %zu "
- "is not an object",
- SummaryClassName.data(), Index);
- }
-
- const auto *IDValue = EntryObj->get("id");
- if (!IDValue) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: id_table entry at index %zu "
- "does not contain an 'id' field",
- SummaryClassName.data(), Index);
- }
-
- if (!IDValue->getAsUINT64()) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: id_table entry at index %zu "
- "'id' field is not a valid entity id integer",
- SummaryClassName.data(), Index);
- }
- }
-
- // Safe to dereference: all entries were validated above.
- llvm::sort(IDTable, [](const json::Value &A, const json::Value &B) {
- return *A.getAsObject()->get("id")->getAsUINT64() <
- *B.getAsObject()->get("id")->getAsUINT64();
- });
-
- return llvm::Error::success();
-}
-
-llvm::Error normalizeLinkageTable(json::Array &LinkageTable,
- llvm::StringRef SummaryClassName) {
- for (const auto &[Index, Entry] : llvm::enumerate(LinkageTable)) {
- const auto *EntryObj = Entry.getAsObject();
- if (!EntryObj) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: linkage_table entry at index "
- "%zu is not an object",
- SummaryClassName.data(), Index);
- }
-
- const auto *IDValue = EntryObj->get("id");
- if (!IDValue) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: linkage_table entry at index "
- "%zu does not contain an 'id' field",
- SummaryClassName.data(), Index);
- }
-
- if (!IDValue->getAsUINT64()) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: linkage_table entry at index "
- "%zu 'id' field is not a valid entity id integer",
- SummaryClassName.data(), Index);
- }
- }
-
- // Safe to dereference: all entries were validated above.
- llvm::sort(LinkageTable, [](const json::Value &A, const json::Value &B) {
- return *A.getAsObject()->get("id")->getAsUINT64() <
- *B.getAsObject()->get("id")->getAsUINT64();
- });
-
- return llvm::Error::success();
-}
-
-llvm::Error normalizeSummaryData(json::Array &SummaryData, size_t DataIndex,
- llvm::StringRef SummaryClassName) {
- for (const auto &[SummaryIndex, SummaryEntry] :
- llvm::enumerate(SummaryData)) {
- const auto *SummaryEntryObj = SummaryEntry.getAsObject();
- if (!SummaryEntryObj) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: data entry at index %zu, "
- "summary_data entry at index %zu is not an object",
- SummaryClassName.data(), DataIndex, SummaryIndex);
- }
-
- const auto *EntityIDValue = SummaryEntryObj->get("entity_id");
- if (!EntityIDValue) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: data entry at index %zu, "
- "summary_data entry at index %zu does not contain an "
- "'entity_id' field",
- SummaryClassName.data(), DataIndex, SummaryIndex);
- }
-
- if (!EntityIDValue->getAsUINT64()) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: data entry at index %zu, "
- "summary_data entry at index %zu 'entity_id' field is not "
- "a valid entity id integer",
- SummaryClassName.data(), DataIndex, SummaryIndex);
- }
- }
-
- // Safe to dereference: all entries were validated above.
- llvm::sort(SummaryData, [](const json::Value &A, const json::Value &B) {
- return *A.getAsObject()->get("entity_id")->getAsUINT64() <
- *B.getAsObject()->get("entity_id")->getAsUINT64();
- });
-
- return llvm::Error::success();
-}
-
-llvm::Error normalizeData(json::Array &Data, llvm::StringRef SummaryClassName) {
- for (const auto &[DataIndex, DataEntry] : llvm::enumerate(Data)) {
- auto *DataEntryObj = DataEntry.getAsObject();
- if (!DataEntryObj) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: data entry at index %zu "
- "is not an object",
- SummaryClassName.data(), DataIndex);
- }
-
- if (!DataEntryObj->getString("summary_name")) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: data entry at index %zu "
- "does not contain a 'summary_name' string field",
- SummaryClassName.data(), DataIndex);
- }
-
- auto *SummaryData = DataEntryObj->getArray("summary_data");
- if (!SummaryData) {
- return createStringError(
- inconvertibleErrorCode(),
- "Cannot normalize %s JSON: data entry at index %zu "
- "does not contain a 'summary_data' array field",
- SummaryClassName.data(), DataIndex);
- }
-
- if (auto Err =
- normalizeSummaryData(*SummaryData, DataIndex, SummaryClassName)) {
- return Err;
- }
- }
-
- // Safe to dereference: all entries were validated above.
- llvm::sort(Data, [](const json::Value &A, const json::Value &B) {
- return *A.getAsObject()->getString("summary_name") <
- *B.getAsObject()->getString("summary_name");
- });
-
- return llvm::Error::success();
-}
-
-Expected<json::Value> normalizeSummaryJSON(json::Value Val,
- llvm::StringRef SummaryClassName) {
- auto *Obj = Val.getAsObject();
- if (!Obj) {
- return createStringError(inconvertibleErrorCode(),
- "Cannot normalize %s JSON: expected an object",
- SummaryClassName.data());
- }
-
- auto *IDTable = Obj->getArray("id_table");
- if (!IDTable) {
- return createStringError(inconvertibleErrorCode(),
- "Cannot normalize %s JSON: 'id_table' "
- "field is either missing or has the wrong type",
- SummaryClassName.data());
- }
- if (auto Err = normalizeIDTable(*IDTable, SummaryClassName)) {
- return std::move(Err);
- }
-
- auto *LinkageTable = Obj->getArray("linkage_table");
- if (!LinkageTable) {
- return createStringError(inconvertibleErrorCode(),
- "Cannot normalize %s JSON: 'linkage_table' "
- "field is either missing or has the wrong type",
- SummaryClassName.data());
- }
- if (auto Err = normalizeLinkageTable(*LinkageTable, SummaryClassName)) {
- return std::move(Err);
- }
-
- auto *Data = Obj->getArray("data");
- if (!Data) {
- return createStringError(inconvertibleErrorCode(),
- "Cannot normalize %s JSON: 'data' "
- "field is either missing or has the wrong type",
- SummaryClassName.data());
- }
- if (auto Err = normalizeData(*Data, SummaryClassName)) {
- return std::move(Err);
- }
-
- return Val;
-}
-
-} // namespace
-
-// ============================================================================
-// SummaryTest Fixture Implementation
-// ============================================================================
-
-llvm::Error SummaryTest::readFromString(StringRef JSON,
- StringRef FileName) const {
- auto ExpectedFilePath = writeJSON(JSON, FileName);
- if (!ExpectedFilePath) {
- return ExpectedFilePath.takeError();
- }
- return GetParam().ReadFromFile(*ExpectedFilePath);
-}
-
-llvm::Error SummaryTest::readFromFile(StringRef FileName) const {
- return GetParam().ReadFromFile(makePath(FileName));
-}
-
-llvm::Error SummaryTest::writeEmpty(StringRef FileName) const {
- return GetParam().WriteEmpty(makePath(FileName));
-}
-
-llvm::Error SummaryTest::readWriteRoundTrip(StringRef InputFileName,
- StringRef OutputFileName) const {
- return GetParam().ReadWriteRoundTrip(makePath(InputFileName),
- makePath(OutputFileName));
-}
-
-void SummaryTest::readWriteCompare(StringRef JSON) const {
- const PathString InputFileName("input.json");
- const PathString OutputFileName("output.json");
-
- auto ExpectedInputFilePath = writeJSON(JSON, InputFileName);
- ASSERT_THAT_EXPECTED(ExpectedInputFilePath, Succeeded());
-
- ASSERT_THAT_ERROR(readWriteRoundTrip(InputFileName, OutputFileName),
- Succeeded());
-
- auto ExpectedInputJSON = readJSONFromFile(InputFileName);
- ASSERT_THAT_EXPECTED(ExpectedInputJSON, Succeeded());
-
- auto ExpectedOutputJSON = readJSONFromFile(OutputFileName);
- ASSERT_THAT_EXPECTED(ExpectedOutputJSON, Succeeded());
-
- auto ExpectedNormalizedInputJSON =
- normalizeSummaryJSON(*ExpectedInputJSON, GetParam().SummaryClassName);
- ASSERT_THAT_EXPECTED(ExpectedNormalizedInputJSON, Succeeded());
-
- auto ExpectedNormalizedOutputJSON =
- normalizeSummaryJSON(*ExpectedOutputJSON, GetParam().SummaryClassName);
- ASSERT_THAT_EXPECTED(ExpectedNormalizedOutputJSON, Succeeded());
-
- ASSERT_EQ(*ExpectedNormalizedInputJSON, *ExpectedNormalizedOutputJSON)
- << "Serialization is broken: input is different from output\n"
- << "Input: "
- << llvm::formatv("{0:2}", *ExpectedNormalizedInputJSON).str() << "\n"
- << "Output: "
- << llvm::formatv("{0:2}", *ExpectedNormalizedOutputJSON).str();
-}
-
-namespace {
-
-// ============================================================================
-// First Test Analysis - Simple analysis for testing JSON serialization.
-// ============================================================================
-
-json::Object serializePairsEntitySummaryForJSONFormatTest(
- const EntitySummary &Summary, JSONFormat::EntityIdToJSONFn ToJSON) {
- const auto &TA =
- static_cast<const PairsEntitySummaryForJSONFormatTest &>(Summary);
- json::Array PairsArray;
- for (const auto &[First, Second] : TA.Pairs) {
- PairsArray.push_back(json::Object{
- {"first", ToJSON(First)},
- {"second", ToJSON(Second)},
- });
- }
- return json::Object{{"pairs", std::move(PairsArray)}};
-}
-
-Expected<std::unique_ptr<EntitySummary>>
-deserializePairsEntitySummaryForJSONFormatTest(
- const json::Object &Obj, EntityIdTable &IdTable,
- JSONFormat::EntityIdFromJSONFn FromJSON) {
- auto Result = std::make_unique<PairsEntitySummaryForJSONFormatTest>();
- const json::Array *PairsArray = Obj.getArray("pairs");
- if (!PairsArray) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid field 'pairs'");
- }
- for (const auto &[Index, Value] : llvm::enumerate(*PairsArray)) {
- const json::Object *Pair = Value.getAsObject();
- if (!Pair) {
- return createStringError(
- inconvertibleErrorCode(),
- "pairs element at index %zu is not a JSON object", Index);
- }
- const json::Object *FirstObj = Pair->getObject("first");
- if (!FirstObj) {
- return createStringError(
- inconvertibleErrorCode(),
- "missing or invalid 'first' field at index '%zu'", Index);
- }
- const json::Object *SecondObj = Pair->getObject("second");
- if (!SecondObj) {
- return createStringError(
- inconvertibleErrorCode(),
- "missing or invalid 'second' field at index '%zu'", Index);
- }
- auto ExpectedFirst = FromJSON(*FirstObj);
- if (!ExpectedFirst) {
- return createStringError(inconvertibleErrorCode(),
- "invalid 'first' entity id at index '%zu': %s",
- Index,
- toString(ExpectedFirst.takeError()).c_str());
- }
- auto ExpectedSecond = FromJSON(*SecondObj);
- if (!ExpectedSecond) {
- return createStringError(inconvertibleErrorCode(),
- "invalid 'second' entity id at index '%zu': %s",
- Index,
- toString(ExpectedSecond.takeError()).c_str());
- }
- Result->Pairs.emplace_back(*ExpectedFirst, *ExpectedSecond);
- }
- return std::move(Result);
-}
-
-struct PairsEntitySummaryForJSONFormatTestFormatInfo final
- : JSONFormat::FormatInfo {
- PairsEntitySummaryForJSONFormatTestFormatInfo()
- : JSONFormat::FormatInfo(
- SummaryName("PairsEntitySummaryForJSONFormatTest"),
- serializePairsEntitySummaryForJSONFormatTest,
- deserializePairsEntitySummaryForJSONFormatTest) {}
-};
-
-llvm::Registry<JSONFormat::FormatInfo>::Add<
- PairsEntitySummaryForJSONFormatTestFormatInfo>
- RegisterPairsEntitySummaryForJSONFormatTest(
- "PairsEntitySummaryForJSONFormatTest",
- "Format info for PairsArrayEntitySummary");
-
-// ============================================================================
-// Second Test Analysis - Simple analysis for multi-summary round-trip tests.
-// ============================================================================
-
-json::Object
-serializeTagsEntitySummaryForJSONFormatTest(const EntitySummary &Summary,
- JSONFormat::EntityIdToJSONFn) {
- const auto &TA =
- static_cast<const TagsEntitySummaryForJSONFormatTest &>(Summary);
- json::Array TagsArray;
- for (const auto &Tag : TA.Tags) {
- TagsArray.push_back(Tag);
- }
- return json::Object{{"tags", std::move(TagsArray)}};
-}
-
-Expected<std::unique_ptr<EntitySummary>>
-deserializeTagsEntitySummaryForJSONFormatTest(const json::Object &Obj,
- EntityIdTable &,
- JSONFormat::EntityIdFromJSONFn) {
- auto Result = std::make_unique<TagsEntitySummaryForJSONFormatTest>();
- const json::Array *TagsArray = Obj.getArray("tags");
- if (!TagsArray) {
- return createStringError(inconvertibleErrorCode(),
- "missing or invalid field 'tags'");
- }
- for (const auto &[Index, Value] : llvm::enumerate(*TagsArray)) {
- auto Tag = Value.getAsString();
- if (!Tag) {
- return createStringError(inconvertibleErrorCode(),
- "tags element at index %zu is not a string",
- Index);
- }
- Result->Tags.push_back(Tag->str());
- }
- return std::move(Result);
-}
-
-struct TagsEntitySummaryForJSONFormatTestFormatInfo final
- : JSONFormat::FormatInfo {
- TagsEntitySummaryForJSONFormatTestFormatInfo()
- : JSONFormat::FormatInfo(
- SummaryName("TagsEntitySummaryForJSONFormatTest"),
- serializeTagsEntitySummaryForJSONFormatTest,
- deserializeTagsEntitySummaryForJSONFormatTest) {}
-};
-
-llvm::Registry<JSONFormat::FormatInfo>::Add<
- TagsEntitySummaryForJSONFormatTestFormatInfo>
- RegisterTagsEntitySummaryForJSONFormatTest(
- "TagsEntitySummaryForJSONFormatTest",
- "Format info for TagsEntitySummary");
-
-// ============================================================================
-// NullEntitySummaryForJSONFormatTest - For null data checks
-// ============================================================================
-
-struct NullEntitySummaryForJSONFormatTestFormatInfo final
- : JSONFormat::FormatInfo {
- NullEntitySummaryForJSONFormatTestFormatInfo()
- : JSONFormat::FormatInfo(
- SummaryName("NullEntitySummaryForJSONFormatTest"),
- [](const EntitySummary &, JSONFormat::EntityIdToJSONFn)
- -> json::Object { return json::Object{}; },
- [](const json::Object &, EntityIdTable &,
- JSONFormat::EntityIdFromJSONFn)
- -> llvm::Expected<std::unique_ptr<EntitySummary>> {
- return nullptr;
- }) {}
-};
-
-llvm::Registry<JSONFormat::FormatInfo>::Add<
- NullEntitySummaryForJSONFormatTestFormatInfo>
- RegisterNullEntitySummaryForJSONFormatTest(
- "NullEntitySummaryForJSONFormatTest",
- "Format info for NullEntitySummary");
-
-// ============================================================================
-// MismatchedEntitySummaryForJSONFormatTest - For mismatched SummaryName checks
-// ============================================================================
-
-struct MismatchedEntitySummaryForJSONFormatTestFormatInfo final
- : JSONFormat::FormatInfo {
- MismatchedEntitySummaryForJSONFormatTestFormatInfo()
- : JSONFormat::FormatInfo(
- SummaryName("MismatchedEntitySummaryForJSONFormatTest"),
- [](const EntitySummary &, JSONFormat::EntityIdToJSONFn)
- -> json::Object { return json::Object{}; },
- [](const json::Object &, EntityIdTable &,
- JSONFormat::EntityIdFromJSONFn)
- -> llvm::Expected<std::unique_ptr<EntitySummary>> {
- return std::make_unique<
- MismatchedEntitySummaryForJSONFormatTest>();
- }) {}
-};
-
-llvm::Registry<JSONFormat::FormatInfo>::Add<
- MismatchedEntitySummaryForJSONFormatTestFormatInfo>
- RegisterMismatchedEntitySummaryForJSONFormatTest(
- "MismatchedEntitySummaryForJSONFormatTest",
- "Format info for MismatchedEntitySummary");
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.h b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.h
deleted file mode 100644
index 515735e788d0d..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/JSONFormatTest.h
+++ /dev/null
@@ -1,172 +0,0 @@
-//===- JSONFormatTest.h -----------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Test fixture and helpers for SSAF JSON serialization format unit tests.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
-
-#include "TestFixture.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/Error.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/JSON.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <functional>
-#include <string>
-
-namespace clang::ssaf {
-
-// ============================================================================
-// Test Fixture
-// ============================================================================
-
-class JSONFormatTest : public TestFixture {
-public:
- using PathString = llvm::SmallString<128>;
-
-protected:
- llvm::SmallString<128> TestDir;
-
- void SetUp() override;
-
- void TearDown() override;
-
- PathString makePath(llvm::StringRef FileOrDirectoryName) const;
-
- PathString makePath(llvm::StringRef Dir, llvm::StringRef FileName) const;
-
- llvm::Expected<PathString> makeDirectory(llvm::StringRef DirectoryName) const;
-
- llvm::Expected<PathString> makeSymlink(llvm::StringRef TargetFileName,
- llvm::StringRef SymlinkFileName) const;
-
- llvm::Error setPermission(llvm::StringRef FileName,
- llvm::sys::fs::perms Perms) const;
-
- // Returns true if Unix file permission checks are enforced in this
- // environment. Returns false if running as root (uid 0), or if a probe
- // file with read permission removed can still be opened, indicating that
- // permission checks are not enforced (e.g. certain container setups).
- // Tests that rely on permission-based failure conditions should skip
- // themselves when this returns false.
- bool permissionsAreEnforced() const;
-
- llvm::Expected<llvm::json::Value>
- readJSONFromFile(llvm::StringRef FileName) const;
-
- llvm::Expected<PathString> writeJSON(llvm::StringRef JSON,
- llvm::StringRef FileName) const;
-};
-
-// ============================================================================
-// SummaryOps - Parameterization struct for TUSummary/LUSummary test suites
-// ============================================================================
-
-struct SummaryOps {
- // Suffix appended to the test name by GTest to identify this parameter
- // instantiation (e.g. "Resolved", "Encoding").
- std::string GTestInstantiationSuffix;
-
- // Human-readable name of the summary class under test (e.g. "TUSummary").
- // Used in diagnostic messages to identify which summary type an error
- // originated from.
- std::string SummaryClassName;
-
- std::function<llvm::Error(llvm::StringRef FilePath)> ReadFromFile;
-
- std::function<llvm::Error(llvm::StringRef FilePath)> WriteEmpty;
-
- std::function<llvm::Error(llvm::StringRef InputFilePath,
- llvm::StringRef OutputFilePath)>
- ReadWriteRoundTrip;
-};
-
-// ============================================================================
-// SummaryTest Test Fixture
-// ============================================================================
-
-class SummaryTest : public JSONFormatTest,
- public ::testing::WithParamInterface<SummaryOps> {
-protected:
- llvm::Error readFromString(llvm::StringRef JSON,
- llvm::StringRef FileName = "test.json") const;
-
- llvm::Error readFromFile(llvm::StringRef FileName) const;
-
- llvm::Error writeEmpty(llvm::StringRef FileName) const;
-
- llvm::Error readWriteRoundTrip(llvm::StringRef InputFileName,
- llvm::StringRef OutputFileName) const;
-
- void readWriteCompare(llvm::StringRef JSON) const;
-};
-
-// ============================================================================
-// First Test Analysis - Simple analysis for testing JSON serialization.
-// ============================================================================
-
-struct PairsEntitySummaryForJSONFormatTest final : EntitySummary {
-
- SummaryName getSummaryName() const override {
- return SummaryName("PairsEntitySummaryForJSONFormatTest");
- }
-
- std::vector<std::pair<EntityId, EntityId>> Pairs;
-};
-
-// ============================================================================
-// Second Test Analysis - Simple analysis for multi-summary round-trip tests.
-// ============================================================================
-
-struct TagsEntitySummaryForJSONFormatTest final : EntitySummary {
- SummaryName getSummaryName() const override {
- return SummaryName("TagsEntitySummaryForJSONFormatTest");
- }
-
- std::vector<std::string> Tags;
-};
-
-// ============================================================================
-// NullEntitySummaryForJSONFormatTest - For null data checks
-// ============================================================================
-
-struct NullEntitySummaryForJSONFormatTest final : EntitySummary {
- SummaryName getSummaryName() const override {
- return SummaryName("NullEntitySummaryForJSONFormatTest");
- }
-};
-
-// ============================================================================
-// UnregisteredEntitySummaryForJSONFormatTest - For missing FormatInfo checks
-// ============================================================================
-
-struct UnregisteredEntitySummaryForJSONFormatTest final : EntitySummary {
- SummaryName getSummaryName() const override {
- return SummaryName("UnregisteredEntitySummaryForJSONFormatTest");
- }
-};
-
-// ============================================================================
-// MismatchedEntitySummaryForJSONFormatTest - For mismatched SummaryName checks
-// ============================================================================
-
-struct MismatchedEntitySummaryForJSONFormatTest final : EntitySummary {
- SummaryName getSummaryName() const override {
- return SummaryName("MismatchedEntitySummaryForJSONFormatTest_WrongName");
- }
-};
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
deleted file mode 100644
index 13e1b6c4d3f20..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/LUSummaryTest.cpp
+++ /dev/null
@@ -1,452 +0,0 @@
-//===- LUSummaryTest.cpp --------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Unit tests for SSAF JSON serialization format reading and writing of
-// LUSummary and LUSummaryEncoding.
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONFormatTest.h"
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gmock/gmock.h"
-
-#include <memory>
-#include <vector>
-
-using namespace clang::ssaf;
-using namespace llvm;
-using ::testing::AllOf;
-using ::testing::HasSubstr;
-
-namespace {
-
-// ============================================================================
-// LUSummaryOps - Parameterization for LUSummary/LUSummaryEncoding tests
-// ============================================================================
-
-SummaryOps LUSummaryOps{
- "Resolved", "LUSummary",
- [](llvm::StringRef FilePath) -> llvm::Error {
- auto Result = JSONFormat().readLUSummary(FilePath);
- return Result ? llvm::Error::success() : Result.takeError();
- },
- [](llvm::StringRef FilePath) -> llvm::Error {
- BuildNamespace BN(BuildNamespaceKind::CompilationUnit, "test.cpp");
- NestedBuildNamespace NBN(std::move(BN));
- LUSummary S(llvm::Triple("arm64-apple-macosx"), std::move(NBN));
- return JSONFormat().writeLUSummary(S, FilePath);
- },
- [](llvm::StringRef InputFilePath,
- llvm::StringRef OutputFilePath) -> llvm::Error {
- auto ExpectedS = JSONFormat().readLUSummary(InputFilePath);
- if (!ExpectedS) {
- return ExpectedS.takeError();
- }
- return JSONFormat().writeLUSummary(*ExpectedS, OutputFilePath);
- }};
-
-SummaryOps LUSummaryEncodingOps{
- "Encoding", "LUSummary",
- [](llvm::StringRef FilePath) -> llvm::Error {
- auto Result = JSONFormat().readLUSummaryEncoding(FilePath);
- return Result ? llvm::Error::success() : Result.takeError();
- },
- [](llvm::StringRef FilePath) -> llvm::Error {
- BuildNamespace BN(BuildNamespaceKind::CompilationUnit, "test.cpp");
- NestedBuildNamespace NBN(std::move(BN));
- LUSummaryEncoding E(llvm::Triple("arm64-apple-macosx"), std::move(NBN));
- return JSONFormat().writeLUSummaryEncoding(E, FilePath);
- },
- [](llvm::StringRef InputFilePath,
- llvm::StringRef OutputFilePath) -> llvm::Error {
- auto ExpectedE = JSONFormat().readLUSummaryEncoding(InputFilePath);
- if (!ExpectedE) {
- return ExpectedE.takeError();
- }
- return JSONFormat().writeLUSummaryEncoding(*ExpectedE, OutputFilePath);
- }};
-
-// ============================================================================
-// LUSummaryTest Test Fixture
-// ============================================================================
-
-class LUSummaryTest : public SummaryTest {};
-
-INSTANTIATE_TEST_SUITE_P(JSONFormat, LUSummaryTest,
- ::testing::Values(LUSummaryOps, LUSummaryEncodingOps),
- [](const ::testing::TestParamInfo<SummaryOps> &Info) {
- return Info.param.GTestInstantiationSuffix;
- });
-
-// ============================================================================
-// JSONFormatLUSummaryTest Test Fixture
-// ============================================================================
-
-class JSONFormatLUSummaryTest : public JSONFormatTest {
-protected:
- llvm::Expected<LUSummary> readLUSummaryFromFile(StringRef FileName) const {
- PathString FilePath = makePath(FileName);
- return JSONFormat().readLUSummary(FilePath);
- }
-
- llvm::Expected<LUSummary>
- readLUSummaryFromString(StringRef JSON,
- StringRef FileName = "test.json") const {
- auto ExpectedFilePath = writeJSON(JSON, FileName);
- if (!ExpectedFilePath) {
- return ExpectedFilePath.takeError();
- }
-
- return readLUSummaryFromFile(FileName);
- }
-
- llvm::Error writeLUSummary(const LUSummary &Summary,
- StringRef FileName) const {
- PathString FilePath = makePath(FileName);
- return JSONFormat().writeLUSummary(Summary, FilePath);
- }
-};
-
-// ============================================================================
-// readJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, NonexistentFile) {
- auto Result = readFromFile("nonexistent.json");
-
- EXPECT_THAT_ERROR(std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("reading LUSummary from"),
- HasSubstr("file does not exist"))));
-}
-
-TEST_P(LUSummaryTest, PathIsDirectory) {
- PathString DirName("test_directory.json");
-
- auto ExpectedDirPath = makeDirectory(DirName);
- ASSERT_THAT_EXPECTED(ExpectedDirPath, Succeeded());
-
- auto Result = readFromFile(DirName);
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("reading LUSummary from"),
- HasSubstr("path is a directory, not a file"))));
-}
-
-TEST_P(LUSummaryTest, NotJsonExtension) {
- PathString FileName("test.txt");
-
- auto ExpectedFilePath = writeJSON("{}", FileName);
- ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
-
- auto Result = readFromFile(FileName);
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading LUSummary from file"),
- HasSubstr("failed to read file"),
- HasSubstr("file does not end with '.json' extension"))));
-}
-
-TEST_P(LUSummaryTest, BrokenSymlink) {
-#ifdef _WIN32
- GTEST_SKIP() << "Symlink model differs on Windows";
-#endif
-
- const PathString SymlinkFileName("broken_symlink.json");
-
- // Create a symlink pointing to a non-existent file
- auto ExpectedSymlinkPath =
- makeSymlink("nonexistent_target.json", "broken_symlink.json");
- ASSERT_THAT_EXPECTED(ExpectedSymlinkPath, Succeeded());
-
- auto Result = readFromFile(SymlinkFileName);
-
- EXPECT_THAT_ERROR(std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("reading LUSummary from"),
- HasSubstr("failed to read file"))));
-}
-
-TEST_P(LUSummaryTest, NoReadPermission) {
- if (!permissionsAreEnforced()) {
- GTEST_SKIP() << "File permission checks are not enforced in this "
- "environment";
- }
-
- PathString FileName("no-read-permission.json");
-
- auto ExpectedFilePath = writeJSON(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "id_table": [],
- "linkage_table": [],
- "data": []
- })",
- FileName);
- ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
-
- auto PermError = setPermission(FileName, sys::fs::perms::owner_write |
- sys::fs::perms::owner_exe);
- ASSERT_THAT_ERROR(std::move(PermError), Succeeded());
-
- auto Result = readFromFile(FileName);
-
- EXPECT_THAT_ERROR(std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("reading LUSummary from"),
- HasSubstr("failed to read file"))));
-
- // Restore permissions for cleanup
- auto RestoreError = setPermission(FileName, sys::fs::perms::all_all);
- EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded());
-}
-
-// ============================================================================
-// JSONFormat::entityDataMapFromJSON() Error Tests
-// ============================================================================
-
-TEST_F(JSONFormatLUSummaryTest, ReadEntitySummaryMissingData) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "target_triple": "arm64-apple-macosx",
- "type": "LUSummary",
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "NullEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {}
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("failed to deserialize EntitySummary"),
- HasSubstr("null EntitySummary data for "
- "'SummaryName(NullEntitySummaryForJSONFormatTest)'"))));
-}
-
-TEST_F(JSONFormatLUSummaryTest, ReadEntitySummaryMismatchedSummaryName) {
- auto Result = readLUSummaryFromString(R"({
- "lu_namespace": [
- {
- "kind": "LinkUnit",
- "name": "test.exe"
- }
- ],
- "target_triple": "arm64-apple-macosx",
- "type": "LUSummary",
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "MismatchedEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {}
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading LUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("failed to deserialize EntitySummary"),
- HasSubstr("EntitySummary data for "
- "'SummaryName(MismatchedEntitySummaryForJSONFormatTest)'"
- " reports mismatched "
- "'SummaryName(MismatchedEntitySummaryForJSONFormatTest_"
- "WrongName)'"))));
-}
-
-// ============================================================================
-// JSONFormat::entityDataMapEntryToJSON() Fatal Tests
-// ============================================================================
-
-TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryMissingData) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::LinkUnit, "test.exe"));
- LUSummary Summary(llvm::Triple("arm64-apple-macosx"), std::move(NBN));
-
- NestedBuildNamespace Namespace =
- NestedBuildNamespace::makeCompilationUnit("test.cpp");
- EntityId EI = getIdTable(Summary).getId(
- EntityName{"c:@F at foo", "", std::move(Namespace)});
-
- SummaryName SN("NullEntitySummaryForJSONFormatTest");
- getData(Summary)[SN][EI] = nullptr;
-
- EXPECT_DEATH(
- { (void)writeLUSummary(Summary, "output.json"); },
- "JSONFormat - null EntitySummary data for "
- "'SummaryName\\(NullEntitySummaryForJSONFormatTest\\)'");
-}
-
-TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryMismatchedSummaryName) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::LinkUnit, "test.exe"));
- LUSummary Summary(llvm::Triple("arm64-apple-macosx"), std::move(NBN));
-
- NestedBuildNamespace Namespace =
- NestedBuildNamespace::makeCompilationUnit("test.cpp");
- EntityId EI = getIdTable(Summary).getId(
- EntityName{"c:@F at foo", "", std::move(Namespace)});
-
- SummaryName SN("MismatchedEntitySummaryForJSONFormatTest");
- getData(Summary)[SN][EI] =
- std::make_unique<MismatchedEntitySummaryForJSONFormatTest>();
-
- EXPECT_DEATH(
- { (void)writeLUSummary(Summary, "output.json"); },
- "JSONFormat - EntitySummary data for "
- "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest\\)' "
- "reports "
- "mismatched "
- "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest_WrongName\\)'");
-}
-
-// ============================================================================
-// JSONFormat::writeJSON() Error Tests
-// ============================================================================
-
-TEST_P(LUSummaryTest, WriteFileAlreadyExists) {
- PathString FileName("existing.json");
-
- auto ExpectedFilePath = writeJSON("{}", FileName);
- ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
-
- auto Result = writeEmpty(FileName);
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("writing LUSummary to file"),
- HasSubstr("failed to write file"),
- HasSubstr("file already exists"))));
-}
-
-TEST_P(LUSummaryTest, WriteParentDirectoryNotFound) {
- PathString FilePath = makePath("nonexistent-dir", "test.json");
-
- auto Result = GetParam().WriteEmpty(FilePath);
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("writing LUSummary to file"),
- HasSubstr("failed to write file"),
- HasSubstr("parent directory does not exist"))));
-}
-
-TEST_P(LUSummaryTest, WriteNotJsonExtension) {
- auto Result = writeEmpty("test.txt");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("writing LUSummary to file"),
- HasSubstr("failed to write file"),
- HasSubstr("file does not end with '.json' extension"))));
-}
-
-TEST_P(LUSummaryTest, WriteStreamOpenFailure) {
- if (!permissionsAreEnforced()) {
- GTEST_SKIP() << "File permission checks are not enforced in this "
- "environment";
- }
-
- const PathString DirName("write-protected-dir");
-
- auto ExpectedDirPath = makeDirectory(DirName);
- ASSERT_THAT_EXPECTED(ExpectedDirPath, Succeeded());
-
- auto PermError = setPermission(DirName, sys::fs::perms::owner_read |
- sys::fs::perms::owner_exe);
- ASSERT_THAT_ERROR(std::move(PermError), Succeeded());
-
- PathString FilePath = makePath(DirName, "test.json");
-
- auto Result = GetParam().WriteEmpty(FilePath);
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("writing LUSummary to file"),
- HasSubstr("failed to write file"))));
-
- // Restore permissions for cleanup
- auto RestoreError = setPermission(DirName, sys::fs::perms::all_all);
- EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded());
-}
-
-// ============================================================================
-// JSONFormat::writeLUSummary() Error Tests (LUSummary-only)
-// ============================================================================
-
-TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryNoFormatInfo) {
- NestedBuildNamespace NBN(
- BuildNamespace(BuildNamespaceKind::LinkUnit, "test.exe"));
- LUSummary Summary(llvm::Triple("arm64-apple-macosx"), std::move(NBN));
-
- NestedBuildNamespace Namespace =
- NestedBuildNamespace::makeCompilationUnit("test.cpp");
- EntityId EI = getIdTable(Summary).getId(
- EntityName{"c:@F at foo", "", std::move(Namespace)});
-
- SummaryName UnknownSN("UnregisteredEntitySummaryForJSONFormatTest");
- getData(Summary)[UnknownSN][EI] =
- std::make_unique<UnregisteredEntitySummaryForJSONFormatTest>();
-
- auto Result = writeLUSummary(Summary, "output.json");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("writing LUSummary to file"),
- HasSubstr("writing SummaryData entry to index '0'"),
- HasSubstr("writing EntitySummary entries to field "
- "'summary_data'"),
- HasSubstr("writing EntitySummary entry to index '0'"),
- HasSubstr("writing EntitySummary to field 'entity_summary'"),
- HasSubstr("failed to serialize EntitySummary"),
- HasSubstr(
- "no FormatInfo registered for "
- "'SummaryName(UnregisteredEntitySummaryForJSONFormatTest)'"))));
-}
-
-} // anonymous namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/TUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/TUSummaryTest.cpp
deleted file mode 100644
index 6e88013b2e4a6..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/Serialization/JSONFormatTest/TUSummaryTest.cpp
+++ /dev/null
@@ -1,445 +0,0 @@
-//===- TUSummaryTest.cpp --------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Unit tests for SSAF JSON serialization format reading and writing of
-// TUSummary and TUSummaryEncoding.
-//
-//===----------------------------------------------------------------------===//
-
-#include "JSONFormatTest.h"
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gmock/gmock.h"
-
-#include <memory>
-
-using namespace clang::ssaf;
-using namespace llvm;
-using ::testing::AllOf;
-using ::testing::HasSubstr;
-
-namespace {
-
-// ============================================================================
-// TUSummaryOps - Parameterization for TUSummary/TUSummaryEncoding tests
-// ============================================================================
-
-SummaryOps TUSummaryOps{
- "Resolved", "TUSummary",
- [](llvm::StringRef FilePath) -> llvm::Error {
- auto Result = JSONFormat().readTUSummary(FilePath);
- return Result ? llvm::Error::success() : Result.takeError();
- },
- [](llvm::StringRef FilePath) -> llvm::Error {
- BuildNamespace BN(BuildNamespaceKind::CompilationUnit, "test.cpp");
- TUSummary S(llvm::Triple("arm64-apple-macosx"), std::move(BN));
- return JSONFormat().writeTUSummary(S, FilePath);
- },
- [](llvm::StringRef InputFilePath,
- llvm::StringRef OutputFilePath) -> llvm::Error {
- auto ExpectedS = JSONFormat().readTUSummary(InputFilePath);
- if (!ExpectedS) {
- return ExpectedS.takeError();
- }
- return JSONFormat().writeTUSummary(*ExpectedS, OutputFilePath);
- }};
-
-SummaryOps TUSummaryEncodingOps{
- "Encoding", "TUSummary",
- [](llvm::StringRef FilePath) -> llvm::Error {
- auto Result = JSONFormat().readTUSummaryEncoding(FilePath);
- return Result ? llvm::Error::success() : Result.takeError();
- },
- [](llvm::StringRef FilePath) -> llvm::Error {
- BuildNamespace BN(BuildNamespaceKind::CompilationUnit, "test.cpp");
- TUSummaryEncoding E(llvm::Triple("arm64-apple-macosx"), std::move(BN));
- return JSONFormat().writeTUSummaryEncoding(E, FilePath);
- },
- [](llvm::StringRef InputFilePath,
- llvm::StringRef OutputFilePath) -> llvm::Error {
- auto ExpectedE = JSONFormat().readTUSummaryEncoding(InputFilePath);
- if (!ExpectedE) {
- return ExpectedE.takeError();
- }
- return JSONFormat().writeTUSummaryEncoding(*ExpectedE, OutputFilePath);
- }};
-
-// ============================================================================
-// LUSummaryTest Test Fixture
-// ============================================================================
-
-class TUSummaryTest : public SummaryTest {};
-
-INSTANTIATE_TEST_SUITE_P(JSONFormat, TUSummaryTest,
- ::testing::Values(TUSummaryOps, TUSummaryEncodingOps),
- [](const ::testing::TestParamInfo<SummaryOps> &Info) {
- return Info.param.GTestInstantiationSuffix;
- });
-
-// ============================================================================
-// JSONFormatTUSummaryTest Test Fixture
-// ============================================================================
-
-class JSONFormatTUSummaryTest : public JSONFormatTest {
-protected:
- llvm::Expected<TUSummary> readTUSummaryFromFile(StringRef FileName) const {
- PathString FilePath = makePath(FileName);
- return JSONFormat().readTUSummary(FilePath);
- }
-
- llvm::Expected<TUSummary>
- readTUSummaryFromString(StringRef JSON,
- StringRef FileName = "test.json") const {
- auto ExpectedFilePath = writeJSON(JSON, FileName);
- if (!ExpectedFilePath) {
- return ExpectedFilePath.takeError();
- }
-
- return readTUSummaryFromFile(FileName);
- }
-
- llvm::Error writeTUSummary(const TUSummary &Summary,
- StringRef FileName) const {
- PathString FilePath = makePath(FileName);
- return JSONFormat().writeTUSummary(Summary, FilePath);
- }
-};
-
-// ============================================================================
-// readJSON() Error Tests
-// ============================================================================
-
-TEST_P(TUSummaryTest, NonexistentFile) {
- auto Result = readFromFile("nonexistent.json");
-
- EXPECT_THAT_ERROR(std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"),
- HasSubstr("file does not exist"))));
-}
-
-TEST_P(TUSummaryTest, PathIsDirectory) {
- PathString DirName("test_directory.json");
-
- auto ExpectedDirPath = makeDirectory(DirName);
- ASSERT_THAT_EXPECTED(ExpectedDirPath, Succeeded());
-
- auto Result = readFromFile(DirName);
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"),
- HasSubstr("path is a directory, not a file"))));
-}
-
-TEST_P(TUSummaryTest, NotJsonExtension) {
- PathString FileName("test.txt");
-
- auto ExpectedFilePath = writeJSON("{}", FileName);
- ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
-
- auto Result = readFromFile(FileName);
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("reading TUSummary from file"),
- HasSubstr("failed to read file"),
- HasSubstr("file does not end with '.json' extension"))));
-}
-
-TEST_P(TUSummaryTest, BrokenSymlink) {
-#ifdef _WIN32
- GTEST_SKIP() << "Symlink model differs on Windows";
-#endif
-
- const PathString SymlinkFileName("broken_symlink.json");
-
- // Create a symlink pointing to a non-existent file
- auto ExpectedSymlinkPath =
- makeSymlink("nonexistent_target.json", SymlinkFileName);
- ASSERT_THAT_EXPECTED(ExpectedSymlinkPath, Succeeded());
-
- auto Result = readFromFile(SymlinkFileName);
-
- EXPECT_THAT_ERROR(std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"),
- HasSubstr("failed to read file"))));
-}
-
-TEST_P(TUSummaryTest, NoReadPermission) {
- if (!permissionsAreEnforced()) {
- GTEST_SKIP() << "File permission checks are not enforced in this "
- "environment";
- }
-
- PathString FileName("no-read-permission.json");
-
- auto ExpectedFilePath = writeJSON(R"({
- "tu_namespace": {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- "id_table": [],
- "linkage_table": [],
- "data": []
- })",
- FileName);
- ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
-
- auto PermError = setPermission(FileName, sys::fs::perms::owner_write |
- sys::fs::perms::owner_exe);
- ASSERT_THAT_ERROR(std::move(PermError), Succeeded());
-
- auto Result = readFromFile(FileName);
-
- EXPECT_THAT_ERROR(std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"),
- HasSubstr("failed to read file"))));
-
- // Restore permissions for cleanup
- auto RestoreError = setPermission(FileName, sys::fs::perms::all_all);
- EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded());
-}
-
-// ============================================================================
-// JSONFormat::entityDataMapEntryFromJSON() Error Tests
-// ============================================================================
-
-TEST_F(JSONFormatTUSummaryTest, ReadEntitySummaryMissingData) {
- auto Result = readTUSummaryFromString(R"({
- "tu_namespace": {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- "target_triple": "arm64-apple-macosx",
- "type": "TUSummary",
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "NullEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {}
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading TUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("failed to deserialize EntitySummary"),
- HasSubstr("null EntitySummary data for "
- "'SummaryName(NullEntitySummaryForJSONFormatTest)'"))));
-}
-
-TEST_F(JSONFormatTUSummaryTest, ReadEntitySummaryMismatchedSummaryName) {
- auto Result = readTUSummaryFromString(R"({
- "tu_namespace": {
- "kind": "CompilationUnit",
- "name": "test.cpp"
- },
- "target_triple": "arm64-apple-macosx",
- "type": "TUSummary",
- "id_table": [],
- "linkage_table": [],
- "data": [
- {
- "summary_name": "MismatchedEntitySummaryForJSONFormatTest",
- "summary_data": [
- {
- "entity_id": 0,
- "entity_summary": {}
- }
- ]
- }
- ]
- })");
-
- EXPECT_THAT_EXPECTED(
- Result,
- FailedWithMessage(AllOf(
- HasSubstr("reading TUSummary from file"),
- HasSubstr("reading SummaryData entries from field 'data'"),
- HasSubstr("reading SummaryData entry from index '0'"),
- HasSubstr("reading EntitySummary entries from field 'summary_data'"),
- HasSubstr("reading EntitySummary entry from index '0'"),
- HasSubstr("failed to deserialize EntitySummary"),
- HasSubstr("EntitySummary data for "
- "'SummaryName(MismatchedEntitySummaryForJSONFormatTest)' "
- "reports "
- "mismatched "
- "'SummaryName(MismatchedEntitySummaryForJSONFormatTest_"
- "WrongName)"
- "'"))));
-}
-
-// ============================================================================
-// JSONFormat::entityDataMapEntryToJSON() Fatal Tests
-// ============================================================================
-
-TEST_F(JSONFormatTUSummaryTest, WriteEntitySummaryMissingData) {
- TUSummary Summary(
- llvm::Triple("arm64-apple-macosx"),
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
-
- NestedBuildNamespace Namespace =
- NestedBuildNamespace::makeCompilationUnit("test.cpp");
- EntityId EI = getIdTable(Summary).getId(
- EntityName{"c:@F at foo", "", std::move(Namespace)});
-
- SummaryName SN("NullEntitySummaryForJSONFormatTest");
- getData(Summary)[SN][EI] = nullptr;
-
- EXPECT_DEATH(
- { (void)writeTUSummary(Summary, "output.json"); },
- "JSONFormat - null EntitySummary data for "
- "'SummaryName\\(NullEntitySummaryForJSONFormatTest\\)'");
-}
-
-TEST_F(JSONFormatTUSummaryTest, WriteEntitySummaryMismatchedSummaryName) {
- TUSummary Summary(
- llvm::Triple("arm64-apple-macosx"),
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
-
- NestedBuildNamespace Namespace =
- NestedBuildNamespace::makeCompilationUnit("test.cpp");
- EntityId EI = getIdTable(Summary).getId(
- EntityName{"c:@F at foo", "", std::move(Namespace)});
-
- SummaryName SN("MismatchedEntitySummaryForJSONFormatTest");
- getData(Summary)[SN][EI] =
- std::make_unique<MismatchedEntitySummaryForJSONFormatTest>();
-
- EXPECT_DEATH(
- { (void)writeTUSummary(Summary, "output.json"); },
- "JSONFormat - EntitySummary data for "
- "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest\\)' reports "
- "mismatched "
- "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest_WrongName\\)"
- "'");
-}
-
-// ============================================================================
-// JSONFormat::writeJSON() Error Tests
-// ============================================================================
-
-TEST_P(TUSummaryTest, WriteFileAlreadyExists) {
- PathString FileName("existing.json");
-
- auto ExpectedFilePath = writeJSON("{}", FileName);
- ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
-
- auto Result = writeEmpty(FileName);
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("writing TUSummary to file"),
- HasSubstr("failed to write file"),
- HasSubstr("file already exists"))));
-}
-
-TEST_P(TUSummaryTest, WriteParentDirectoryNotFound) {
- PathString FilePath = makePath("nonexistent-dir", "test.json");
-
- auto Result = GetParam().WriteEmpty(FilePath);
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("writing TUSummary to file"),
- HasSubstr("failed to write file"),
- HasSubstr("parent directory does not exist"))));
-}
-
-TEST_P(TUSummaryTest, WriteNotJsonExtension) {
- auto Result = writeEmpty("test.txt");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(
- AllOf(HasSubstr("writing TUSummary to file"),
- HasSubstr("failed to write file"),
- HasSubstr("file does not end with '.json' extension"))));
-}
-
-TEST_P(TUSummaryTest, WriteStreamOpenFailure) {
- if (!permissionsAreEnforced()) {
- GTEST_SKIP() << "File permission checks are not enforced in this "
- "environment";
- }
-
- const PathString DirName("write-protected-dir");
-
- auto ExpectedDirPath = makeDirectory(DirName);
- ASSERT_THAT_EXPECTED(ExpectedDirPath, Succeeded());
-
- auto PermError = setPermission(DirName, sys::fs::perms::owner_read |
- sys::fs::perms::owner_exe);
- ASSERT_THAT_ERROR(std::move(PermError), Succeeded());
-
- PathString FilePath = makePath(DirName, "test.json");
-
- auto Result = GetParam().WriteEmpty(FilePath);
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(HasSubstr("writing TUSummary to file"),
- HasSubstr("failed to write file"))));
-
- // Restore permissions for cleanup
- auto RestoreError = setPermission(DirName, sys::fs::perms::all_all);
- EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded());
-}
-
-// ============================================================================
-// JSONFormat::writeTUSummary() Error Tests (TUSummary-only)
-// ============================================================================
-
-TEST_F(JSONFormatTUSummaryTest, WriteEntitySummaryNoFormatInfo) {
- TUSummary Summary(
- llvm::Triple("arm64-apple-macosx"),
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
-
- NestedBuildNamespace Namespace =
- NestedBuildNamespace::makeCompilationUnit("test.cpp");
- EntityId EI = getIdTable(Summary).getId(
- EntityName{"c:@F at foo", "", std::move(Namespace)});
-
- SummaryName UnknownSN("UnregisteredEntitySummaryForJSONFormatTest");
- getData(Summary)[UnknownSN][EI] =
- std::make_unique<UnregisteredEntitySummaryForJSONFormatTest>();
-
- auto Result = writeTUSummary(Summary, "output.json");
-
- EXPECT_THAT_ERROR(
- std::move(Result),
- FailedWithMessage(AllOf(
- HasSubstr("writing TUSummary to file"),
- HasSubstr("writing SummaryData entry to index '0'"),
- HasSubstr("writing EntitySummary entries to field "
- "'summary_data'"),
- HasSubstr("writing EntitySummary entry to index '0'"),
- HasSubstr("writing EntitySummary to field 'entity_summary'"),
- HasSubstr("failed to serialize EntitySummary"),
- HasSubstr(
- "no FormatInfo registered for "
- "'SummaryName(UnregisteredEntitySummaryForJSONFormatTest)'"))));
-}
-
-} // anonymous namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/SourceTransformation/EmitterTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/SourceTransformation/EmitterTest.cpp
deleted file mode 100644
index d730c6c337c45..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/SourceTransformation/EmitterTest.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-//===- EmitterTest.cpp ----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Basic/Sarif.h"
-#include "clang/Basic/SourceLocation.h"
-#include "clang/ScalableStaticAnalysisFramework/SourceTransformation/SourceEditEmitter.h"
-#include "clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationReportEmitter.h"
-#include "gtest/gtest.h"
-#include <vector>
-
-using namespace llvm;
-using namespace clang;
-using namespace ssaf;
-
-namespace {
-
-class RecordingEditEmitter : public SourceEditEmitter {
-public:
- std::vector<clang::tooling::Replacement> Replacements;
-
- void addReplacement(clang::tooling::Replacement R) override {
- Replacements.push_back(std::move(R));
- }
-};
-
-class RecordingReportEmitter : public TransformationReportEmitter {
-public:
- struct Entry {
- std::string RuleId;
- clang::SarifResultLevel Level;
- clang::CharSourceRange Range;
- std::string Message;
- };
- std::vector<Entry> Results;
-
- void addResult(StringRef RuleId, clang::SarifResultLevel Level,
- clang::CharSourceRange Range, StringRef Message) override {
- Results.push_back({RuleId.str(), Level, Range, Message.str()});
- }
-};
-
-TEST(SourceEditEmitterTest, AccumulatesInOrder) {
- RecordingEditEmitter E;
- E.addReplacement(clang::tooling::Replacement("a.cpp", 0, 0, "// 1"));
- E.addReplacement(clang::tooling::Replacement("a.cpp", 10, 0, "// 2"));
- ASSERT_EQ(E.Replacements.size(), 2u);
- EXPECT_EQ(E.Replacements[0].getReplacementText(), "// 1");
- EXPECT_EQ(E.Replacements[1].getReplacementText(), "// 2");
- EXPECT_EQ(E.Replacements[0].getOffset(), 0u);
- EXPECT_EQ(E.Replacements[1].getOffset(), 10u);
-}
-
-TEST(TransformationReportEmitterTest, AccumulatesInOrder) {
- RecordingReportEmitter R;
- R.addResult("rule-a", clang::SarifResultLevel::Note, clang::CharSourceRange{},
- "first");
- R.addResult("rule-b", clang::SarifResultLevel::Warning,
- clang::CharSourceRange{}, "second");
- ASSERT_EQ(R.Results.size(), 2u);
- EXPECT_EQ(R.Results[0].RuleId, "rule-a");
- EXPECT_EQ(R.Results[0].Level, clang::SarifResultLevel::Note);
- EXPECT_EQ(R.Results[0].Message, "first");
- EXPECT_EQ(R.Results[1].RuleId, "rule-b");
- EXPECT_EQ(R.Results[1].Level, clang::SarifResultLevel::Warning);
- EXPECT_EQ(R.Results[1].Message, "second");
-}
-
-TEST(TransformationReportEmitterTest, AcceptsInvalidRange) {
- RecordingReportEmitter R;
- R.addResult("rule", clang::SarifResultLevel::Note, clang::CharSourceRange{},
- "no-location");
- ASSERT_EQ(R.Results.size(), 1u);
- EXPECT_FALSE(R.Results[0].Range.isValid());
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/SourceTransformation/RegistryTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/SourceTransformation/RegistryTest.cpp
deleted file mode 100644
index 0c68cd95dd499..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/SourceTransformation/RegistryTest.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-//===- RegistryTest.cpp ---------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/SourceTransformation/Transformation.h"
-#include "clang/ScalableStaticAnalysisFramework/SourceTransformation/TransformationRegistry.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-
-using namespace llvm;
-using namespace clang;
-using namespace ssaf;
-
-namespace {
-
-class StubEditEmitter : public SourceEditEmitter {
-public:
- void addReplacement(clang::tooling::Replacement) override {}
-};
-
-class StubReportEmitter : public TransformationReportEmitter {
-public:
- void addResult(StringRef, clang::SarifResultLevel, clang::CharSourceRange,
- StringRef) override {}
-};
-
-class StubTransformation : public Transformation {
-public:
- using Transformation::Transformation;
-};
-
-} // namespace
-
-static TransformationRegistry::Add<StubTransformation>
- RegisterStubTransformation("stub-transformation",
- "A transformation for testing");
-
-namespace {
-
-class TransformationRegistryTest : public TestFixture {};
-
-TEST_F(TransformationRegistryTest, isTransformationRegistered) {
- EXPECT_FALSE(isTransformationRegistered("not-a-transformation"));
- EXPECT_TRUE(isTransformationRegistered("stub-transformation"));
-}
-
-TEST_F(TransformationRegistryTest, makeTransformation) {
- WPASuite Suite = makeWPASuite();
- StubEditEmitter Edits;
- StubReportEmitter Report;
- std::unique_ptr<Transformation> T =
- makeTransformation("stub-transformation", Suite, Edits, Report);
- EXPECT_NE(T, nullptr);
-}
-
-TEST_F(TransformationRegistryTest, EnumeratingRegistryEntries) {
- auto Entries = TransformationRegistry::entries();
- EXPECT_TRUE(llvm::any_of(Entries, [](const auto &Entry) {
- return StringRef(Entry.getName()) == "stub-transformation";
- }));
-}
-
-TEST_F(TransformationRegistryTest, PrintAvailableTransformations) {
- std::string Buffer;
- raw_string_ostream OS(Buffer);
- printAvailableTransformations(OS);
- EXPECT_NE(StringRef(Buffer).find("stub-transformation"), StringRef::npos);
- EXPECT_NE(StringRef(Buffer).find("A transformation for testing"),
- StringRef::npos);
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/SummaryData/SummaryDataTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/SummaryData/SummaryDataTest.cpp
deleted file mode 100644
index ecf7c1b3347be..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/SummaryData/SummaryDataTest.cpp
+++ /dev/null
@@ -1,398 +0,0 @@
-//===- SummaryDataTest.cpp ------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gtest/gtest.h"
-#include <memory>
-#include <utility>
-#include <vector>
-
-using namespace clang;
-using namespace ssaf;
-
-namespace {
-
-// ---------------------------------------------------------------------------
-// Instance counter
-// ---------------------------------------------------------------------------
-
-static int NextSummaryInstanceId = 0;
-
-// ---------------------------------------------------------------------------
-// Entity summaries
-// ---------------------------------------------------------------------------
-
-class Analysis1EntitySummary final : public EntitySummary {
-public:
- int InstanceId = NextSummaryInstanceId++;
- SummaryName getSummaryName() const override {
- return SummaryName("Analysis1");
- }
-};
-
-class Analysis2EntitySummary final : public EntitySummary {
-public:
- int InstanceId = NextSummaryInstanceId++;
- SummaryName getSummaryName() const override {
- return SummaryName("Analysis2");
- }
-};
-
-class Analysis3EntitySummary final : public EntitySummary {
-public:
- int InstanceId = NextSummaryInstanceId++;
- SummaryName getSummaryName() const override {
- return SummaryName("Analysis3");
- }
-};
-
-class Analysis4EntitySummary final : public EntitySummary {
-public:
- int InstanceId = NextSummaryInstanceId++;
- SummaryName getSummaryName() const override {
- return SummaryName("Analysis4");
- }
-};
-
-// ---------------------------------------------------------------------------
-// Data
-// ---------------------------------------------------------------------------
-
-class Analysis1Data final : public SummaryData {
-public:
- static SummaryName summaryName() { return SummaryName("Analysis1"); }
- std::vector<std::pair<EntityId, int>> Entries;
- bool WasFinalized = false;
-};
-
-class Analysis2Data final : public SummaryData {
-public:
- static SummaryName summaryName() { return SummaryName("Analysis2"); }
- std::vector<std::pair<EntityId, int>> Entries;
- bool WasFinalized = false;
-};
-
-// No builder or registration for Analysis3. Data for Analysis3 is inserted
-// into the LUSummary to verify the consumer silently skips it.
-class Analysis3Data final : public SummaryData {
-public:
- static SummaryName summaryName() { return SummaryName("Analysis3"); }
-};
-
-// Analysis4 has a registered builder but no data is inserted into the
-// LUSummary, so the builder is never invoked and getData returns nullptr.
-class Analysis4Data final : public SummaryData {
-public:
- static SummaryName summaryName() { return SummaryName("Analysis4"); }
- std::vector<std::pair<EntityId, int>> Entries;
- bool WasFinalized = false;
-};
-
-// ---------------------------------------------------------------------------
-// Builder destruction flags (reset in SetUp)
-// ---------------------------------------------------------------------------
-
-static bool Analysis1BuilderWasDestroyed = false;
-static bool Analysis2BuilderWasDestroyed = false;
-static bool Analysis4BuilderWasDestroyed = false;
-
-// ---------------------------------------------------------------------------
-// Builders
-// ---------------------------------------------------------------------------
-
-class Analysis1Builder final
- : public SummaryDataBuilder<Analysis1Data, Analysis1EntitySummary> {
-public:
- ~Analysis1Builder() { Analysis1BuilderWasDestroyed = true; }
-
- void addSummary(EntityId Id,
- std::unique_ptr<Analysis1EntitySummary> S) override {
- getData().Entries.push_back({Id, S->InstanceId});
- }
-
- void finalize() override { getData().WasFinalized = true; }
-};
-
-static SummaryDataBuilderRegistry::Add<Analysis1Builder>
- RegAnalysis1("Builder for Analysis1");
-
-class Analysis2Builder final
- : public SummaryDataBuilder<Analysis2Data, Analysis2EntitySummary> {
-public:
- ~Analysis2Builder() { Analysis2BuilderWasDestroyed = true; }
-
- void addSummary(EntityId Id,
- std::unique_ptr<Analysis2EntitySummary> S) override {
- getData().Entries.push_back({Id, S->InstanceId});
- }
-
- void finalize() override { getData().WasFinalized = true; }
-};
-
-static SummaryDataBuilderRegistry::Add<Analysis2Builder>
- RegAnalysis2("Builder for Analysis2");
-
-class Analysis4Builder final
- : public SummaryDataBuilder<Analysis4Data, Analysis4EntitySummary> {
-public:
- ~Analysis4Builder() { Analysis4BuilderWasDestroyed = true; }
-
- void addSummary(EntityId Id,
- std::unique_ptr<Analysis4EntitySummary> S) override {
- getData().Entries.push_back({Id, S->InstanceId});
- }
-
- void finalize() override { getData().WasFinalized = true; }
-};
-
-static SummaryDataBuilderRegistry::Add<Analysis4Builder>
- RegAnalysis4("Builder for Analysis4");
-
-// ---------------------------------------------------------------------------
-// Fixture
-// ---------------------------------------------------------------------------
-
-class LUSummaryConsumerTest : public TestFixture {
-protected:
- static constexpr EntityLinkage ExternalLinkage =
- EntityLinkage(EntityLinkageType::External);
-
- void SetUp() override {
- NextSummaryInstanceId = 0;
- Analysis1BuilderWasDestroyed = false;
- Analysis2BuilderWasDestroyed = false;
- Analysis4BuilderWasDestroyed = false;
- }
-
- std::unique_ptr<LUSummary> makeLUSummary() {
- NestedBuildNamespace NS(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
- return std::make_unique<LUSummary>(llvm::Triple("arm64-apple-macosx"),
- std::move(NS));
- }
-
- EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
- NestedBuildNamespace NS(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
- EntityName Name(USR.str(), "", NS);
- EntityId Id = getIdTable(LU).getId(Name);
- getLinkageTable(LU).insert({Id, ExternalLinkage});
- return Id;
- }
-
- static bool hasEntry(const std::vector<std::pair<EntityId, int>> &Entries,
- EntityId Id, int InstanceId) {
- return llvm::is_contained(Entries, std::make_pair(Id, InstanceId));
- }
-
- /// Inserts a freshly constructed SummaryT for the given entity and returns
- /// the summary's InstanceId so the test can verify delivery later.
- template <typename SummaryT>
- int insertSummary(LUSummary &LU, llvm::StringRef SN, EntityId Id) {
- auto S = std::make_unique<SummaryT>();
- int InstanceId = S->InstanceId;
- getData(LU)[SummaryName(SN.str())][Id] = std::move(S);
- return InstanceId;
- }
-};
-
-// ---------------------------------------------------------------------------
-// Tests
-// ---------------------------------------------------------------------------
-
-TEST(SummaryDataBuilderRegistryTest, BuilderIsRegistered) {
- EXPECT_FALSE(SummaryDataBuilderRegistry::contains("AnalysisNonExisting"));
- EXPECT_TRUE(SummaryDataBuilderRegistry::contains("Analysis1"));
- EXPECT_TRUE(SummaryDataBuilderRegistry::contains("Analysis2"));
- EXPECT_TRUE(SummaryDataBuilderRegistry::contains("Analysis4"));
-}
-
-TEST(SummaryDataBuilderRegistryTest, BuilderCanBeInstantiated) {
- EXPECT_EQ(SummaryDataBuilderRegistry::instantiate("AnalysisNonExisting"),
- nullptr);
- EXPECT_NE(SummaryDataBuilderRegistry::instantiate("Analysis1"), nullptr);
- EXPECT_NE(SummaryDataBuilderRegistry::instantiate("Analysis2"), nullptr);
- EXPECT_NE(SummaryDataBuilderRegistry::instantiate("Analysis4"), nullptr);
-}
-
-// run() — processes all registered analyses present in the LUSummary.
-TEST_F(LUSummaryConsumerTest, RunAll) {
- auto LU = makeLUSummary();
- const auto E1 = addEntity(*LU, "Entity1");
- const auto E2 = addEntity(*LU, "Entity2");
- const auto E3 = addEntity(*LU, "Entity3");
-
- int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
- int s1b = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E2);
- int s2a = insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
- int s2b = insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E3);
-
- // No registered builder — Analysis3 data silently skipped.
- (void)insertSummary<Analysis3EntitySummary>(*LU, "Analysis3", E1);
-
- LUSummaryConsumer Consumer(std::move(LU));
- SummaryDataStore Store = std::move(Consumer).run();
-
- {
- auto Data1OrErr = Store.get<Analysis1Data>();
- ASSERT_THAT_EXPECTED(Data1OrErr, llvm::Succeeded());
- auto &Data1 = *Data1OrErr;
-
- EXPECT_EQ(Data1.Entries.size(), 2u);
- EXPECT_TRUE(hasEntry(Data1.Entries, E1, s1a));
- EXPECT_TRUE(hasEntry(Data1.Entries, E2, s1b));
- EXPECT_TRUE(Data1.WasFinalized);
- EXPECT_TRUE(Analysis1BuilderWasDestroyed);
-
- // take() transfers ownership — subsequent get() returns an error.
- auto Take1OrErr = Store.take<Analysis1Data>();
- ASSERT_THAT_EXPECTED(Take1OrErr, llvm::Succeeded());
- EXPECT_NE(*Take1OrErr, nullptr);
- EXPECT_THAT_EXPECTED(Store.get<Analysis1Data>(), llvm::Failed());
- }
-
- {
- auto Data2OrErr = Store.get<Analysis2Data>();
- ASSERT_THAT_EXPECTED(Data2OrErr, llvm::Succeeded());
- auto &Data2 = *Data2OrErr;
- EXPECT_EQ(Data2.Entries.size(), 2u);
- EXPECT_TRUE(hasEntry(Data2.Entries, E2, s2a));
- EXPECT_TRUE(hasEntry(Data2.Entries, E3, s2b));
- EXPECT_TRUE(Data2.WasFinalized);
- EXPECT_TRUE(Analysis2BuilderWasDestroyed);
-
- auto Take2OrErr = Store.take<Analysis2Data>();
- ASSERT_THAT_EXPECTED(Take2OrErr, llvm::Succeeded());
- EXPECT_NE(*Take2OrErr, nullptr);
- EXPECT_THAT_EXPECTED(Store.get<Analysis2Data>(), llvm::Failed());
- }
-
- // Unregistered — not present in store.
- EXPECT_THAT_EXPECTED(Store.get<Analysis3Data>(), llvm::Failed());
-
- // Registered builder but no data in LUSummary — not present in store.
- EXPECT_THAT_EXPECTED(Store.get<Analysis4Data>(), llvm::Failed());
- EXPECT_FALSE(Analysis4BuilderWasDestroyed);
-}
-
-// run(names) — processes only the analyses for the given names.
-TEST_F(LUSummaryConsumerTest, RunByName) {
- auto LU = makeLUSummary();
- const auto E1 = addEntity(*LU, "Entity1");
- const auto E2 = addEntity(*LU, "Entity2");
-
- int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
- insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
-
- LUSummaryConsumer Consumer(std::move(LU));
- auto StoreOrErr = Consumer.run({SummaryName("Analysis1")});
- ASSERT_THAT_EXPECTED(StoreOrErr, llvm::Succeeded());
-
- // Analysis1 was requested and has data — present.
- auto Data1OrErr = StoreOrErr->get<Analysis1Data>();
- ASSERT_THAT_EXPECTED(Data1OrErr, llvm::Succeeded());
- auto &Data1 = *Data1OrErr;
- EXPECT_EQ(Data1.Entries.size(), 1u);
- EXPECT_TRUE(hasEntry(Data1.Entries, E1, s1a));
- EXPECT_TRUE(Data1.WasFinalized);
-
- // Analysis2 was not requested — not present even though data exists.
- EXPECT_THAT_EXPECTED(StoreOrErr->get<Analysis2Data>(), llvm::Failed());
-}
-
-// run(names) — error when a requested name has no data in LUSummary.
-TEST_F(LUSummaryConsumerTest, RunByNameErrorMissingData) {
- auto LU = makeLUSummary();
- LUSummaryConsumer Consumer(std::move(LU));
-
- EXPECT_THAT_EXPECTED(Consumer.run({SummaryName("Analysis1")}),
- llvm::Failed());
-}
-
-// run(names) — error when a requested name has no registered builder.
-TEST_F(LUSummaryConsumerTest, RunByNameErrorMissingBuilder) {
- auto LU = makeLUSummary();
- const auto E1 = addEntity(*LU, "Entity1");
- insertSummary<Analysis3EntitySummary>(*LU, "Analysis3", E1);
-
- LUSummaryConsumer Consumer(std::move(LU));
-
- // Analysis3 has data but no registered builder.
- EXPECT_THAT_EXPECTED(Consumer.run({SummaryName("Analysis3")}),
- llvm::Failed());
-}
-
-// run<DataTs...>() — type-safe subset.
-TEST_F(LUSummaryConsumerTest, RunByType) {
- auto LU = makeLUSummary();
- const auto E1 = addEntity(*LU, "Entity1");
- const auto E2 = addEntity(*LU, "Entity2");
-
- int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
- insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
-
- LUSummaryConsumer Consumer(std::move(LU));
- auto StoreOrErr = Consumer.run<Analysis1Data>();
- ASSERT_THAT_EXPECTED(StoreOrErr, llvm::Succeeded());
-
- // Analysis1 was requested — present.
- auto Data1OrErr = StoreOrErr->get<Analysis1Data>();
- ASSERT_THAT_EXPECTED(Data1OrErr, llvm::Succeeded());
- auto &Data1 = *Data1OrErr;
- EXPECT_EQ(Data1.Entries.size(), 1u);
- EXPECT_TRUE(hasEntry(Data1.Entries, E1, s1a));
- EXPECT_TRUE(Data1.WasFinalized);
-
- // Analysis2 was not requested — not present even though data exists.
- EXPECT_THAT_EXPECTED(StoreOrErr->get<Analysis2Data>(), llvm::Failed());
-}
-
-// run<DataTs...>() — error when a requested type has no data in LUSummary.
-TEST_F(LUSummaryConsumerTest, RunByTypeErrorMissingData) {
- auto LU = makeLUSummary();
- LUSummaryConsumer Consumer(std::move(LU));
-
- EXPECT_THAT_EXPECTED(Consumer.run<Analysis1Data>(), llvm::Failed());
-}
-
-// contains() — present entries return true; absent entries return false.
-TEST_F(LUSummaryConsumerTest, Contains) {
- auto LU = makeLUSummary();
- const auto E1 = addEntity(*LU, "Entity1");
- insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
-
- LUSummaryConsumer Consumer(std::move(LU));
- SummaryDataStore Store = std::move(Consumer).run();
-
- // Type-safe variant.
- EXPECT_TRUE(Store.contains<Analysis1Data>());
- EXPECT_FALSE(Store.contains<Analysis2Data>());
-
- // Name-based variant.
- EXPECT_TRUE(Store.contains(SummaryName("Analysis1")));
- EXPECT_FALSE(Store.contains(SummaryName("Analysis2")));
-
- // After take(), contains() returns false.
- ASSERT_THAT_EXPECTED(Store.take<Analysis1Data>(), llvm::Succeeded());
- EXPECT_FALSE(Store.contains<Analysis1Data>());
- EXPECT_FALSE(Store.contains(SummaryName("Analysis1")));
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/SummaryNameTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/SummaryNameTest.cpp
deleted file mode 100644
index e1d35f6628232..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/SummaryNameTest.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-//===- SummaryNameTest.cpp ------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Support/FormatProviders.h"
-#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/raw_ostream.h"
-#include "gtest/gtest.h"
-
-using namespace clang;
-using namespace ssaf;
-
-namespace {
-
-TEST(SummaryNameTest, Equality) {
- const auto TestAnalysis1 = SummaryName("TestAnalysis1");
- const auto Alternative1 = SummaryName("TestAnalysis1");
- const auto TestAnalysis2 = SummaryName("TestAnalysis2");
-
- EXPECT_EQ(TestAnalysis1, Alternative1); // Idempotency.
- EXPECT_NE(Alternative1, TestAnalysis2); // Inequality.
-}
-
-TEST(SummaryNameTest, LessThan) {
- const auto TestAnalysis1 = SummaryName("TestAnalysis1");
- const auto Alternative1 = SummaryName("TestAnalysis1");
-
- const auto TestAnalysis2 = SummaryName("TestAnalysis2");
- const auto TestAnalysis3 = SummaryName("TestAnalysis3");
-
- // Equivalency.
- EXPECT_FALSE(TestAnalysis1 < Alternative1);
- EXPECT_FALSE(Alternative1 < TestAnalysis1);
-
- // Transitivity.
- EXPECT_LT(TestAnalysis1, TestAnalysis2);
- EXPECT_LT(TestAnalysis2, TestAnalysis3);
- EXPECT_LT(TestAnalysis1, TestAnalysis3);
-}
-
-TEST(SummaryNameTest, Str) {
- const auto Handle1 = SummaryName("TestAnalysis1");
- const auto Handle2 = SummaryName("TestAnalysis1");
- const auto Handle3 = SummaryName("TestAnalysis2");
-
- EXPECT_EQ(Handle1.str(), "TestAnalysis1");
- EXPECT_EQ(Handle2.str(), "TestAnalysis1");
- EXPECT_EQ(Handle3.str(), "TestAnalysis2");
-}
-
-TEST(SummaryNameTest, FormatProvider) {
- EXPECT_EQ(llvm::formatv("{0}", SummaryName("MyAnalysis")).str(),
- "SummaryName(MyAnalysis)");
-}
-
-TEST(SummaryNameTest, StreamOutput) {
- std::string S;
- llvm::raw_string_ostream(S) << SummaryName("MyAnalysis");
- EXPECT_EQ(S, "SummaryName(MyAnalysis)");
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
deleted file mode 100644
index 55c5c781e42d9..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/TUSummaryBuilderTest.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-//===- TUSummaryBuilderTest.cpp -------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryBuilder.h"
-#include "FindDecl.h"
-#include "TestFixture.h"
-#include "clang/Frontend/SSAFOptions.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/EntitySummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.h"
-#include "clang/Tooling/Tooling.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "gmock/gmock.h"
-#include "gtest/gtest.h"
-#include <memory>
-#include <type_traits>
-
-using namespace clang;
-using namespace ssaf;
-
-using llvm::SmallVector;
-using testing::Field;
-using testing::Optional;
-using testing::UnorderedElementsAre;
-
-struct SummaryResult {
- EntitySummary *Summary;
- bool Inserted;
-};
-
-template <class ConcreteEntitySummary>
-[[nodiscard]]
-static auto addSummaryTo(TUSummaryBuilder &Builder, EntityId ID,
- ConcreteEntitySummary Summary) {
- static_assert(std::is_base_of_v<EntitySummary, ConcreteEntitySummary>);
- auto NewSummary = std::make_unique<ConcreteEntitySummary>(std::move(Summary));
- SummaryName Name = NewSummary->getSummaryName();
- auto [Place, Inserted] = Builder.addSummary(ID, std::move(NewSummary));
- return std::pair{Name, SummaryResult{Place, Inserted}};
-}
-
-namespace {
-
-// Mock EntitySummary classes for testing
-struct MockSummaryData1 final : public EntitySummary {
- explicit MockSummaryData1(int Value) : Value(Value) {}
- SummaryName getSummaryName() const override {
- return SummaryName("MockSummary1");
- }
- int Value;
-};
-
-struct MockSummaryData2 final : public EntitySummary {
- explicit MockSummaryData2(std::string Text) : Text(std::move(Text)) {}
- SummaryName getSummaryName() const override {
- return SummaryName("MockSummary2");
- }
- std::string Text;
-};
-
-struct MockSummaryData3 final : public EntitySummary {
- explicit MockSummaryData3(bool Flag) : Flag(Flag) {}
- SummaryName getSummaryName() const override {
- return SummaryName("MockSummary3");
- }
- bool Flag;
-};
-
-void PrintTo(const MockSummaryData1 &S, std::ostream *OS) {
- *OS << "MockSummaryData1(" << S.getSummaryName().str().str() << ")";
-}
-void PrintTo(const MockSummaryData2 &S, std::ostream *OS) {
- *OS << "MockSummaryData2(" << S.getSummaryName().str().str() << ")";
-}
-void PrintTo(const MockSummaryData3 &S, std::ostream *OS) {
- *OS << "MockSummaryData3(" << S.getSummaryName().str().str() << ")";
-}
-
-struct TUSummaryBuilderTest : ssaf::TestFixture {
- SSAFOptions Opts;
- TUSummary Summary{
- llvm::Triple("arm64-apple-macosx"),
- BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")};
- TUSummaryBuilder Builder{Summary, Opts};
- TUSummaryExtractor Extractor{Builder};
-
- [[nodiscard]] EntityId addTestEntity(llvm::StringRef USR) {
- return getIdTable(Summary).getId(
- EntityName(USR, /*Suffix=*/"", /*Namespace=*/{}));
- }
-
- [[nodiscard]] static SmallVector<SummaryName>
- summaryNames(const TUSummary &Summary) {
- return llvm::to_vector(llvm::make_first_range(getData(Summary)));
- }
-
- [[nodiscard]] static SmallVector<EntityId>
- entitiesOfSummary(const TUSummary &Summary, const SummaryName &Name) {
- const auto &MappingIt = getData(Summary).find(Name);
- if (MappingIt == getData(Summary).end())
- return {};
- return llvm::to_vector(llvm::make_first_range(MappingIt->second));
- }
-
- template <class ConcreteSummaryData>
- [[nodiscard]] static std::optional<ConcreteSummaryData>
- getAsEntitySummary(const TUSummary &Summary, const SummaryName &Name,
- EntityId E) {
- static_assert(std::is_base_of_v<EntitySummary, ConcreteSummaryData>);
- const auto &MappingIt = getData(Summary).find(Name);
- if (MappingIt == getData(Summary).end())
- return std::nullopt;
- auto SummaryIt = MappingIt->second.find(E);
- if (SummaryIt == MappingIt->second.end())
- return std::nullopt;
- assert(Name == SummaryIt->second->getSummaryName());
- return static_cast<const ConcreteSummaryData &>(*SummaryIt->second);
- }
-};
-
-TEST_F(TUSummaryBuilderTest, AddEntity) {
- EntityName EN1("c:@F at foo", "", /*Namespace=*/{});
- EntityName EN2("c:@F at bar", "", /*Namespace=*/{});
-
- EntityIdTable &IdTable = getIdTable(Summary);
-
- EntityId ID = IdTable.getId(EN1);
- EntityId IDAlias = IdTable.getId(EN1);
- EXPECT_EQ(ID, IDAlias); // Idenpotency
-
- EntityId ID2 = IdTable.getId(EN2);
- EXPECT_NE(ID, ID2);
- EXPECT_NE(IDAlias, ID2);
-
- EXPECT_EQ(IdTable.count(), 2U);
- EXPECT_TRUE(IdTable.contains(EN1));
- EXPECT_TRUE(IdTable.contains(EN2));
-}
-
-TEST_F(TUSummaryBuilderTest, TUSummaryBuilderAddSingleSummary) {
- EntityId ID = addTestEntity("c:@F at foo");
- auto [Name, Res] = addSummaryTo(Builder, ID, MockSummaryData1(10));
- ASSERT_TRUE(Res.Inserted);
- ASSERT_TRUE(Res.Summary);
-
- // Should have a summary type with an entity.
- EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name));
- EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID));
-
- EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID),
- Optional(Field(&MockSummaryData1::Value, 10)));
-}
-
-TEST_F(TUSummaryBuilderTest, AddMultipleSummariesToSameEntity) {
- EntityId ID = addTestEntity("c:@F at foo");
-
- // Add different summary types to the same entity.
- auto [Name1, Res1] = addSummaryTo(Builder, ID, MockSummaryData1(42));
- auto [Name2, Res2] = addSummaryTo(Builder, ID, MockSummaryData2("test data"));
- auto [Name3, Res3] = addSummaryTo(Builder, ID, MockSummaryData3(true));
- ASSERT_TRUE(Res1.Inserted);
- ASSERT_TRUE(Res2.Inserted);
- ASSERT_TRUE(Res3.Inserted);
- ASSERT_TRUE(Res1.Summary);
- ASSERT_TRUE(Res2.Summary);
- ASSERT_TRUE(Res3.Summary);
-
- // All Names must be unique
- EXPECT_EQ((std::set<SummaryName>{Name1, Name2, Name3}.size()), 3U);
-
- // Should have 3 summary type with the same entity.
- EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name1, Name2, Name3));
- EXPECT_THAT(entitiesOfSummary(Summary, Name1), UnorderedElementsAre(ID));
- EXPECT_THAT(entitiesOfSummary(Summary, Name2), UnorderedElementsAre(ID));
- EXPECT_THAT(entitiesOfSummary(Summary, Name3), UnorderedElementsAre(ID));
-
- EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name1, ID),
- Optional(Field(&MockSummaryData1::Value, 42)));
- EXPECT_THAT(getAsEntitySummary<MockSummaryData2>(Summary, Name2, ID),
- Optional(Field(&MockSummaryData2::Text, "test data")));
- EXPECT_THAT(getAsEntitySummary<MockSummaryData3>(Summary, Name3, ID),
- Optional(Field(&MockSummaryData3::Flag, true)));
-}
-
-TEST_F(TUSummaryBuilderTest, AddSameSummaryTypeToMultipleEntities) {
- EntityId ID1 = addTestEntity("c:@F at foo");
- EntityId ID2 = addTestEntity("c:@F at bar");
- EntityId ID3 = addTestEntity("c:@F at baz");
-
- // Add the same summary type to different entities.
- auto [Name1, Res1] = addSummaryTo(Builder, ID1, MockSummaryData1(1));
- auto [Name2, Res2] = addSummaryTo(Builder, ID2, MockSummaryData1(2));
- auto [Name3, Res3] = addSummaryTo(Builder, ID3, MockSummaryData1(3));
- ASSERT_TRUE(Res1.Inserted);
- ASSERT_TRUE(Res2.Inserted);
- ASSERT_TRUE(Res3.Inserted);
- ASSERT_TRUE(Res1.Summary);
- ASSERT_TRUE(Res2.Summary);
- ASSERT_TRUE(Res3.Summary);
-
- // All 3 should be the same summary type.
- EXPECT_THAT((llvm::ArrayRef{Name1, Name2, Name3}), testing::Each(Name1));
-
- // Should have only 1 summary type with 3 entities.
- EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name1));
- EXPECT_THAT(entitiesOfSummary(Summary, Name1),
- UnorderedElementsAre(ID1, ID2, ID3));
-
- EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name1, ID1),
- Optional(Field(&MockSummaryData1::Value, 1)));
- EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name2, ID2),
- Optional(Field(&MockSummaryData1::Value, 2)));
- EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name3, ID3),
- Optional(Field(&MockSummaryData1::Value, 3)));
-}
-
-TEST_F(TUSummaryBuilderTest, AddConflictingSummaryToSameEntity) {
- EntityId ID = addTestEntity("c:@F at foo");
-
- auto [Name, Res] = addSummaryTo(Builder, ID, MockSummaryData1(10));
- ASSERT_TRUE(Res.Inserted);
- ASSERT_TRUE(Res.Summary);
-
- // Check the initial value.
- EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name));
- EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID));
- EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID),
- Optional(Field(&MockSummaryData1::Value, 10)));
-
- // This is a different summary of the same kind.
- auto NewSummary = std::make_unique<MockSummaryData1>(20);
- ASSERT_EQ(NewSummary->getSummaryName(), Name);
-
- // Let's add this different summary.
- // This should keep the map intact and give us the existing entity summary.
- auto [Slot, Inserted] = Builder.addSummary(ID, std::move(NewSummary));
- ASSERT_FALSE(Inserted);
- ASSERT_TRUE(Slot);
-
- // Check that the summary object is not consumed and remained the same.
- ASSERT_TRUE(NewSummary);
- ASSERT_EQ(static_cast<MockSummaryData1 *>(NewSummary.get())->Value, 20);
-
- // Check that the Slot refers to the existing entity summary.
- ASSERT_EQ(Slot->getSummaryName(), Name);
- ASSERT_EQ(static_cast<MockSummaryData1 *>(Slot)->Value, 10);
-
- // Check that the values remained the same.
- EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name));
- EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID));
- EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID),
- Optional(Field(&MockSummaryData1::Value, 10)));
-
- // We can update the existing summary.
- static_cast<MockSummaryData1 *>(Res.Summary)->Value = 30;
-
- // Check that the values remained the same except what we updated.
- EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name));
- EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID));
- EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID),
- Optional(Field(&MockSummaryData1::Value, 30)));
-}
-
-struct TUSummaryBuilderLinkageTest : TUSummaryBuilderTest {
- std::unique_ptr<ASTUnit> AST;
- static constexpr auto Internal = EntityLinkageType::Internal;
- static constexpr auto External = EntityLinkageType::External;
-
- const FunctionDecl *findFnByName(StringRef Name) {
- return ssaf::findFnByName(Name, AST->getASTContext());
- }
-
- std::optional<EntityLinkageType> getLinkageFor(std::optional<EntityId> ID) {
- if (!ID)
- return std::nullopt;
- if (auto It = getLinkageTable(Summary).find(*ID);
- It != getLinkageTable(Summary).end())
- return It->second.getLinkage();
- return std::nullopt;
- }
-};
-
-TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkage) {
- AST = tooling::buildASTFromCode("static void target() {}");
- const FunctionDecl *Fn = findFnByName("target");
- ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), Internal);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, HasExternalLinkage) {
- AST = tooling::buildASTFromCode("void target() {}");
- const FunctionDecl *Fn = findFnByName("target");
- ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), External);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, HasExternalLinkageWithInline) {
- AST = tooling::buildASTFromCode("inline void target() {}");
- const FunctionDecl *Fn = findFnByName("target");
- ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), External);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkageWithStaticInline) {
- AST = tooling::buildASTFromCode("static inline void target() {}");
- const FunctionDecl *Fn = findFnByName("target");
- ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), Internal);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, ConstVolatileGlobalHasExternalLinkage) {
- AST = tooling::buildASTFromCode("namespace ns {\n"
- " const volatile int glob = 0;\n"
- "}");
- const auto *VD = findDeclByName<VarDecl>("glob", AST->getASTContext());
- ASSERT_TRUE(VD);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(VD)), External);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, ConstGlobalHasInternalLinkage) {
- AST = tooling::buildASTFromCode("namespace ns {\n"
- " const int glob = 0;\n"
- "}");
- const auto *VD = findDeclByName<VarDecl>("glob", AST->getASTContext());
- ASSERT_TRUE(VD);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(VD)), Internal);
-}
-
-// See 'getLinkageForDecl' in
-// ScalableStaticAnalysisFramework/Core/TUSummary/TUSummaryExtractor.cpp
-
-TEST_F(TUSummaryBuilderLinkageTest, ParamOfExternalFunctionIsExternal) {
- AST = tooling::buildASTFromCode("void target(int *ptr) {}");
- const auto *PVD = findDeclByName<ParmVarDecl>("ptr", AST->getASTContext());
- ASSERT_TRUE(PVD);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(PVD)), External);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, ParamOfInlineFunctionIsExternal) {
- AST = tooling::buildASTFromCode("inline void target(int *ptr) {}");
- const auto *PVD = findDeclByName<ParmVarDecl>("ptr", AST->getASTContext());
- ASSERT_TRUE(PVD);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(PVD)), External);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, ParamOfStaticFunctionIsInternal) {
- AST = tooling::buildASTFromCode("static void target(int *ptr) {}");
- const auto *PVD = findDeclByName<ParmVarDecl>("ptr", AST->getASTContext());
- ASSERT_TRUE(PVD);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(PVD)), Internal);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, ParamOfAnonNamespaceFunctionIsInternal) {
- AST = tooling::buildASTFromCode("namespace {\n"
- " void target(int *ptr) {}\n"
- "}");
- const auto *PVD = findDeclByName<ParmVarDecl>("ptr", AST->getASTContext());
- ASSERT_TRUE(PVD);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(PVD)), Internal);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, ParamOfClassMemberFunctionIsExternal) {
- AST = tooling::buildASTFromCode(
- "class C { public: void target(int *ptr) {} };");
- const auto *PVD = findDeclByName<ParmVarDecl>("ptr", AST->getASTContext());
- ASSERT_TRUE(PVD);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(PVD)), External);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, FieldOfExternalClassIsExternal) {
- AST = tooling::buildASTFromCode("struct S { int *p; };");
- const auto *FD = findDeclByName<FieldDecl>("p", AST->getASTContext());
- ASSERT_TRUE(FD);
- EXPECT_EQ(getLinkageFor(Extractor.addEntity(FD)), External);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, ReturnSlotInheritsParentLinkage) {
- AST = tooling::buildASTFromCode("int *target() { return nullptr; }");
- const FunctionDecl *Fn = findFnByName("target");
- ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Extractor.addEntityForReturn(Fn)), External);
-}
-
-TEST_F(TUSummaryBuilderLinkageTest, ReturnSlotInheritsParentLinkageInternal) {
- AST = tooling::buildASTFromCode("static int *target() { return nullptr; }");
- const FunctionDecl *Fn = findFnByName("target");
- ASSERT_TRUE(Fn);
- EXPECT_EQ(getLinkageFor(Extractor.addEntityForReturn(Fn)), Internal);
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp b/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
deleted file mode 100644
index c1c41997abcf2..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-//===- TestFixture.cpp ----------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include <ostream>
-#include <string>
-
-namespace clang::ssaf {
-
-template <class T> static std::string asString(const T &Obj) {
- std::string S;
- llvm::raw_string_ostream(S) << Obj;
- return S;
-}
-
-void PrintTo(const BuildNamespace &BN, std::ostream *OS) {
- *OS << asString(BN);
-}
-
-void PrintTo(const EntityId &EI, std::ostream *OS) { *OS << asString(EI); }
-
-void PrintTo(const EntityLinkage &EL, std::ostream *OS) { *OS << asString(EL); }
-
-void PrintTo(const EntityName &EN, std::ostream *OS) { *OS << asString(EN); }
-
-void PrintTo(const NestedBuildNamespace &NBN, std::ostream *OS) {
- *OS << asString(NBN);
-}
-
-void PrintTo(const SummaryName &SN, std::ostream *OS) { *OS << asString(SN); }
-
-} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h b/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h
deleted file mode 100644
index 2116c2b4a664c..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h
+++ /dev/null
@@ -1,47 +0,0 @@
-//===- TestFixture.h --------------------------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_TESTFIXTURE_H
-#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_TESTFIXTURE_H
-
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/TUSummaryEncoding.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityIdTable.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-#include "gtest/gtest.h"
-#include <iosfwd>
-
-namespace clang::ssaf {
-
-class TestFixture : public ::testing::Test {
-protected:
- static WPASuite makeWPASuite() { return WPASuite(); }
-
-#define FIELD(CLASS, FIELD_NAME) \
- static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
- static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def"
-};
-
-void PrintTo(const BuildNamespace &BN, std::ostream *OS);
-void PrintTo(const EntityId &E, std::ostream *OS);
-void PrintTo(const EntityLinkage &EL, std::ostream *OS);
-void PrintTo(const EntityName &EN, std::ostream *OS);
-void PrintTo(const NestedBuildNamespace &NBN, std::ostream *OS);
-void PrintTo(const SummaryName &N, std::ostream *OS);
-
-} // namespace clang::ssaf
-
-#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSISFRAMEWORK_TESTFIXTURE_H
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
deleted file mode 100644
index 5a4192242643e..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/AnalysisDriverTest.cpp
+++ /dev/null
@@ -1,563 +0,0 @@
-//===- AnalysisDriverTest.cpp ---------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
-#include "../TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/SummaryName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisRegistry.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisResult.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/SummaryAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Testing/Support/Error.h"
-#include "gtest/gtest.h"
-#include <memory>
-#include <string>
-#include <utility>
-#include <vector>
-
-using namespace clang;
-using namespace ssaf;
-
-namespace {
-
-// ---------------------------------------------------------------------------
-// Instance counter
-// ---------------------------------------------------------------------------
-
-static int NextSummaryInstanceId = 0;
-
-// ---------------------------------------------------------------------------
-// Entity summaries
-// ---------------------------------------------------------------------------
-
-class Analysis1EntitySummary final : public EntitySummary {
-public:
- int InstanceId = NextSummaryInstanceId++;
- static SummaryName summaryName() { return SummaryName("Analysis1"); }
- SummaryName getSummaryName() const override {
- return SummaryName("Analysis1");
- }
-};
-
-class Analysis2EntitySummary final : public EntitySummary {
-public:
- int InstanceId = NextSummaryInstanceId++;
- static SummaryName summaryName() { return SummaryName("Analysis2"); }
- SummaryName getSummaryName() const override {
- return SummaryName("Analysis2");
- }
-};
-
-class Analysis3EntitySummary final : public EntitySummary {
-public:
- int InstanceId = NextSummaryInstanceId++;
- static SummaryName summaryName() { return SummaryName("Analysis3"); }
- SummaryName getSummaryName() const override {
- return SummaryName("Analysis3");
- }
-};
-
-class Analysis4EntitySummary final : public EntitySummary {
-public:
- int InstanceId = NextSummaryInstanceId++;
- static SummaryName summaryName() { return SummaryName("Analysis4"); }
- SummaryName getSummaryName() const override {
- return SummaryName("Analysis4");
- }
-};
-
-// ---------------------------------------------------------------------------
-// Analysis names
-// ---------------------------------------------------------------------------
-
-const AnalysisName Analysis1Name("Analysis1");
-const AnalysisName Analysis2Name("Analysis2");
-const AnalysisName Analysis3Name("Analysis3");
-const AnalysisName Analysis4Name("Analysis4");
-const AnalysisName Analysis5Name("Analysis5");
-const AnalysisName CycleAName("CycleA");
-const AnalysisName CycleBName("CycleB");
-
-// ---------------------------------------------------------------------------
-// Results
-// ---------------------------------------------------------------------------
-
-class Analysis1Result final : public AnalysisResult {
-public:
- static AnalysisName analysisName() { return Analysis1Name; }
- std::vector<std::pair<EntityId, int>> Entries;
- bool WasInitialized = false;
- bool WasFinalized = false;
-};
-
-class Analysis2Result final : public AnalysisResult {
-public:
- static AnalysisName analysisName() { return Analysis2Name; }
- std::vector<std::pair<EntityId, int>> Entries;
- bool WasInitialized = false;
- bool WasFinalized = false;
-};
-
-// No analysis or registration for Analysis3. Data for Analysis3 is inserted
-// into the LUSummary to verify the driver silently skips it.
-class Analysis3Result final : public AnalysisResult {
-public:
- static AnalysisName analysisName() { return Analysis3Name; }
-};
-
-// Analysis4 has a registered analysis but no data is inserted into the
-// LUSummary, so it is skipped and get() returns nullptr.
-class Analysis4Result final : public AnalysisResult {
-public:
- static AnalysisName analysisName() { return Analysis4Name; }
- std::vector<std::pair<EntityId, int>> Entries;
- bool WasInitialized = false;
- bool WasFinalized = false;
-};
-
-// Analysis5 is a derived analysis that depends on Analysis1, Analysis2, and
-// Analysis4. It verifies that the driver passes dependency results to
-// initialize() and that the initialize/step/finalize lifecycle is respected.
-class Analysis5Result final : public AnalysisResult {
-public:
- static AnalysisName analysisName() { return Analysis5Name; }
- std::vector<std::string> CallSequence;
- std::vector<std::pair<EntityId, int>> Analysis1Entries;
- std::vector<std::pair<EntityId, int>> Analysis2Entries;
- std::vector<std::pair<EntityId, int>> Analysis4Entries;
-};
-
-// CycleA and CycleB form a dependency cycle (CycleA → CycleB → CycleA).
-// Registered solely to exercise cycle detection in AnalysisDriver::toposort().
-// initialize() and step() are unreachable stubs - the cycle is caught before
-// any analysis executes.
-class CycleAResult final : public AnalysisResult {
-public:
- static AnalysisName analysisName() { return CycleAName; }
-};
-
-class CycleBResult final : public AnalysisResult {
-public:
- static AnalysisName analysisName() { return CycleBName; }
-};
-
-// ---------------------------------------------------------------------------
-// Analyses
-// ---------------------------------------------------------------------------
-
-class Analysis1 final
- : public SummaryAnalysis<Analysis1Result, Analysis1EntitySummary> {
-public:
- inline static bool WasDestroyed = false;
- ~Analysis1() { WasDestroyed = true; }
-
- llvm::Error initialize() override {
- getResult().WasInitialized = true;
- return llvm::Error::success();
- }
-
- llvm::Error add(EntityId Id, const Analysis1EntitySummary &S) override {
- getResult().Entries.push_back({Id, S.InstanceId});
- return llvm::Error::success();
- }
-
- llvm::Error finalize() override {
- getResult().WasFinalized = true;
- return llvm::Error::success();
- }
-};
-
-static AnalysisRegistry::Add<Analysis1> RegAnalysis1("Analysis for Analysis1");
-
-class Analysis2 final
- : public SummaryAnalysis<Analysis2Result, Analysis2EntitySummary> {
-public:
- inline static bool WasDestroyed = false;
- ~Analysis2() { WasDestroyed = true; }
-
- llvm::Error initialize() override {
- getResult().WasInitialized = true;
- return llvm::Error::success();
- }
-
- llvm::Error add(EntityId Id, const Analysis2EntitySummary &S) override {
- getResult().Entries.push_back({Id, S.InstanceId});
- return llvm::Error::success();
- }
-
- llvm::Error finalize() override {
- getResult().WasFinalized = true;
- return llvm::Error::success();
- }
-};
-
-static AnalysisRegistry::Add<Analysis2> RegAnalysis2("Analysis for Analysis2");
-
-// No Analysis3 or registration for Analysis3.
-
-class Analysis4 final
- : public SummaryAnalysis<Analysis4Result, Analysis4EntitySummary> {
-public:
- inline static bool WasDestroyed = false;
- ~Analysis4() { WasDestroyed = true; }
-
- llvm::Error initialize() override {
- getResult().WasInitialized = true;
- return llvm::Error::success();
- }
-
- llvm::Error add(EntityId Id, const Analysis4EntitySummary &S) override {
- getResult().Entries.push_back({Id, S.InstanceId});
- return llvm::Error::success();
- }
-
- llvm::Error finalize() override {
- getResult().WasFinalized = true;
- return llvm::Error::success();
- }
-};
-
-static AnalysisRegistry::Add<Analysis4> RegAnalysis4("Analysis for Analysis4");
-
-class Analysis5 final
- : public DerivedAnalysis<Analysis5Result, Analysis1Result, Analysis2Result,
- Analysis4Result> {
- int StepCount = 0;
-
-public:
- inline static bool WasDestroyed = false;
- ~Analysis5() { WasDestroyed = true; }
-
- llvm::Error initialize(const Analysis1Result &R1, const Analysis2Result &R2,
- const Analysis4Result &R4) override {
- getResult().CallSequence.push_back("initialize");
- getResult().Analysis1Entries = R1.Entries;
- getResult().Analysis2Entries = R2.Entries;
- getResult().Analysis4Entries = R4.Entries;
- return llvm::Error::success();
- }
-
- llvm::Expected<bool> step() override {
- getResult().CallSequence.push_back("step");
- return ++StepCount < 2;
- }
-
- llvm::Error finalize() override {
- getResult().CallSequence.push_back("finalize");
- return llvm::Error::success();
- }
-};
-
-static AnalysisRegistry::Add<Analysis5> RegAnalysis5("Analysis for Analysis5");
-
-class CycleA final : public DerivedAnalysis<CycleAResult, CycleBResult> {
-public:
- llvm::Error initialize(const CycleBResult &) override {
- return llvm::Error::success();
- }
- llvm::Expected<bool> step() override { return false; }
-};
-
-static AnalysisRegistry::Add<CycleA> RegCycleA("Cyclic analysis A (test only)");
-
-class CycleB final : public DerivedAnalysis<CycleBResult, CycleAResult> {
-public:
- llvm::Error initialize(const CycleAResult &) override {
- return llvm::Error::success();
- }
- llvm::Expected<bool> step() override { return false; }
-};
-
-static AnalysisRegistry::Add<CycleB> RegCycleB("Cyclic analysis B (test only)");
-
-// ---------------------------------------------------------------------------
-// Fixture
-// ---------------------------------------------------------------------------
-
-class AnalysisDriverTest : public TestFixture {
-protected:
- static constexpr EntityLinkage ExternalLinkage =
- EntityLinkage(EntityLinkageType::External);
-
- void SetUp() override {
- NextSummaryInstanceId = 0;
- Analysis1::WasDestroyed = false;
- Analysis2::WasDestroyed = false;
- // No Analysis3 - not registered, so no WasDestroyed flag.
- Analysis4::WasDestroyed = false;
- Analysis5::WasDestroyed = false;
- }
-
- std::unique_ptr<LUSummary> makeLUSummary() {
- NestedBuildNamespace NS(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
- return std::make_unique<LUSummary>(llvm::Triple("arm64-apple-macosx"),
- std::move(NS));
- }
-
- EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
- NestedBuildNamespace NS(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
- EntityName Name(USR.str(), "", NS);
- EntityId Id = getIdTable(LU).getId(Name);
- getLinkageTable(LU).insert({Id, ExternalLinkage});
- return Id;
- }
-
- static bool hasEntry(const std::vector<std::pair<EntityId, int>> &Entries,
- EntityId Id, int InstanceId) {
- return llvm::is_contained(Entries, std::make_pair(Id, InstanceId));
- }
-
- template <typename SummaryT>
- int insertSummary(LUSummary &LU, llvm::StringRef SN, EntityId Id) {
- auto S = std::make_unique<SummaryT>();
- int InstanceId = S->InstanceId;
- getData(LU)[SummaryName(SN.str())][Id] = std::move(S);
- return InstanceId;
- }
-};
-
-// ---------------------------------------------------------------------------
-// Tests
-// ---------------------------------------------------------------------------
-
-TEST(AnalysisRegistryTest, AnalysisIsRegistered) {
- EXPECT_TRUE(AnalysisRegistry::contains(Analysis1Name));
- EXPECT_TRUE(AnalysisRegistry::contains(Analysis2Name));
- EXPECT_FALSE(AnalysisRegistry::contains(Analysis3Name));
- EXPECT_TRUE(AnalysisRegistry::contains(Analysis4Name));
- EXPECT_TRUE(AnalysisRegistry::contains(Analysis5Name));
- EXPECT_TRUE(AnalysisRegistry::contains(CycleAName));
- EXPECT_TRUE(AnalysisRegistry::contains(CycleBName));
-}
-
-TEST(AnalysisRegistryTest, AnalysisCanBeInstantiated) {
- constexpr auto instantiate = AnalysisRegistry::instantiate;
- EXPECT_THAT_EXPECTED(
- instantiate(AnalysisName("AnalysisNonExisting")),
- llvm::FailedWithMessage(
- "no analysis registered for 'AnalysisName(AnalysisNonExisting)'"));
- EXPECT_THAT_EXPECTED(instantiate(Analysis1Name), llvm::Succeeded());
- EXPECT_THAT_EXPECTED(instantiate(Analysis2Name), llvm::Succeeded());
- // No Analysis3 - not registered, so instantiate() would fail.
- EXPECT_THAT_EXPECTED(instantiate(Analysis4Name), llvm::Succeeded());
- EXPECT_THAT_EXPECTED(instantiate(Analysis5Name), llvm::Succeeded());
- EXPECT_THAT_EXPECTED(instantiate(CycleAName), llvm::Succeeded());
- EXPECT_THAT_EXPECTED(instantiate(CycleBName), llvm::Succeeded());
-}
-
-// run<T...>() — processes the non-cyclic analyses in topological order.
-// CycleA and CycleB are excluded because they form a cycle; run() && would
-// error on them, so the type-safe subset overload is used here instead.
-TEST_F(AnalysisDriverTest, RunAll) {
- auto LU = makeLUSummary();
- const auto E1 = addEntity(*LU, "Entity1");
- const auto E2 = addEntity(*LU, "Entity2");
- const auto E3 = addEntity(*LU, "Entity3");
- const auto E4 = addEntity(*LU, "Entity4");
-
- int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
- int s1b = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E2);
- int s2a = insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
- int s2b = insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E3);
- int s4a = insertSummary<Analysis4EntitySummary>(*LU, "Analysis4", E4);
-
- // No registered analysis — Analysis3 data silently skipped.
- (void)insertSummary<Analysis3EntitySummary>(*LU, "Analysis3", E1);
-
- AnalysisDriver Driver(std::move(LU));
- auto WPAOrErr = Driver.run<Analysis1Result, Analysis2Result, Analysis4Result,
- Analysis5Result>();
- ASSERT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
-
- {
- auto R1OrErr = WPAOrErr->get<Analysis1Result>();
- ASSERT_THAT_EXPECTED(R1OrErr, llvm::Succeeded());
- EXPECT_EQ(R1OrErr->Entries.size(), 2u);
- EXPECT_TRUE(hasEntry(R1OrErr->Entries, E1, s1a));
- EXPECT_TRUE(hasEntry(R1OrErr->Entries, E2, s1b));
- EXPECT_TRUE(R1OrErr->WasInitialized);
- EXPECT_TRUE(R1OrErr->WasFinalized);
- EXPECT_TRUE(Analysis1::WasDestroyed);
- }
-
- {
- auto R2OrErr = WPAOrErr->get<Analysis2Result>();
- ASSERT_THAT_EXPECTED(R2OrErr, llvm::Succeeded());
- EXPECT_EQ(R2OrErr->Entries.size(), 2u);
- EXPECT_TRUE(hasEntry(R2OrErr->Entries, E2, s2a));
- EXPECT_TRUE(hasEntry(R2OrErr->Entries, E3, s2b));
- EXPECT_TRUE(R2OrErr->WasInitialized);
- EXPECT_TRUE(R2OrErr->WasFinalized);
- EXPECT_TRUE(Analysis2::WasDestroyed);
- }
-
- {
- auto R4OrErr = WPAOrErr->get<Analysis4Result>();
- ASSERT_THAT_EXPECTED(R4OrErr, llvm::Succeeded());
- EXPECT_EQ(R4OrErr->Entries.size(), 1u);
- EXPECT_TRUE(hasEntry(R4OrErr->Entries, E4, s4a));
- EXPECT_TRUE(R4OrErr->WasInitialized);
- EXPECT_TRUE(R4OrErr->WasFinalized);
- EXPECT_TRUE(Analysis4::WasDestroyed);
- }
-
- {
- auto R5OrErr = WPAOrErr->get<Analysis5Result>();
- ASSERT_THAT_EXPECTED(R5OrErr, llvm::Succeeded());
- EXPECT_EQ(
- R5OrErr->CallSequence,
- (std::vector<std::string>{"initialize", "step", "step", "finalize"}));
- EXPECT_EQ(R5OrErr->Analysis1Entries.size(), 2u);
- EXPECT_TRUE(hasEntry(R5OrErr->Analysis1Entries, E1, s1a));
- EXPECT_TRUE(hasEntry(R5OrErr->Analysis1Entries, E2, s1b));
- EXPECT_EQ(R5OrErr->Analysis2Entries.size(), 2u);
- EXPECT_TRUE(hasEntry(R5OrErr->Analysis2Entries, E2, s2a));
- EXPECT_TRUE(hasEntry(R5OrErr->Analysis2Entries, E3, s2b));
- EXPECT_EQ(R5OrErr->Analysis4Entries.size(), 1u);
- EXPECT_TRUE(hasEntry(R5OrErr->Analysis4Entries, E4, s4a));
- EXPECT_TRUE(Analysis5::WasDestroyed);
- }
-
- // Unregistered analysis — not present in WPA.
- EXPECT_THAT_EXPECTED(
- WPAOrErr->get<Analysis3Result>(),
- llvm::FailedWithMessage(
- "no result for 'AnalysisName(Analysis3)' in WPASuite"));
-}
-
-// run(names) — processes only the analyses for the given names.
-TEST_F(AnalysisDriverTest, RunByName) {
- auto LU = makeLUSummary();
- const auto E1 = addEntity(*LU, "Entity1");
- const auto E2 = addEntity(*LU, "Entity2");
-
- int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
- insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
-
- AnalysisDriver Driver(std::move(LU));
- auto WPAOrErr = Driver.run({AnalysisName("Analysis1")});
- ASSERT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
-
- // Analysis1 was requested and has data — present.
- auto R1OrErr = WPAOrErr->get<Analysis1Result>();
- ASSERT_THAT_EXPECTED(R1OrErr, llvm::Succeeded());
- EXPECT_EQ(R1OrErr->Entries.size(), 1u);
- EXPECT_TRUE(hasEntry(R1OrErr->Entries, E1, s1a));
- EXPECT_TRUE(R1OrErr->WasInitialized);
- EXPECT_TRUE(R1OrErr->WasFinalized);
-
- // Analysis2 was not requested — not present even though data exists.
- EXPECT_THAT_EXPECTED(
- WPAOrErr->get<Analysis2Result>(),
- llvm::FailedWithMessage(
- "no result for 'AnalysisName(Analysis2)' in WPASuite"));
-}
-
-// run(names) — error when a requested name has no data in LUSummary.
-TEST_F(AnalysisDriverTest, RunByNameErrorMissingData) {
- auto LU = makeLUSummary();
- AnalysisDriver Driver(std::move(LU));
-
- EXPECT_THAT_EXPECTED(
- Driver.run({AnalysisName("Analysis1")}),
- llvm::FailedWithMessage(
- "no data for analysis 'AnalysisName(Analysis1)' in LUSummary"));
-}
-
-// run(names) — error when a requested name has no registered analysis.
-TEST_F(AnalysisDriverTest, RunByNameErrorMissingAnalysis) {
- auto LU = makeLUSummary();
- const auto E1 = addEntity(*LU, "Entity1");
- insertSummary<Analysis3EntitySummary>(*LU, "Analysis3", E1);
-
- AnalysisDriver Driver(std::move(LU));
-
- // Analysis3 has data but no registered analysis.
- EXPECT_THAT_EXPECTED(
- Driver.run({AnalysisName("Analysis3")}),
- llvm::FailedWithMessage(
- "no analysis registered for 'AnalysisName(Analysis3)'"));
-}
-
-// run<ResultTs...>() — type-safe subset.
-TEST_F(AnalysisDriverTest, RunByType) {
- auto LU = makeLUSummary();
- const auto E1 = addEntity(*LU, "Entity1");
- const auto E2 = addEntity(*LU, "Entity2");
-
- int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
- insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
-
- AnalysisDriver Driver(std::move(LU));
- auto WPAOrErr = Driver.run<Analysis1Result>();
- ASSERT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
-
- // Analysis1 was requested — present.
- auto R1OrErr = WPAOrErr->get<Analysis1Result>();
- ASSERT_THAT_EXPECTED(R1OrErr, llvm::Succeeded());
- EXPECT_EQ(R1OrErr->Entries.size(), 1u);
- EXPECT_TRUE(hasEntry(R1OrErr->Entries, E1, s1a));
- EXPECT_TRUE(R1OrErr->WasInitialized);
- EXPECT_TRUE(R1OrErr->WasFinalized);
-
- // Analysis2 was not requested — not present even though data exists.
- EXPECT_THAT_EXPECTED(
- WPAOrErr->get<Analysis2Result>(),
- llvm::FailedWithMessage(
- "no result for 'AnalysisName(Analysis2)' in WPASuite"));
-}
-
-// run<ResultTs...>() — error when a requested type has no data in LUSummary.
-TEST_F(AnalysisDriverTest, RunByTypeErrorMissingData) {
- auto LU = makeLUSummary();
- AnalysisDriver Driver(std::move(LU));
-
- EXPECT_THAT_EXPECTED(
- Driver.run<Analysis1Result>(),
- llvm::FailedWithMessage(
- "no data for analysis 'AnalysisName(Analysis1)' in LUSummary"));
-}
-
-// contains() — present entries return true; absent entries return false.
-TEST_F(AnalysisDriverTest, Contains) {
- auto LU = makeLUSummary();
- const auto E1 = addEntity(*LU, "Entity1");
- insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
- insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E1);
- insertSummary<Analysis4EntitySummary>(*LU, "Analysis4", E1);
-
- AnalysisDriver Driver(std::move(LU));
- auto WPAOrErr = Driver.run<Analysis1Result, Analysis2Result, Analysis4Result,
- Analysis5Result>();
- ASSERT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
- EXPECT_TRUE(WPAOrErr->contains<Analysis1Result>());
- // Analysis3 has no registered analysis — never present in WPA.
- EXPECT_FALSE(WPAOrErr->contains<Analysis3Result>());
-}
-
-// run() && — errors when the registry contains a dependency cycle.
-TEST_F(AnalysisDriverTest, CycleDetected) {
- auto LU = makeLUSummary();
- AnalysisDriver Driver(std::move(LU));
- EXPECT_THAT_EXPECTED(
- std::move(Driver).run(),
- llvm::FailedWithMessage("cycle detected: AnalysisName(CycleA) -> "
- "AnalysisName(CycleB) -> AnalysisName(CycleA)"));
-}
-
-} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp b/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp
deleted file mode 100644
index 62cda9d7c6ff1..0000000000000
--- a/clang/unittests/ScalableStaticAnalysisFramework/WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp
+++ /dev/null
@@ -1,582 +0,0 @@
-//===- UnsafeBufferReachableAnalysisTest.cpp ------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "../TestFixture.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/EntityPointerLevel/EntityPointerLevel.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlow.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/PointerFlow/PointerFlowAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
-#include "clang/ScalableStaticAnalysisFramework/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/EntityLinker/LUSummary.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/BuildNamespace.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityId.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityLinkage.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/Model/EntityName.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/AnalysisDriver.h"
-#include "clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "gtest/gtest.h"
-#include <map>
-#include <memory>
-#include <optional>
-
-using namespace clang;
-using namespace ssaf;
-
-namespace clang::ssaf {
-extern PointerFlowEntitySummary buildPointerFlowEntitySummary(EdgeSet Edges);
-extern UnsafeBufferUsageEntitySummary
- buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet);
-} // namespace clang::ssaf
-
-namespace {
-
-class UnsafeBufferReachableAnalysisTest : public TestFixture {
-protected:
- using EPLEdge = std::pair<EntityPointerLevel, EntityPointerLevel>;
-
- static constexpr EntityLinkage ExternalLinkage =
- EntityLinkage(EntityLinkageType::External);
-
- std::unique_ptr<LUSummary> makeLUSummary() {
- NestedBuildNamespace NS(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
- return std::make_unique<LUSummary>(llvm::Triple("arm64-apple-macosx"),
- std::move(NS));
- }
-
- EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
- NestedBuildNamespace NS(
- {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
- EntityName Name(USR.str(), "", NS);
- EntityId Id = getIdTable(LU).getId(Name);
- getLinkageTable(LU).insert({Id, ExternalLinkage});
- return Id;
- }
-
- /// Insert a PointerFlowEntitySummary for an entity.
- void insertPointerFlowSummary(LUSummary &LU, EntityId Id, EdgeSet Edges) {
- getData(LU)[PointerFlowEntitySummary::summaryName()][Id] =
- std::make_unique<PointerFlowEntitySummary>(
- buildPointerFlowEntitySummary(std::move(Edges)));
- }
-
- /// Insert an UnsafeBufferUsageEntitySummary for an entity.
- void insertUnsafeBufferUsageSummary(LUSummary &LU, EntityId Id,
- EntityPointerLevelSet UnsafeBuffers) {
- getData(LU)[UnsafeBufferUsageEntitySummary::summaryName()][Id] =
- std::make_unique<UnsafeBufferUsageEntitySummary>(
- buildUnsafeBufferUsageEntitySummary(std::move(UnsafeBuffers)));
- }
-
- class LetterEntityBiMap {
- std::map<char, EntityId> Forward;
- std::map<EntityId, char> Reverse;
-
- public:
- void insert(char C, EntityId Id) {
- Forward.try_emplace(C, Id);
- Reverse[Id] = C;
- }
-
- EntityId operator[](char C) const { return Forward.at(C); }
- char operator[](EntityId Id) const { return Reverse.at(Id); }
- size_t size() const { return Forward.size(); }
- };
-
- /// Create entities for the entity domain \p EntDom in \p LU. For simplicity,
- /// entities are given by letters in \p EntDom. Return a "bi-directional map"
- /// between letters and EntityIds.
- LetterEntityBiMap createEntities(LUSummary &LU, llvm::ArrayRef<char> EntDom) {
- LetterEntityBiMap Result;
- for (char Name : EntDom)
- Result.insert(Name, addEntity(LU, ("E" + llvm::Twine(Name)).str()));
- return Result;
- }
-
- /// Insert both PointerFlow and UnsafeBufferUsage summaries for an entity
- /// from a list of edges and a list of starter EPLs.
- void insertSummaries(LUSummary &LU, EntityId Id,
- llvm::ArrayRef<EPLEdge> EdgeList,
- llvm::ArrayRef<EntityPointerLevel> StarterList) {
- EdgeSet Edges;
- for (const auto &[From, To] : EdgeList)
- Edges[From].insert(To);
- insertPointerFlowSummary(LU, Id, std::move(Edges));
-
- EntityPointerLevelSet Starters;
- for (const auto &EPL : StarterList)
- Starters.insert(EPL);
- insertUnsafeBufferUsageSummary(LU, Id, std::move(Starters));
- }
-
- /// Run the driver and return the flattened reachable EPL set.
- std::optional<EntityPointerLevelSet>
- computeReachables(std::unique_ptr<LUSummary> LU, unsigned Line) {
- AnalysisDriver Driver(std::move(LU));
- auto WPAOrErr =
- Driver.run<PointerFlowAnalysisResult, UnsafeBufferUsageAnalysisResult,
- UnsafeBufferReachableAnalysisResult>();
- if (!WPAOrErr) {
- ADD_FAILURE_AT(__FILE__, Line) << llvm::toString(WPAOrErr.takeError());
- return std::nullopt;
- }
- auto ROrErr = WPAOrErr->get<UnsafeBufferReachableAnalysisResult>();
- if (!ROrErr) {
- ADD_FAILURE_AT(__FILE__, Line) << llvm::toString(ROrErr.takeError());
- return std::nullopt;
- }
- EntityPointerLevelSet Result;
- for (const auto &[Id, EPLs] : ROrErr->Reachables)
- Result.insert(EPLs.begin(), EPLs.end());
- return Result;
- }
-
- using Node = std::pair<char, unsigned>;
- using Edge = std::pair<Node, Node>;
-
- // FIXME: When we use more advanced search algorithms, it may involve
- // a divide-and-conquer approach on sub-graphs organized by contributors.
- // In that case, we may want to enumerate all possible partitions of
- // how edges are distributed among contributors. For now we use
- // `singlePartition`.
-
- /// Compute reachables from \p StarterLayout in the graph defined by \p
- /// EdgeLayout. Edges and starters are all belong to one contributor.
- std::set<Node> singlePartition(llvm::ArrayRef<char> EntityDomain,
- llvm::ArrayRef<Edge> EdgeLayout,
- llvm::ArrayRef<Node> StarterLayout,
- unsigned Line) {
- auto LU = makeLUSummary();
- auto Entities = createEntities(*LU, EntityDomain);
- auto GetEPL = [&Entities](const Node &N) -> EntityPointerLevel {
- return buildEntityPointerLevel(Entities[N.first], N.second);
- };
- auto GetNode = [&Entities](const EntityPointerLevel &N) -> Node {
- return {Entities[N.getEntity()], N.getPointerLevel()};
- };
-
- std::vector<EPLEdge> Edges;
- for (const auto &[F, T] : EdgeLayout)
- Edges.push_back({GetEPL(F), GetEPL(T)});
-
- std::vector<EntityPointerLevel> Starters;
- for (const Node &N : StarterLayout)
- Starters.push_back(GetEPL(N));
-
- insertSummaries(*LU, Entities[EntityDomain[0]], Edges, Starters);
- for (size_t Idx = 1; Idx < EntityDomain.size(); ++Idx)
- insertSummaries(*LU, Entities[EntityDomain[Idx]], {}, {});
-
- auto Reachables = computeReachables(std::move(LU), Line);
- if (!Reachables)
- return {};
-
- std::set<Node> Result;
- for (auto &EPL : *Reachables)
- Result.insert(GetNode(EPL));
-
- return Result;
- }
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Tests below focus on pointer flow graph topology and the starter set.
-// Letters represent distinct entities; numbers represent pointer levels.
-//
-// For example, `LinearChain` tests a graph forming a linear chain with 3
-// edges: (a,1) -> (b,1) -> (c,1) -> (d,1) with starter {(a,1)}. Thus, {(a,1),
-// (b,1), (c,1), (d,1)} is the expected reachable set.
-////////////////////////////////////////////////////////////////////////////////
-
-// Linear chain: (a,1) -> (b,1) -> (c,1) -> (d,1).
-// Start from {(a,1)} => {(a,1), (b,1), (c,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, LinearChain) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}}, {{'b', 1}, {'c', 1}}, {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'a', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 4u);
-}
-
-// Linear chain: (a,1) -> (b,2), (b,1) -> (c,2), (c,1) -> (d,2).
-// Start from {(a,2)} => {(a,2), (b,3), (c,4), (d,5)}
-TEST_F(UnsafeBufferReachableAnalysisTest, LinearChain2) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 2}}, {{'b', 1}, {'c', 2}}, {{'c', 1}, {'d', 2}}},
- /* StarterLayout */ {{'a', 2}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 4u);
- EXPECT_EQ(Reachables,
- (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 4}, {'d', 5}}));
-}
-
-// Linear chain: (a,1) -> (b,2), (b,4) -> (c,1) -> (d,1).
-// Start from {(a,2)} => {(a,2), (b,3)} (halted at (b,3) — no key (b,j<=3))
-TEST_F(UnsafeBufferReachableAnalysisTest, LinearChain3) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 2}}, {{'b', 4}, {'c', 1}}, {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'a', 2}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 2u);
- EXPECT_EQ(Reachables, (std::set<Node>{{'a', 2}, {'b', 3}}));
-}
-
-// Linear chain: (a,1) -> (b,1) -> (c,1) -> (d,1).
-// Start from mid-chain {(c,1)} => {(c,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, LinearChainFromMiddle) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}}, {{'b', 1}, {'c', 1}}, {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'c', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 2u);
- EXPECT_TRUE(Reachables.count({'c', 1}));
- EXPECT_TRUE(Reachables.count({'d', 1}));
-}
-
-// Diamond: (a,1) -> (b,1), (a,1) -> (c,1), (b,1) -> (d,1), (c,1) -> (d,1).
-// Start from {(a,1)} => {(a,1), (b,1), (c,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, Diamond) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}},
- {{'a', 1}, {'c', 1}},
- {{'b', 1}, {'d', 1}},
- {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'a', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 4u);
-}
-
-// Diamond: (a,1) -> (b,2), (a,1) -> (c,2), (b,1) -> (d,2), (c,1) -> (d,2).
-// Start from {(a,2)} => {(a,2), (b,3), (c,3), (d,4)}
-TEST_F(UnsafeBufferReachableAnalysisTest, Diamond2) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 2}},
- {{'a', 1}, {'c', 2}},
- {{'b', 1}, {'d', 2}},
- {{'c', 1}, {'d', 2}}},
- /* StarterLayout */ {{'a', 2}}, __LINE__);
- EXPECT_EQ(Reachables,
- (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 3}, {'d', 4}}));
-}
-
-// DisconnectedDiamond: (a,1) -> (b,2), (a,1) -> (c,2), (b,5) -> (d,1), (c,5) ->
-// (d,1). Start from {(a,2)} => {(a,2), (b,3), (c,3)}
-TEST_F(UnsafeBufferReachableAnalysisTest, DisconnectedDiamond) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 2}},
- {{'a', 1}, {'c', 2}},
- {{'b', 5}, {'d', 1}},
- {{'c', 5}, {'d', 1}}},
- /* StarterLayout */ {{'a', 2}}, __LINE__);
- EXPECT_EQ(Reachables, (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 3}}));
-}
-
-// Diamond: (a,1) -> (b,1), (a,1) -> (c,1), (b,1) -> (d,1), (c,1) -> (d,1).
-// Start from one branch {(b,1)} => {(b,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, DiamondFromBranch) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}},
- {{'a', 1}, {'c', 1}},
- {{'b', 1}, {'d', 1}},
- {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'b', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 2u);
- EXPECT_TRUE(Reachables.count({'b', 1}));
- EXPECT_TRUE(Reachables.count({'d', 1}));
-}
-
-// Disconnected subgraphs: (a,1) -> (b,1), (c,1) -> (d,1).
-// Start from {(a,1)} => {(a,1), (b,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, DisconnectedSubgraphs) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */ {{{'a', 1}, {'b', 1}}, {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'a', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 2u);
- EXPECT_TRUE(Reachables.count({'a', 1}));
- EXPECT_TRUE(Reachables.count({'b', 1}));
-}
-
-// Disconnected subgraphs: (a,1) -> (b,1), (c,1) -> (d,1).
-// Start from tail {(b,1)} => {(b,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, DisconnectedSubgraphs2) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */ {{{'a', 1}, {'b', 1}}, {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'b', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 1u);
- EXPECT_TRUE(Reachables.count({'b', 1}));
-}
-
-// Cycle: (a,1) -> (b,1) -> (c,1) -> (d,1) -> (a,1).
-// Start from {(c,1)} => {(a,1), (b,1), (c,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, Cycle) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}},
- {{'b', 1}, {'c', 1}},
- {{'c', 1}, {'d', 1}},
- {{'d', 1}, {'a', 1}}},
- /* StarterLayout */ {{'c', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 4u);
- EXPECT_TRUE(Reachables.count({'a', 1}));
- EXPECT_TRUE(Reachables.count({'b', 1}));
- EXPECT_TRUE(Reachables.count({'c', 1}));
- EXPECT_TRUE(Reachables.count({'d', 1}));
-}
-
-// Cycle: (a,1) -> (b,1) -> (c,1) -> (d,1) -> (a,1).
-// Start from {(c,2)} => {(a,2), (b,2), (c,2), (d,2)}
-TEST_F(UnsafeBufferReachableAnalysisTest, Cycle2) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}},
- {{'b', 1}, {'c', 1}},
- {{'c', 1}, {'d', 1}},
- {{'d', 1}, {'a', 1}}},
- /* StarterLayout */ {{'c', 2}}, __LINE__);
- EXPECT_EQ(Reachables,
- (std::set<Node>{{'a', 2}, {'b', 2}, {'c', 2}, {'d', 2}}));
-}
-
-// Cycle: (a,1) -> (b,2) -> (c,3) -> (d,4) -> (a,1).
-// Start from {(a,2)} => {(a,2), (b,3), (c,4), (d,5)}
-TEST_F(UnsafeBufferReachableAnalysisTest, Cycle3) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 2}},
- {{'b', 2}, {'c', 3}},
- {{'c', 3}, {'d', 4}},
- {{'d', 4}, {'a', 1}}},
- /* StarterLayout */ {{'a', 2}}, __LINE__);
- EXPECT_EQ(Reachables,
- (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 4}, {'d', 5}}));
-}
-
-// Empty graph: no edges, start from {(a,1)} => {(a,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, EmptyGraph) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a'},
- /* EdgeLayout */ {},
- /* StarterLayout */ {{'a', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 1u);
- EXPECT_TRUE(Reachables.count({'a', 1}));
-}
-
-// Star: (a,1) -> (b,1), (a,1) -> (c,1), (a,1) -> (d,1).
-// Start from {(a,1)} => {(a,1), (b,1), (c,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, StarFromHub) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}}, {{'a', 1}, {'c', 1}}, {{'a', 1}, {'d', 1}}},
- /* StarterLayout */ {{'a', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 4u);
-}
-
-// Star: (a,1) -> (b,2), (a,1) -> (c,2), (a,1) -> (d,2).
-// Start from {(a,2)} => {(a,2), (b,3), (c,3), (d,3)}
-TEST_F(UnsafeBufferReachableAnalysisTest, StarFromHub2) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 2}}, {{'a', 1}, {'c', 2}}, {{'a', 1}, {'d', 2}}},
- /* StarterLayout */ {{'a', 2}}, __LINE__);
- EXPECT_EQ(Reachables,
- (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 3}, {'d', 3}}));
-}
-
-// Star: (a,2) -> (b,1), (a,2) -> (c,1), (a,2) -> (d,1).
-// Start from {(a,1)} => {(a,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, StarFromHub3) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 2}, {'b', 1}}, {{'a', 2}, {'c', 1}}, {{'a', 2}, {'d', 1}}},
- /* StarterLayout */ {{'a', 1}}, __LINE__);
- EXPECT_EQ(Reachables, (std::set<Node>{{'a', 1}}));
-}
-
-// Star: (a,1) -> (b,1), (a,1) -> (c,1), (a,1) -> (d,1).
-// Start from leaf {(c,1)} => {(c,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, StarFromLeaf) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}}, {{'a', 1}, {'c', 1}}, {{'a', 1}, {'d', 1}}},
- /* StarterLayout */ {{'c', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 1u);
- EXPECT_TRUE(Reachables.count({'c', 1}));
-}
-
-// Reverse star: (a,1) -> (d,1), (b,1) -> (d,1), (c,1) -> (d,1).
-// Start from {(a,1)} => {(a,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, ReverseStarFromSource) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'d', 1}}, {{'b', 1}, {'d', 1}}, {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'a', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 2u);
- EXPECT_TRUE(Reachables.count({'a', 1}));
- EXPECT_TRUE(Reachables.count({'d', 1}));
-}
-
-// Reverse star: (a,1) -> (d,2), (b,1) -> (d,2), (c,1) -> (d,2).
-// Start from {(a,2)} => {(a,2), (d,3)}
-TEST_F(UnsafeBufferReachableAnalysisTest, ReverseStarFromSource2) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'d', 2}}, {{'b', 1}, {'d', 2}}, {{'c', 1}, {'d', 2}}},
- /* StarterLayout */ {{'a', 2}}, __LINE__);
- EXPECT_EQ(Reachables, (std::set<Node>{{'a', 2}, {'d', 3}}));
-}
-
-// Reverse star: (a,1) -> (d,1), (b,1) -> (d,1), (c,1) -> (d,1).
-// Start from sink {(d,1)} => {(d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, ReverseStarFromSink) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'d', 1}}, {{'b', 1}, {'d', 1}}, {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'d', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 1u);
- EXPECT_TRUE(Reachables.count({'d', 1}));
-}
-
-// Reverse star: (a,1) -> (d,1), (b,1) -> (d,1), (c,1) -> (d,1).
-// Start from sink {(d,2)} => {(d,2)}
-TEST_F(UnsafeBufferReachableAnalysisTest, ReverseStarFromSink2) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'d', 1}}, {{'b', 1}, {'d', 1}}, {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'d', 2}}, __LINE__);
- EXPECT_EQ(Reachables, (std::set<Node>{{'d', 2}}));
-}
-
-// Self-loop: (a,1) -> (b,1) -> (b,1) -> (c,1) -> (d,1).
-// Start from {(a,1)} => {(a,1), (b,1), (c,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, SelfLoopFromRoot) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}},
- {{'b', 1}, {'b', 1}},
- {{'b', 1}, {'c', 1}},
- {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'a', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 4u);
-}
-
-// Self-loop: (a,1) -> (b,1) -> (b,1) -> (c,2) -> (d,2).
-// Start from {(a,2)} => {(a,2), (b,2), (c,3), (d,4)}
-TEST_F(UnsafeBufferReachableAnalysisTest, SelfLoopFromRoot2) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}},
- {{'b', 1}, {'b', 1}},
- {{'b', 1}, {'c', 2}},
- {{'c', 1}, {'d', 2}}},
- /* StarterLayout */ {{'a', 2}}, __LINE__);
- EXPECT_EQ(Reachables,
- (std::set<Node>{{'a', 2}, {'b', 2}, {'c', 3}, {'d', 4}}));
-}
-
-// Self-loop: (a,1) -> (b,1) -> (b,1) -> (c,1) -> (d,1).
-// Start from {(b,1)} => {(b,1), (c,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, SelfLoopFromLoopNode) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}},
- {{'b', 1}, {'b', 1}},
- {{'b', 1}, {'c', 1}},
- {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'b', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 3u);
- EXPECT_TRUE(Reachables.count({'b', 1}));
- EXPECT_TRUE(Reachables.count({'c', 1}));
- EXPECT_TRUE(Reachables.count({'d', 1}));
-}
-
-// Self-loop: (a,1) -> (b,1) -> (b,1) -> (c,2) -> (d,2).
-// Start from {(b,2)} => {(b,2), (c,3), (d,4)}
-TEST_F(UnsafeBufferReachableAnalysisTest, SelfLoopFromLoopNode2) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */
- {{{'a', 1}, {'b', 1}},
- {{'b', 1}, {'b', 1}},
- {{'b', 1}, {'c', 2}},
- {{'c', 1}, {'d', 2}}},
- /* StarterLayout */ {{'b', 2}}, __LINE__);
- EXPECT_EQ(Reachables, (std::set<Node>{{'b', 2}, {'c', 3}, {'d', 4}}));
-}
-
-// Multiple starters: (a,1) -> (b,1), (c,1) -> (d,1) (disconnected).
-// Start from {(a,1), (c,1)} => {(a,1), (b,1), (c,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, MultipleStartersBothChains) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */ {{{'a', 1}, {'b', 1}}, {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'a', 1}, {'c', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 4u);
-}
-
-// Multiple starters: (a,1) -> (b,2), (c,1) -> (d,2).
-// Start from {(a,2), (c,2)} => {(a,2), (b,3), (c,2), (d,3)}
-TEST_F(UnsafeBufferReachableAnalysisTest, MultipleStartersBothChains2) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */ {{{'a', 1}, {'b', 2}}, {{'c', 1}, {'d', 2}}},
- /* StarterLayout */ {{'a', 2}, {'c', 2}}, __LINE__);
- EXPECT_EQ(Reachables,
- (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 2}, {'d', 3}}));
-}
-
-// Multiple starters: (a,1) -> (b,1), (c,1) -> (d,1) (disconnected).
-// Start from leaves {(b,1), (d,1)} => {(b,1), (d,1)}
-TEST_F(UnsafeBufferReachableAnalysisTest, MultipleStartersLeaves) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c', 'd'},
- /* EdgeLayout */ {{{'a', 1}, {'b', 1}}, {{'c', 1}, {'d', 1}}},
- /* StarterLayout */ {{'b', 1}, {'d', 1}}, __LINE__);
- EXPECT_EQ(Reachables.size(), 2u);
- EXPECT_TRUE(Reachables.count({'b', 1}));
- EXPECT_TRUE(Reachables.count({'d', 1}));
-}
-
-// Multi-key, same source entity: (a,1) -> (b,1), (a,2) -> (c,1).
-// Start from {(a,3)} => {(a,3), (b,3), (c,2)}
-TEST_F(UnsafeBufferReachableAnalysisTest, MultipleKeysSameEntity) {
- auto Reachables = singlePartition(
- /* EntityDomain */ {'a', 'b', 'c'},
- /* EdgeLayout */ {{{'a', 1}, {'b', 1}}, {{'a', 2}, {'c', 1}}},
- /* StarterLayout */ {{'a', 3}}, __LINE__);
- EXPECT_EQ(Reachables, (std::set<Node>{{'a', 3}, {'b', 3}, {'c', 2}}));
-}
-
-} // namespace
diff --git a/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
index edcfcf853526d..82f633adaf261 100644
--- a/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/Driver/BUILD.gn
@@ -17,10 +17,10 @@ static_library("Driver") {
"//clang/lib/DependencyScanning",
"//clang/lib/Frontend",
"//clang/lib/Options",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/Frontend",
- "//clang/lib/ScalableStaticAnalysisFramework/SourceTransformation",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/Frontend",
+ "//clang/lib/ScalableStaticAnalysis/SourceTransformation",
"//llvm/include/llvm/Config:llvm-config",
"//llvm/lib/BinaryFormat",
"//llvm/lib/Option",
diff --git a/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn
index 737d9be4f7c48..f371f125e52e2 100644
--- a/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/lib/FrontendTool/BUILD.gn
@@ -12,10 +12,10 @@ static_library("FrontendTool") {
"//clang/lib/Frontend",
"//clang/lib/Frontend/Rewrite",
"//clang/lib/Options",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/Frontend",
- "//clang/lib/ScalableStaticAnalysisFramework/SourceTransformation",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/Frontend",
+ "//clang/lib/ScalableStaticAnalysis/SourceTransformation",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Analyses/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Analyses/BUILD.gn
deleted file mode 100644
index f54dea7d2bde5..0000000000000
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Analyses/BUILD.gn
+++ /dev/null
@@ -1,27 +0,0 @@
-static_library("Analyses") {
- output_name = "clangScalableStaticAnalysisFrameworkAnalyses"
- configs += [ "//llvm/utils/gn/build:clang_code" ]
- deps = [
- "//clang/lib/AST",
- "//clang/lib/Analysis",
- "//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//llvm/lib/Support",
- ]
- include_dirs = [ "." ]
- sources = [
- "CallGraph/CallGraphExtractor.cpp",
- "CallGraph/CallGraphJSONFormat.cpp",
- "EntityPointerLevel/EntityPointerLevel.cpp",
- "EntityPointerLevel/EntityPointerLevelFormat.cpp",
- "PointerFlow/PointerFlow.cpp",
- "PointerFlow/PointerFlowAnalysis.cpp",
- "PointerFlow/PointerFlowExtractor.cpp",
- "PointerFlow/PointerFlowFormat.cpp",
- "SSAFAnalysesCommon.cpp",
- "UnsafeBufferUsage/UnsafeBufferUsage.cpp",
- "UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp",
- "UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp",
- "UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp",
- ]
-}
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
deleted file mode 100644
index a52907c6fdfe4..0000000000000
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Core/BUILD.gn
+++ /dev/null
@@ -1,37 +0,0 @@
-static_library("Core") {
- output_name = "clangScalableStaticAnalysisFrameworkCore"
- configs += [ "//llvm/utils/gn/build:clang_code" ]
- deps = [
- "//clang/lib/AST",
- "//clang/lib/UnifiedSymbolResolution",
- "//llvm/lib/Support",
- ]
- sources = [
- "ASTEntityMapping.cpp",
- "EntityLinker/EntityLinker.cpp",
- "Model/BuildNamespace.cpp",
- "Model/EntityId.cpp",
- "Model/EntityIdTable.cpp",
- "Model/EntityLinkage.cpp",
- "Model/EntityName.cpp",
- "Model/SummaryName.cpp",
- "Serialization/JSONFormat/Artifact.cpp",
- "Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp",
- "Serialization/JSONFormat/JSONFormatImpl.cpp",
- "Serialization/JSONFormat/LUSummary.cpp",
- "Serialization/JSONFormat/LUSummaryEncoding.cpp",
- "Serialization/JSONFormat/TUSummary.cpp",
- "Serialization/JSONFormat/TUSummaryEncoding.cpp",
- "Serialization/JSONFormat/WPASuite.cpp",
- "Serialization/SerializationFormatRegistry.cpp",
- "SummaryData/LUSummaryConsumer.cpp",
- "SummaryData/SummaryDataBuilderRegistry.cpp",
- "Support/ErrorBuilder.cpp",
- "TUSummary/ExtractorRegistry.cpp",
- "TUSummary/TUSummaryBuilder.cpp",
- "TUSummary/TUSummaryExtractor.cpp",
- "WholeProgramAnalysis/AnalysisDriver.cpp",
- "WholeProgramAnalysis/AnalysisName.cpp",
- "WholeProgramAnalysis/AnalysisRegistry.cpp",
- ]
-}
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Frontend/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Frontend/BUILD.gn
deleted file mode 100644
index 184ab82dfe229..0000000000000
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Frontend/BUILD.gn
+++ /dev/null
@@ -1,13 +0,0 @@
-static_library("Frontend") {
- output_name = "clangScalableStaticAnalysisFrameworkFrontend"
- configs += [ "//llvm/utils/gn/build:clang_code" ]
- deps = [
- "//clang/lib/AST",
- "//clang/lib/Basic",
- "//clang/lib/Frontend",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/Sema",
- "//llvm/lib/Support",
- ]
- sources = [ "TUSummaryExtractorFrontendAction.cpp" ]
-}
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/BUILD.gn
deleted file mode 100644
index eb046c3d0e330..0000000000000
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/SourceTransformation/BUILD.gn
+++ /dev/null
@@ -1,12 +0,0 @@
-static_library("SourceTransformation") {
- output_name = "clangScalableStaticAnalysisFrameworkSourceTransformation"
- configs += [ "//llvm/utils/gn/build:clang_code" ]
- deps = [
- "//clang/lib/AST",
- "//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/Tooling/Core",
- "//llvm/lib/Support",
- ]
- sources = [ "TransformationRegistry.cpp" ]
-}
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Tool/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Tool/BUILD.gn
deleted file mode 100644
index b45ecef4053c0..0000000000000
--- a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysisFramework/Tool/BUILD.gn
+++ /dev/null
@@ -1,10 +0,0 @@
-static_library("Tool") {
- output_name = "clangScalableStaticAnalysisFrameworkTool"
- configs += [ "//llvm/utils/gn/build:clang_code" ]
- deps = [
- "//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//llvm/lib/Support",
- ]
- sources = [ "Utils.cpp" ]
-}
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-analyzer/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-analyzer/BUILD.gn
index 1bab754756208..4c309fd2927d4 100644
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-analyzer/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-analyzer/BUILD.gn
@@ -2,10 +2,10 @@ executable("clang-ssaf-analyzer") {
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/SourceTransformation",
- "//clang/lib/ScalableStaticAnalysisFramework/Tool",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/SourceTransformation",
+ "//clang/lib/ScalableStaticAnalysis/Tool",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn
index 59c0fde4ee3f1..aa328612d48b0 100644
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-format/BUILD.gn
@@ -2,10 +2,10 @@ executable("clang-ssaf-format") {
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/SourceTransformation",
- "//clang/lib/ScalableStaticAnalysisFramework/Tool",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/SourceTransformation",
+ "//clang/lib/ScalableStaticAnalysis/Tool",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn
index 829485a78b9fe..e2a5ce4a13721 100644
--- a/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/tools/clang-ssaf-linker/BUILD.gn
@@ -2,10 +2,10 @@ executable("clang-ssaf-linker") {
configs += [ "//llvm/utils/gn/build:clang_code" ]
deps = [
"//clang/lib/Basic",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/SourceTransformation",
- "//clang/lib/ScalableStaticAnalysisFramework/Tool",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/SourceTransformation",
+ "//clang/lib/ScalableStaticAnalysis/Tool",
"//llvm/lib/Option",
"//llvm/lib/Support",
]
diff --git a/llvm/utils/gn/secondary/clang/unittests/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/BUILD.gn
index 7d108c963c1cf..f29052a406e2d 100644
--- a/llvm/utils/gn/secondary/clang/unittests/BUILD.gn
+++ b/llvm/utils/gn/secondary/clang/unittests/BUILD.gn
@@ -29,7 +29,7 @@ group("unittests") {
deps += [
"Analysis:ClangAnalysisTests",
"Analysis/FlowSensitive:ClangAnalysisFlowSensitiveTests",
- "ScalableStaticAnalysisFramework:ClangScalableAnalysisTests",
+ "ScalableStaticAnalysis:ClangScalableAnalysisTests",
"StaticAnalyzer:StaticAnalysisTests",
]
}
diff --git a/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysisFramework/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysisFramework/BUILD.gn
deleted file mode 100644
index 1295816faa3ee..0000000000000
--- a/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysisFramework/BUILD.gn
+++ /dev/null
@@ -1,57 +0,0 @@
-import("//third-party/unittest/unittest.gni")
-
-unittest("ClangScalableAnalysisTests") {
- configs += [ "//llvm/utils/gn/build:clang_code" ]
- deps = [
- "//clang/lib/AST",
- "//clang/lib/ASTMatchers",
- "//clang/lib/Basic",
- "//clang/lib/Frontend",
- "//clang/lib/ScalableStaticAnalysisFramework/Analyses",
- "//clang/lib/ScalableStaticAnalysisFramework/Core",
- "//clang/lib/ScalableStaticAnalysisFramework/Frontend",
- "//clang/lib/ScalableStaticAnalysisFramework/SourceTransformation",
- "//clang/lib/Serialization",
- "//clang/lib/Tooling",
- "//clang/lib/Tooling/Core",
- "//llvm/lib/Frontend/OpenMP",
- "//llvm/lib/Support",
- "//llvm/lib/Testing/Support",
- ]
- include_dirs = [ "." ]
- sources = [
- "ASTEntityMappingTest.cpp",
- "Analyses/CallGraph/CallGraphExtractorTest.cpp",
- "Analyses/PointerFlow/PointerFlowTest.cpp",
- "Analyses/PointerFlow/PointerFlowWPATest.cpp",
- "Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp",
- "Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp",
- "BuildNamespaceTest.cpp",
- "EntityIdTableTest.cpp",
- "EntityIdTest.cpp",
- "EntityLinkageTest.cpp",
- "EntityLinkerTest.cpp",
- "EntityNameTest.cpp",
- "ErrorBuilderTest.cpp",
- "Frontend/TUSummaryExtractorFrontendActionTest.cpp",
- "LUSummaryTest.cpp",
- "ModelStringConversionsTest.cpp",
- "Registries/FancyAnalysisData.cpp",
- "Registries/MockSerializationFormat.cpp",
- "Registries/MockSummaryExtractor1.cpp",
- "Registries/MockSummaryExtractor2.cpp",
- "Registries/SerializationFormatRegistryTest.cpp",
- "Registries/SummaryExtractorRegistryTest.cpp",
- "Serialization/JSONFormatTest/JSONFormatTest.cpp",
- "Serialization/JSONFormatTest/LUSummaryTest.cpp",
- "Serialization/JSONFormatTest/TUSummaryTest.cpp",
- "SourceTransformation/EmitterTest.cpp",
- "SourceTransformation/RegistryTest.cpp",
- "SummaryData/SummaryDataTest.cpp",
- "SummaryNameTest.cpp",
- "TUSummaryBuilderTest.cpp",
- "TestFixture.cpp",
- "WholeProgramAnalysis/AnalysisDriverTest.cpp",
- "WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp",
- ]
-}
diff --git a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
index 997635a6a486a..ac27841da5d02 100644
--- a/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang/BUILD.bazel
@@ -2646,16 +2646,16 @@ cc_library(
cc_library(
name = "scalable_static_analysis_core",
srcs = glob([
- "lib/ScalableStaticAnalysisFramework/Core/**/*.cpp",
- "lib/ScalableStaticAnalysisFramework/Core/**/*.h",
+ "lib/ScalableStaticAnalysis/Core/**/*.cpp",
+ "lib/ScalableStaticAnalysis/Core/**/*.h",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Core/**/*.h"] + [
- "include/clang/ScalableStaticAnalysisFramework/SSAFBuiltinForceLinker.h",
- "include/clang/ScalableStaticAnalysisFramework/SSAFForceLinker.h",
+ hdrs = glob(["include/clang/ScalableStaticAnalysis/Core/**/*.h"] + [
+ "include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h",
+ "include/clang/ScalableStaticAnalysis/SSAFForceLinker.h",
]),
textual_hdrs = glob([
- "include/clang/ScalableStaticAnalysisFramework/Core/**/*.def",
- "include/clang/ScalableStaticAnalysisFramework/*.def",
+ "include/clang/ScalableStaticAnalysis/Core/**/*.def",
+ "include/clang/ScalableStaticAnalysis/*.def",
]),
deps = [
":ast",
@@ -2669,11 +2669,11 @@ cc_library(
cc_library(
name = "scalable_static_analysis_analyses",
srcs = glob([
- "lib/ScalableStaticAnalysisFramework/Analyses/**/*.cpp",
- "lib/ScalableStaticAnalysisFramework/Analyses/**/*.h",
+ "lib/ScalableStaticAnalysis/Analyses/**/*.cpp",
+ "lib/ScalableStaticAnalysis/Analyses/**/*.h",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Analyses/**/*.h"]),
- includes = ["lib/ScalableStaticAnalysisFramework/Analyses"],
+ hdrs = glob(["include/clang/ScalableStaticAnalysis/Analyses/**/*.h"]),
+ includes = ["lib/ScalableStaticAnalysis/Analyses"],
deps = [
":analysis",
":ast",
@@ -2686,9 +2686,9 @@ cc_library(
cc_library(
name = "scalable_static_analysis_tool",
srcs = glob([
- "lib/ScalableStaticAnalysisFramework/Tool/**/*.cpp",
+ "lib/ScalableStaticAnalysis/Tool/**/*.cpp",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Tool/**/*.h"]),
+ hdrs = glob(["include/clang/ScalableStaticAnalysis/Tool/**/*.h"]),
deps = [
":basic",
":scalable_static_analysis_core",
@@ -2699,9 +2699,9 @@ cc_library(
cc_library(
name = "scalable_static_analysis_source_transformation",
srcs = glob([
- "lib/ScalableStaticAnalysisFramework/SourceTransformation/**/*.cpp",
+ "lib/ScalableStaticAnalysis/SourceTransformation/**/*.cpp",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/SourceTransformation/**/*.h"]),
+ hdrs = glob(["include/clang/ScalableStaticAnalysis/SourceTransformation/**/*.h"]),
deps = [
":ast",
":basic",
@@ -2715,9 +2715,9 @@ cc_library(
cc_library(
name = "scalable_static_analysis_frontend",
srcs = glob([
- "lib/ScalableStaticAnalysisFramework/Frontend/**/*.cpp",
+ "lib/ScalableStaticAnalysis/Frontend/**/*.cpp",
]),
- hdrs = glob(["include/clang/ScalableStaticAnalysisFramework/Frontend/**/*.h"]),
+ hdrs = glob(["include/clang/ScalableStaticAnalysis/Frontend/**/*.h"]),
deps = [
":ast",
":basic",
diff --git a/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel b/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
index aaedb96dbd6c0..f422001dbab26 100644
--- a/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/clang/unittests/BUILD.bazel
@@ -786,11 +786,11 @@ cc_test(
name = "scalable_static_analysis_tests",
size = "small",
srcs = glob([
- "ScalableStaticAnalysisFramework/**/*.cpp",
- "ScalableStaticAnalysisFramework/**/*.h",
+ "ScalableStaticAnalysis/**/*.cpp",
+ "ScalableStaticAnalysis/**/*.h",
]),
- features = ["-layering_check"], # #include "../../lib/ScalableStaticAnalysisFramework/Core/ModelStringConversions.h"
- includes = ["ScalableStaticAnalysisFramework"],
+ features = ["-layering_check"], # #include "../../lib/ScalableStaticAnalysis/Core/ModelStringConversions.h"
+ includes = ["ScalableStaticAnalysis"],
deps = [
"//clang:ast",
"//clang:ast_matchers",
>From f1b49bde28f86a4e76b544cf74d35f0f7eb25466 Mon Sep 17 00:00:00 2001
From: Aviral Goel <goel.aviral at gmail.com>
Date: Wed, 24 Jun 2026 09:34:05 -0700
Subject: [PATCH 4/6] Add
---
.../developer-docs/ForceLinkerHeaders.rst | 158 ++
.../developer-docs/HowToExtend.rst | 222 +++
.../SummaryExtractionInternals.rst | 31 +
.../developer-docs/index.rst | 10 +
clang/docs/ScalableStaticAnalysis/index.rst | 19 +
.../user-docs/SummaryExtraction.rst | 37 +
.../Analyses/CallGraph/CallGraphSummary.h | 54 +
.../EntityPointerLevel/EntityPointerLevel.h | 121 ++
.../EntityPointerLevelFormat.h | 48 +
.../Analyses/PointerFlow/PointerFlow.h | 52 +
.../PointerFlow/PointerFlowAnalysis.h | 46 +
.../Analyses/PointerFlow/PointerFlowFormat.h | 37 +
.../UnsafeBufferUsage/UnsafeBufferUsage.h | 50 +
.../UnsafeBufferUsageAnalysis.h | 62 +
.../BuiltinAnchorSources.def | 31 +
.../Core/ASTEntityMapping.h | 47 +
.../Core/EntityLinker/EntityLinker.h | 95 ++
.../Core/EntityLinker/EntitySummaryEncoding.h | 42 +
.../Core/EntityLinker/LUSummary.h | 62 +
.../Core/EntityLinker/LUSummaryEncoding.h | 64 +
.../Core/EntityLinker/TUSummaryEncoding.h | 67 +
.../Core/Model/BuildNamespace.h | 129 ++
.../Core/Model/EntityId.h | 54 +
.../Core/Model/EntityIdTable.h | 53 +
.../Core/Model/EntityLinkage.h | 53 +
.../Core/Model/EntityName.h | 62 +
.../Core/Model/PrivateFieldNames.def | 52 +
.../Core/Model/SummaryName.h | 41 +
.../Core/Serialization/JSONFormat.h | 268 +++
.../Core/Serialization/SerializationFormat.h | 266 +++
.../SerializationFormatRegistry.h | 89 +
.../Core/SummaryData/LUSummaryConsumer.h | 93 ++
.../Core/SummaryData/SummaryData.h | 28 +
.../Core/SummaryData/SummaryDataBuilder.h | 97 ++
.../SummaryData/SummaryDataBuilderRegistry.h | 74 +
.../Core/SummaryData/SummaryDataStore.h | 115 ++
.../Core/SummaryData/SummaryDataTraits.h | 41 +
.../Core/Support/ErrorBuilder.h | 210 +++
.../Core/Support/FormatProviders.h | 93 ++
.../Core/TUSummary/EntitySummary.h | 30 +
.../Core/TUSummary/ExtractorRegistry.h | 56 +
.../Core/TUSummary/TUSummary.h | 51 +
.../Core/TUSummary/TUSummaryBuilder.h | 81 +
.../Core/TUSummary/TUSummaryExtractor.h | 45 +
.../Core/WholeProgramAnalysis/AnalysisBase.h | 60 +
.../WholeProgramAnalysis/AnalysisDriver.h | 95 ++
.../Core/WholeProgramAnalysis/AnalysisName.h | 49 +
.../WholeProgramAnalysis/AnalysisRegistry.h | 111 ++
.../WholeProgramAnalysis/AnalysisResult.h | 30 +
.../WholeProgramAnalysis/AnalysisTraits.h | 36 +
.../WholeProgramAnalysis/DerivedAnalysis.h | 133 ++
.../WholeProgramAnalysis/SummaryAnalysis.h | 121 ++
.../Core/WholeProgramAnalysis/WPASuite.h | 99 ++
.../TUSummaryExtractorFrontendAction.h | 33 +
.../SSAFBuiltinForceLinker.h | 43 +
.../ScalableStaticAnalysis/SSAFForceLinker.h | 25 +
.../SourceTransformation/SourceEditEmitter.h | 29 +
.../SourceTransformation/Transformation.h | 38 +
.../TransformationRegistry.h | 66 +
.../TransformationReportEmitter.h | 33 +
.../clang/ScalableStaticAnalysis/Tool/Utils.h | 95 ++
.../Analyses/CMakeLists.txt | 28 +
.../Analyses/CallGraph/CallGraphExtractor.cpp | 108 ++
.../CallGraph/CallGraphJSONFormat.cpp | 174 ++
.../EntityPointerLevel/EntityPointerLevel.cpp | 366 +++++
.../EntityPointerLevelFormat.cpp | 134 ++
.../Analyses/PointerFlow/PointerFlow.cpp | 22 +
.../PointerFlow/PointerFlowAnalysis.cpp | 122 ++
.../PointerFlow/PointerFlowExtractor.cpp | 372 +++++
.../PointerFlow/PointerFlowFormat.cpp | 132 ++
.../Analyses/SSAFAnalysesCommon.cpp | 145 ++
.../Analyses/SSAFAnalysesCommon.h | 82 +
.../UnsafeBufferUsage/UnsafeBufferUsage.cpp | 22 +
.../UnsafeBufferUsageAnalysis.cpp | 250 +++
.../UnsafeBufferUsageExtractor.cpp | 110 ++
.../UnsafeBufferUsageFormat.cpp | 86 +
.../lib/ScalableStaticAnalysis/CMakeLists.txt | 6 +
.../Core/ASTEntityMapping.cpp | 83 +
.../Core/CMakeLists.txt | 39 +
.../Core/EntityLinker/EntityLinker.cpp | 197 +++
.../Core/Model/BuildNamespace.cpp | 73 +
.../Core/Model/EntityId.cpp | 17 +
.../Core/Model/EntityIdTable.cpp | 31 +
.../Core/Model/EntityLinkage.cpp | 33 +
.../Core/Model/EntityName.cpp | 41 +
.../Core/Model/SummaryName.cpp | 17 +
.../Core/ModelStringConversions.h | 87 +
.../Serialization/JSONFormat/Artifact.cpp | 173 ++
.../JSONFormat/JSONEntitySummaryEncoding.cpp | 86 +
.../JSONFormat/JSONEntitySummaryEncoding.h | 52 +
.../JSONFormat/JSONFormatImpl.cpp | 1380 ++++++++++++++++
.../Serialization/JSONFormat/JSONFormatImpl.h | 219 +++
.../Serialization/JSONFormat/LUSummary.cpp | 196 +++
.../JSONFormat/LUSummaryEncoding.cpp | 193 +++
.../Serialization/JSONFormat/TUSummary.cpp | 196 +++
.../JSONFormat/TUSummaryEncoding.cpp | 193 +++
.../Serialization/JSONFormat/WPASuite.cpp | 226 +++
.../SerializationFormatRegistry.cpp | 37 +
.../Core/SummaryData/LUSummaryConsumer.cpp | 78 +
.../SummaryDataBuilderRegistry.cpp | 36 +
.../Core/Support/ErrorBuilder.cpp | 63 +
.../Core/TUSummary/ExtractorRegistry.cpp | 39 +
.../Core/TUSummary/TUSummaryBuilder.cpp | 36 +
.../Core/TUSummary/TUSummaryExtractor.cpp | 80 +
.../WholeProgramAnalysis/AnalysisDriver.cpp | 212 +++
.../WholeProgramAnalysis/AnalysisName.cpp | 16 +
.../WholeProgramAnalysis/AnalysisRegistry.cpp | 46 +
.../Frontend/#%2Aediff-merge%2A#zEv5rY# | 198 +++
.../Frontend/CMakeLists.txt | 16 +
.../TUSummaryExtractorFrontendAction.cpp | 199 +++
.../Plugins/CMakeLists.txt | 15 +
.../Plugins/ExamplePlugin/AnalysisResults.h | 39 +
.../Plugins/ExamplePlugin/CMakeLists.txt | 18 +
.../Plugins/ExamplePlugin/PairsAnalysis.cpp | 197 +++
.../Plugins/ExamplePlugin/TagsAnalysis.cpp | 160 ++
.../ExamplePlugin/TagsPairsAnalysis.cpp | 136 ++
.../SourceTransformation/CMakeLists.txt | 13 +
.../TransformationRegistry.cpp | 44 +
.../Tool/CMakeLists.txt | 12 +
.../lib/ScalableStaticAnalysis/Tool/Utils.cpp | 207 +++
.../ASTEntityMappingTest.cpp | 341 ++++
.../CallGraph/CallGraphExtractorTest.cpp | 517 ++++++
.../Analyses/PointerFlow/PointerFlowTest.cpp | 1443 +++++++++++++++++
.../PointerFlow/PointerFlowWPATest.cpp | 141 ++
.../UnsafeBufferUsageTest.cpp | 783 +++++++++
.../UnsafeBufferUsageWPATest.cpp | 132 ++
.../BuildNamespaceTest.cpp | 158 ++
.../ScalableStaticAnalysis/CMakeLists.txt | 56 +
.../EntityIdTableTest.cpp | 142 ++
.../ScalableStaticAnalysis/EntityIdTest.cpp | 100 ++
.../EntityLinkageTest.cpp | 117 ++
.../EntityLinkerTest.cpp | 667 ++++++++
.../ScalableStaticAnalysis/EntityNameTest.cpp | 95 ++
.../ErrorBuilderTest.cpp | 196 +++
.../ScalableStaticAnalysis/FindDecl.h | 53 +
.../ScalableStaticAnalysis/LUSummaryTest.cpp | 25 +
.../ModelStringConversionsTest.cpp | 106 ++
.../Registries/FancyAnalysisData.cpp | 60 +
.../Registries/MockSerializationFormat.cpp | 232 +++
.../Registries/MockSerializationFormat.h | 85 +
.../Registries/MockSummaryExtractor1.cpp | 44 +
.../Registries/MockSummaryExtractor2.cpp | 44 +
.../Registries/MockTUSummaryBuilder.h | 31 +
.../SerializationFormatRegistryTest.cpp | 115 ++
.../SummaryExtractorRegistryTest.cpp | 113 ++
.../JSONFormatTest/JSONFormatTest.cpp | 639 ++++++++
.../JSONFormatTest/JSONFormatTest.h | 172 ++
.../JSONFormatTest/LUSummaryTest.cpp | 452 ++++++
.../JSONFormatTest/TUSummaryTest.cpp | 445 +++++
.../SourceTransformation/EmitterTest.cpp | 81 +
.../SourceTransformation/RegistryTest.cpp | 78 +
.../SummaryData/SummaryDataTest.cpp | 398 +++++
.../SummaryNameTest.cpp | 67 +
.../TUSummaryBuilderTest.cpp | 404 +++++
.../ScalableStaticAnalysis/TestFixture.cpp | 42 +
.../ScalableStaticAnalysis/TestFixture.h | 47 +
.../AnalysisDriverTest.cpp | 563 +++++++
.../UnsafeBufferReachableAnalysisTest.cpp | 582 +++++++
158 files changed, 21886 insertions(+)
create mode 100644 clang/docs/ScalableStaticAnalysis/developer-docs/ForceLinkerHeaders.rst
create mode 100644 clang/docs/ScalableStaticAnalysis/developer-docs/HowToExtend.rst
create mode 100644 clang/docs/ScalableStaticAnalysis/developer-docs/SummaryExtractionInternals.rst
create mode 100644 clang/docs/ScalableStaticAnalysis/developer-docs/index.rst
create mode 100644 clang/docs/ScalableStaticAnalysis/index.rst
create mode 100644 clang/docs/ScalableStaticAnalysis/user-docs/SummaryExtraction.rst
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityId.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityName.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Model/SummaryName.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/SourceTransformation/SourceEditEmitter.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/SourceTransformation/Transformation.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/SourceTransformation/TransformationReportEmitter.h
create mode 100644 clang/include/clang/ScalableStaticAnalysis/Tool/Utils.h
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractor.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphJSONFormat.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/CMakeLists.txt
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/ASTEntityMapping.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/CMakeLists.txt
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Model/BuildNamespace.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Model/EntityId.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Model/EntityIdTable.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Model/EntityLinkage.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Model/EntityName.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Model/SummaryName.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/ModelStringConversions.h
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/Artifact.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.h
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummary.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummary.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/WPASuite.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/Support/ErrorBuilder.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Frontend/#%2Aediff-merge%2A#zEv5rY#
create mode 100644 clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
create mode 100644 clang/lib/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Plugins/CMakeLists.txt
create mode 100644 clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/AnalysisResults.h
create mode 100644 clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/CMakeLists.txt
create mode 100644 clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/PairsAnalysis.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsAnalysis.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/SourceTransformation/CMakeLists.txt
create mode 100644 clang/lib/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.cpp
create mode 100644 clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt
create mode 100644 clang/lib/ScalableStaticAnalysis/Tool/Utils.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/ASTEntityMappingTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractorTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowWPATest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/BuildNamespaceTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
create mode 100644 clang/unittests/ScalableStaticAnalysis/EntityIdTableTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/EntityIdTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/EntityLinkageTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/EntityLinkerTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/EntityNameTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/ErrorBuilderTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/FindDecl.h
create mode 100644 clang/unittests/ScalableStaticAnalysis/LUSummaryTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/ModelStringConversionsTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Registries/FancyAnalysisData.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.h
create mode 100644 clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor1.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor2.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Registries/MockTUSummaryBuilder.h
create mode 100644 clang/unittests/ScalableStaticAnalysis/Registries/SerializationFormatRegistryTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Registries/SummaryExtractorRegistryTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.h
create mode 100644 clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/LUSummaryTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/TUSummaryTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/SourceTransformation/EmitterTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/SourceTransformation/RegistryTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/SummaryData/SummaryDataTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/SummaryNameTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/TUSummaryBuilderTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/TestFixture.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/TestFixture.h
create mode 100644 clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/AnalysisDriverTest.cpp
create mode 100644 clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp
diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/ForceLinkerHeaders.rst b/clang/docs/ScalableStaticAnalysis/developer-docs/ForceLinkerHeaders.rst
new file mode 100644
index 0000000000000..d75855a8b8af3
--- /dev/null
+++ b/clang/docs/ScalableStaticAnalysis/developer-docs/ForceLinkerHeaders.rst
@@ -0,0 +1,158 @@
+====================
+Force-Linker Headers
+====================
+
+.. WARNING:: The framework is rapidly evolving.
+ The documentation might be out-of-sync with the implementation.
+ The purpose of this documentation is to give context for upcoming reviews.
+
+The problem
+***********
+
+SSAF uses `llvm::Registry\<\> <https://llvm.org/doxygen/classllvm_1_1Registry.html>`_
+for decentralized registration of summary extractors and serialization formats.
+Each registration is a file-scope static object whose constructor adds an entry
+to the global registry:
+
+.. code-block:: c++
+
+ // In MyExtractor.cpp
+ static TUSummaryExtractorRegistry::Add<MyExtractor>
+ RegisterExtractor("MyExtractor", "My summary extractor");
+
+When the translation unit containing this static object is compiled into a
+**static library** (``.a`` / ``.lib``), the static linker will only pull in
+object files that resolve an undefined symbol in the consuming binary.
+Because no code ever calls anything in ``MyExtractor.o`` directly, the linker
+discards the object file — and the registration never runs.
+
+This is not a problem for **shared libraries** (``.so`` / ``.dylib``), because
+the dynamic linker loads the entire shared object and runs all global
+constructors unconditionally.
+
+The solution: anchor symbols
+****************************
+
+Each registration translation unit defines a ``volatile int`` **anchor symbol**:
+
+.. code-block:: c++
+
+ // In MyExtractor.cpp - next to the registry Add<> object in the ``clang::ssaf`` namespace
+ // NOLINTNEXTLINE(misc-use-internal-linkage)
+ volatile int MyExtractorAnchorSource = 0;
+
+For **in-tree** anchors, add a single ``ANCHOR(...)`` entry to
+``BuiltinAnchorSources.def`` (in alphabetical order):
+
+.. code-block:: c++
+
+ // In clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def
+ ANCHOR(JSONFormatAnchorSource)
+ ANCHOR(MyExtractorAnchorSource) // <-- Add here, in alphabetical order
+
+``SSAFBuiltinForceLinker.h`` includes this ``.def`` file automatically to
+generate the ``extern`` declarations and the ``AnchorSources`` array — there is
+no need to edit that header directly.
+
+Any translation unit that ``#include``\s this header now has a reference to
+``MyExtractorAnchorSource``, which forces the linker to pull in
+``MyExtractor.o`` — and with it, the static ``Add<>`` registration object.
+
+The ``volatile`` qualifier is essential: without it the compiler could
+constant-fold the ``0`` and eliminate the reference entirely.
+
+These anchor symbols must be mutable (not ``const``), because otherwise on MSVC
+``const volatile`` variables would still have **internal linkage** — despite
+that the standard specifies that these should have **external linkage**.
+
+Header hierarchy
+================
+
+.. code-block:: text
+
+ SSAFForceLinker.h (umbrella — include this in binaries)
+ └── SSAFBuiltinForceLinker.h (upstream built-in anchors only)
+
+- ``clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h`` — anchors for
+ upstream-provided (built-in) extractors and formats (e.g. ``JSONFormat``).
+- ``clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h`` — umbrella header
+ that includes ``SSAFBuiltinForceLinker.h``. This is the header that
+ downstream projects should modify to add their own force-linker includes
+ (see :doc:`HowToExtend`).
+
+Include the umbrella header with ``// IWYU pragma: keep`` in any translation
+unit that must guarantee all registrations are active — typically the entry
+point of a binary that uses ``clangScalableStaticAnalysisCore``:
+
+.. code-block:: c++
+
+ // In ExecuteCompilerInvocation.cpp
+ #include "clang/ScalableStaticAnalysis/SSAFForceLinker.h" // IWYU pragma: keep
+
+Naming convention
+=================
+
+Anchor symbols follow the pattern ``<Component>AnchorSource`` in the ``clang::ssaf`` namespace.
+For example:
+
+- ``JSONFormatAnchorSource``
+- ``MyExtractorAnchorSource``
+
+All anchor sources are aggregated into a single ``BuiltinAnchorDestination``
+lambda in the force-linker header (see ``SSAFBuiltinForceLinker.h``).
+
+Considered alternatives
+***********************
+
+``--whole-archive`` / ``-force_load``
+=====================================
+
+The linker can be instructed to include *every* object file from a static
+library, regardless of whether any symbols are referenced:
+
+.. code-block:: bash
+
+ # GNU ld / lld (Linux, BSD)
+ -Wl,--whole-archive -lclangScalableStaticAnalysisCore -Wl,--no-whole-archive
+
+ # Apple ld
+ -Wl,-force_load,libclangScalableStaticAnalysisCore.a
+
+Since CMake 3.24, the ``$<LINK_LIBRARY:WHOLE_ARCHIVE,...>`` generator expression
+provides a portable way to do the same:
+
+.. code-block:: cmake
+
+ target_link_libraries(clang PRIVATE
+ "$<LINK_LIBRARY:WHOLE_ARCHIVE,clangScalableStaticAnalysisCore>")
+
+**Why we did not choose this approach**:
+
+- It is a blunt instrument — *all* object files in the library are pulled in,
+ increasing binary size.
+- The anchor approach only targets specific object files: only registrations
+ whose anchors are referenced in a force-linker header are pulled in.
+- ``--whole-archive`` semantics vary across platforms and toolchains, requiring
+ platform-specific CMake logic or the relatively new ``WHOLE_ARCHIVE``
+ generator expression.
+
+Explicit initialization functions
+=================================
+
+An alternative is a central ``initializeSSAFRegistrations()`` function that
+explicitly calls into each registration module:
+
+.. code-block:: c++
+
+ void initializeSSAFRegistrations() {
+ initializeJSONFormat();
+ initializeMyExtractor();
+ // ... one entry per registration
+ }
+
+**Why we did not choose this approach**:
+
+- It reintroduces a centralized list that must be maintained manually, defeating
+ the decoupled-registration benefit of ``llvm::Registry``.
+- Adding a new extractor or format requires modifying a central file, which
+ increases merge-conflict risk for downstream users.
diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/HowToExtend.rst b/clang/docs/ScalableStaticAnalysis/developer-docs/HowToExtend.rst
new file mode 100644
index 0000000000000..de6800bd13e0a
--- /dev/null
+++ b/clang/docs/ScalableStaticAnalysis/developer-docs/HowToExtend.rst
@@ -0,0 +1,222 @@
+===========================
+How to Extend the Framework
+===========================
+
+.. WARNING:: The framework is rapidly evolving.
+ The documentation might be out-of-sync with the implementation.
+ The purpose of this documentation is to give context for upcoming reviews.
+
+SSAF is designed to be extensible with new **summary extractors** and **serialization formats**.
+Extensions can be added in three ways:
+
+#. **Statically, in-tree** — built as part of the upstream LLVM/Clang tree.
+#. **Statically, out-of-tree (downstream)** — built in a downstream fork or project that links ``clangScalableStaticAnalysisCore`` as a static library.
+#. **Dynamically, via plugins** — loaded at runtime as shared objects.
+
+All three approaches use the same ``llvm::Registry``-based registration mechanism.
+The key difference is how the linker sees the registration:
+static libraries need :doc:`force-linker anchors <ForceLinkerHeaders>` to prevent dead-stripping, while shared libraries do not.
+
+Adding a summary extractor
+**************************
+
+A summary extractor is an ``ASTConsumer`` that inspects the AST and populates a ``TUSummary`` via the ``TUSummaryBuilder`` interface.
+
+Step 1: Implement the extractor
+===============================
+
+.. code-block:: c++
+
+ //--- MyExtractor.h
+ #include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+
+ namespace clang::ssaf {
+
+ class MyExtractor : public TUSummaryExtractor {
+ public:
+ using TUSummaryExtractor::TUSummaryExtractor;
+
+ // Override HandleTranslationUnit or any other virtual functions of an ASTConsumer...
+ // Use the SummaryBuilder to populate the summary while walking the AST.
+ };
+
+ } // namespace clang::ssaf
+
+Step 2: Register the extractor
+==============================
+
+.. code-block:: c++
+
+ //--- MyExtractor.cpp
+ #include "MyExtractor.h"
+ #include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+
+ using namespace clang::ssaf;
+
+ namespace clang::ssaf {
+ // NOLINTNEXTLINE(misc-use-internal-linkage)
+ volatile int MyExtractorAnchorSource = 0;
+ } // namespace clang::ssaf
+
+ static TUSummaryExtractorRegistry::Add<MyExtractor>
+ RegisterExtractor("MyExtractor", "My awesome summary extractor");
+
+The ``"MyExtractor"`` string is the name users pass to ``--ssaf-extract-summaries=MyExtractor``.
+
+Step 3: Add the force-linker anchor
+===================================
+
+See :doc:`ForceLinkerHeaders` for a full explanation of why this is needed.
+
+For **in-tree** additions, add one line to
+``clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def``
+(in alphabetical order):
+
+.. code-block:: c++
+
+ ANCHOR(MyExtractorAnchorSource)
+
+``SSAFBuiltinForceLinker.h`` includes this ``.def`` file automatically — no
+need to edit it directly.
+
+For **downstream** additions, see `Out-of-tree (downstream) extensions`_ below.
+
+
+Adding a serialization format
+*****************************
+
+A serialization format controls how the ``TUSummary`` is written to (and read from) disk.
+This involves more boilerplate than an extractor because each format has a per-analysis ``FormatInfo`` sub-registry.
+
+Step 1: Define the format class
+===============================
+
+Your format class must inherit from ``SerializationFormat`` and define a ``FormatInfo`` type alias:
+
+.. code-block:: c++
+
+ //--- MyFormat.h
+ #include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+ #include "clang/Support/Compiler.h"
+ #include "llvm/Support/Registry.h"
+
+ namespace clang::ssaf {
+
+ class MyFormat : public SerializationFormat {
+ public:
+ // Define the type aliases: SerializerFn, DeserializerFn
+ using FormatInfo = FormatInfoEntry<SerializerFn, DeserializerFn>;
+
+ // Override readTUSummaryEncoding, writeTUSummary, etc.
+ };
+
+ } // namespace clang::ssaf
+
+ LLVM_DECLARE_REGISTRY(llvm::Registry<MyFormat::FormatInfo>)
+
+Step 2: Register the format
+===========================
+
+.. code-block:: c++
+
+ //--- MyFormat.cpp
+ #include "MyFormat.h"
+ #include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+
+ using namespace clang::ssaf;
+
+ namespace clang::ssaf {
+ // NOLINTNEXTLINE(misc-use-internal-linkage)
+ volatile int MyFormatAnchorSource = 0;
+ } // namespace clang::ssaf
+
+ static SerializationFormatRegistry::Add<MyFormat>
+ RegisterFormat("myformat", "My awesome serialization format");
+
+ LLVM_DEFINE_REGISTRY(llvm::Registry<MyFormat::FormatInfo>)
+
+The format name (``"myformat"``) is matched against the file extension in ``--ssaf-tu-summary-file=output.myformat``.
+
+Step 3: Register per-analysis FormatInfo entries
+================================================
+
+For each analysis that should be serializable in your format, register a ``FormatInfo`` entry.
+``FormatInfo`` must be implemented for any of the summaries that wants to support ``myformat``:
+
+.. code-block:: c++
+
+ namespace {
+ using FormatInfo = MyFormat::FormatInfo;
+ struct MyAnalysisFormatInfo final : FormatInfo {
+ MyAnalysisFormatInfo() : FormatInfo{
+ SummaryName("MyAnalysis"),
+ serializeMyAnalysis,
+ deserializeMyAnalysis,
+ } {}
+ };
+ } // namespace
+
+ static llvm::Registry<FormatInfo>::Add<MyAnalysisFormatInfo>
+ RegisterFormatInfo("MyAnalysisFormatInfo",
+ "MyFormat format info for MyAnalysis");
+
+Step 4: Add the force-linker anchor
+===================================
+
+Same pattern as for extractors — add the anchor to ``BuiltinAnchorSources.def``
+(in alphabetical order). See `Adding a summary extractor`_ Step 3,
+and :doc:`ForceLinkerHeaders`.
+
+
+Static extensibility
+********************
+
+In-tree extensions
+==================
+
+For extensions that are part of the upstream LLVM/Clang tree:
+
+#. Add the anchor to ``clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def`` (in alphabetical order).
+#. Add the source files to the ``clangScalableStaticAnalysisCore`` CMake library target.
+#. That's it — the ``SSAFForceLinker.h`` umbrella includes ``SSAFBuiltinForceLinker.h``
+ transitively, so any binary that includes the umbrella will pull in the registration.
+
+Out-of-tree (downstream) extensions
+===================================
+
+Downstream projects that maintain a fork can add their own extensions without
+modifying upstream files — reducing the risk of merge-conflicts:
+
+#. Create a downstream force-linker header, e.g. ``SSAFDownstreamForceLinker.h``,
+ containing the anchor references for downstream-only extractors and formats.
+#. Include it from ``SSAFForceLinker.h`` (the umbrella):
+
+ .. code-block:: c++
+
+ // In SSAFForceLinker.h
+ #include "SSAFBuiltinForceLinker.h" // IWYU pragma: keep
+ #include "SSAFDownstreamForceLinker.h" // IWYU pragma: keep
+
+ This is a single-line addition per downstream project, minimizing conflicts with upstream changes.
+ Upstream will try to avoid modifying this umbrella header, making it a stable static extension point.
+
+#. Add the downstream source files to the build system as usual.
+
+
+Dynamic extensibility (plugins)
+*******************************
+
+Shared libraries loaded at runtime — via ``dlopen`` / ``LoadLibrary`` or the
+Clang plugin mechanism — do **not** need force-linker anchors, but having them also does not hurt.
+
+When a shared object (``.so`` / ``.dylib``) is loaded, the dynamic linker runs all global constructors in that library unconditionally.
+This means the ``llvm::Registry::Add<>`` objects execute their constructors and register themselves automatically.
+
+To use a plugin:
+
+#. Build your extractor or format as a shared library.
+#. Load it with the Clang plugin mechanism (``-fplugin=`` or ``-load``).
+#. Pass the extractor name to ``--ssaf-extract-summaries=`` as usual.
+
+No changes to any force-linker header are required.
+The ``llvm::Registry`` infrastructure handles everything once the shared object is loaded.
diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/SummaryExtractionInternals.rst b/clang/docs/ScalableStaticAnalysis/developer-docs/SummaryExtractionInternals.rst
new file mode 100644
index 0000000000000..8190f2c8c7fae
--- /dev/null
+++ b/clang/docs/ScalableStaticAnalysis/developer-docs/SummaryExtractionInternals.rst
@@ -0,0 +1,31 @@
+============================
+Summary Extraction Internals
+============================
+
+.. WARNING:: The framework is rapidly evolving.
+ The documentation might be out-of-sync with the implementation.
+ The purpose of this documentation is to give context for upcoming reviews.
+
+When ``--ssaf-tu-summary-file=`` is non-empty, ``CreateFrontendAction()`` (in ``ExecuteCompilerInvocation.cpp``)
+wraps the original ``FrontendAction`` inside a ``TUSummaryExtractorFrontendAction``.
+This ensures that the summary extraction transparently happens after the original frontend action, which is usually either compilation (``-c``) or just ``-fsyntax-only`` in tests.
+
+Lifetime of a summary extraction
+********************************
+
+The ``TUSummaryExtractorFrontendAction`` will try to construct a ``TUSummaryRunner`` ASTConsumer and report an error on failure.
+When it succeeds, it will multiplex the handlers of the ASTConsumer to every summary extractor and in the end, serialize and write the results to the desired file.
+
+Implementation details
+**********************
+
+Global Registries
+=================
+
+The framework uses `llvm::Registry\<\> <https://llvm.org/doxygen/classllvm_1_1Registry.html>`_
+as an extension point for adding new summary analyses or serialization formats.
+Each entry in the *registry* holds a name, a description and a pointer to a constructor.
+Because static linking can discard unreferenced registration objects, the framework
+uses :doc:`ForceLinkerHeaders` to ensure they are retained.
+
+For details on how to add new extractors and formats, see :doc:`HowToExtend`.
diff --git a/clang/docs/ScalableStaticAnalysis/developer-docs/index.rst b/clang/docs/ScalableStaticAnalysis/developer-docs/index.rst
new file mode 100644
index 0000000000000..139cb281a2ab4
--- /dev/null
+++ b/clang/docs/ScalableStaticAnalysis/developer-docs/index.rst
@@ -0,0 +1,10 @@
+=======================
+Developer Documentation
+=======================
+
+.. toctree::
+ :numbered:
+ :maxdepth: 2
+ :glob:
+
+ *
diff --git a/clang/docs/ScalableStaticAnalysis/index.rst b/clang/docs/ScalableStaticAnalysis/index.rst
new file mode 100644
index 0000000000000..1a2699fd7423f
--- /dev/null
+++ b/clang/docs/ScalableStaticAnalysis/index.rst
@@ -0,0 +1,19 @@
+==================================
+Scalable Static Analysis Framework
+==================================
+
+This is a framework for writing cross-translation unit analyses in a scalable and extensible setting.
+
+.. toctree::
+ :numbered:
+ :maxdepth: 2
+ :glob:
+
+ user-docs/*
+
+:doc:`Developer documentation <developer-docs/index>`
+
+.. toctree::
+ :hidden:
+
+ developer-docs/index
diff --git a/clang/docs/ScalableStaticAnalysis/user-docs/SummaryExtraction.rst b/clang/docs/ScalableStaticAnalysis/user-docs/SummaryExtraction.rst
new file mode 100644
index 0000000000000..96892cfa5fdea
--- /dev/null
+++ b/clang/docs/ScalableStaticAnalysis/user-docs/SummaryExtraction.rst
@@ -0,0 +1,37 @@
+==================
+Summary Extraction
+==================
+
+.. WARNING:: The framework is rapidly evolving.
+ The documentation might be out-of-sync with the implementation.
+ The purpose of this documentation is to give context for upcoming reviews.
+
+Command-line interface
+**********************
+
+Two flags control summary extraction:
+
+- ``--ssaf-extract-summaries=<name1>,<name2>,...``: Comma-separated list of summary extractor names to enable.
+- ``--ssaf-tu-summary-file=<path>.<format>``: Output file for the extracted summaries. The file extension selects the serialization format (e.g. ``.json``).
+- ``--ssaf-list-extractors``: List the available summary extractors.
+- ``--ssaf-list-formats``: List the available serialization formats.
+
+Example invocation:
+
+.. code-block:: bash
+
+ clang --ssaf-extract-summaries=MyAwesomeAnalysis \
+ --ssaf-tu-summary-file=my-tu-summary.json \
+ -c input.cpp -o input.o
+
+ clang --ssaf-list-extractors --ssaf-list-formats
+
+Diagnostics
+***********
+
+In case the ``--ssaf-*`` flags are used incorrectly, or some extractor fails to implement the desired serialization format
+or just happens to have an error, then the error is forwarded as a ``scalable-static-analysis-framework`` error.
+These errors can be downgraded into warnings using ``-Wno-error=scalable-static-analysis-framework``.
+These errors can be completely suppressed using ``-Wno-scalable-static-analysis-framework``.
+
+See the `diagnostic flags <https://clang.llvm.org/docs/DiagnosticsReference.html#wscalable-static-analysis-framework>`_ for the full list of diagnostics controlled by ``-Wscalable-static-analysis-framework``.
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h
new file mode 100644
index 0000000000000..e3a335384792a
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h
@@ -0,0 +1,54 @@
+//===- CallGraphSummary.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include <set>
+
+namespace clang::ssaf {
+
+/// Summary of direct call-graph edges for a single function entity.
+///
+/// Represents a function definition, and information about its callees.
+///
+/// \bug Indirect calls (e.g. function pointers) are not represented.
+/// \bug ObjCMessageExprs are not represented.
+/// \bug Primary template functions are not represented.
+struct CallGraphSummary final : public EntitySummary {
+ struct Location {
+ std::string File;
+ unsigned Line;
+ unsigned Column;
+ };
+
+ static constexpr llvm::StringLiteral Name = "CallGraph";
+ SummaryName getSummaryName() const override {
+ return SummaryName(Name.str());
+ }
+
+ /// Represents the location of the function.
+ Location Definition = {};
+
+ /// The set of direct callees of this function.
+ std::set<EntityId> DirectCallees;
+
+ /// The set of virtual callees of this function.
+ std::set<EntityId> VirtualCallees;
+
+ /// A human-readable name of the function.
+ /// This is not guaranteed to be accurate or unique.
+ std::string PrettyName;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_CALLGRAPH_CALLGRAPHSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h
new file mode 100644
index 0000000000000..c296016258f8d
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h
@@ -0,0 +1,121 @@
+//===- EntityPointerLevel.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
+
+#include "clang/AST/Expr.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include <set>
+
+namespace clang::ssaf {
+class TUSummaryExtractor;
+
+/// An EntityPointerLevel is associated with a level of the declared
+/// pointer/array type of an entity. In the fully-expanded spelling of the
+/// declared type, a EntityPointerLevel is associated with a '*' (or a '[]`) in
+/// that declaration.
+///
+/// For example, for 'int *p[10];', there are two EntityPointerLevels.
+/// One is associated with 'int *[10]' of 'p' and the other is associated with
+/// 'int *' of 'p'.
+///
+/// An EntityPointerLevel can be identified by an EntityId and an unsigned
+/// integer indicating the pointer level: '(EntityId, PointerLevel)'.
+/// An EntityPointerLevel 'P' is valid iff 'P.EntityId' has a pointer type with
+/// at least 'P.PointerLevel' levels (This implies 'P.PointerLevel > 0').
+///
+/// For the same example 'int *p[10];', the EntityPointerLevels below are valid:
+/// - '(p, 2)' is associated with the 'int *' part of the declared type of 'p';
+/// - '(p, 1)' is associated with the 'int *[10]' part of the declared type of
+/// 'p'.
+class EntityPointerLevel {
+ EntityId Entity;
+ unsigned PointerLevel;
+
+ friend class EntityPointerLevelTranslator;
+ // For unittests:
+ friend EntityPointerLevel buildEntityPointerLevel(EntityId, unsigned);
+
+ explicit EntityPointerLevel(std::pair<EntityId, unsigned> Pair)
+ : Entity(Pair.first), PointerLevel(Pair.second) {}
+
+public:
+ EntityId getEntity() const { return Entity; }
+ unsigned getPointerLevel() const { return PointerLevel; }
+
+ bool operator==(const EntityPointerLevel &Other) const {
+ return std::tie(Entity, PointerLevel) ==
+ std::tie(Other.Entity, Other.PointerLevel);
+ }
+
+ bool operator!=(const EntityPointerLevel &Other) const {
+ return !(*this == Other);
+ }
+
+ bool operator<(const EntityPointerLevel &Other) const {
+ return std::tie(Entity, PointerLevel) <
+ std::tie(Other.Entity, Other.PointerLevel);
+ }
+
+ /// Compares `EntityPointerLevel`s; additionally, partially compares
+ /// `EntityPointerLevel` with `EntityId`.
+ struct Comparator {
+ using is_transparent = void;
+ bool operator()(const EntityPointerLevel &L,
+ const EntityPointerLevel &R) const {
+ return L < R;
+ }
+ bool operator()(const EntityId &L, const EntityPointerLevel &R) const {
+ return L < R.getEntity();
+ }
+ bool operator()(const EntityPointerLevel &L, const EntityId &R) const {
+ return L.getEntity() < R;
+ }
+ };
+};
+
+using EntityPointerLevelSet =
+ std::set<EntityPointerLevel, EntityPointerLevel::Comparator>;
+
+/// Translate a pointer/array type expression 'E' to a (set of)
+/// EntityPointerLevel(s) associated with the declared type of the base address
+/// of `E`. If the base address of `E` is not associated with an entity, the
+/// translation result is an empty set.
+///
+/// \param E the pointer expression to be translated
+/// \param Ctx the AST context of `E`
+/// \param AddEntity the callback provided by the caller to convert EntityNames
+/// to EntityIds.
+llvm::Expected<EntityPointerLevelSet>
+translateEntityPointerLevel(const Expr *E, ASTContext &Ctx,
+ TUSummaryExtractor &Extractor);
+
+/// Creates a `EntityPointerLevel` from a pair of an EntityId and a pointer
+/// level:
+EntityPointerLevel buildEntityPointerLevel(EntityId, unsigned);
+
+/// Create an EntityPointerLevel (EPL) from a NamedDecl of a pointer/array type.
+///
+/// \param ND the NamedDecl of a pointer/array type.
+/// \param AddEntity the callback provided by the caller to convert EntityNames
+/// to EntityIds.
+/// \param IsFunRet true iff the created EPL is associated with the return type
+/// of a function entity.
+llvm::Expected<EntityPointerLevel>
+createEntityPointerLevel(const NamedDecl *ND, TUSummaryExtractor &Extractor,
+ bool IsFunRet = false);
+
+/// Creates a new EntityPointerLevel (EPL) from `E` by incrementing `E`'s
+/// pointer level.
+/// \return the EPL that is associated with the pointee (or array element) type
+/// of `E`'s associated pointer/array type of the same entity.
+EntityPointerLevel incrementPointerLevel(const EntityPointerLevel &E);
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVEL_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
new file mode 100644
index 0000000000000..e650f3061181f
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h
@@ -0,0 +1,48 @@
+//===- EntityPointerLevelFormat.h -------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
+
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "llvm/ADT/iterator_range.h"
+#include <map>
+
+namespace clang::ssaf {
+llvm::json::Value
+entityPointerLevelToJSON(const EntityPointerLevel &EPL,
+ JSONFormat::EntityIdToJSONFn EntityId2JSON);
+
+Expected<EntityPointerLevel>
+entityPointerLevelFromJSON(const llvm::json::Value &EPLData,
+ JSONFormat::EntityIdFromJSONFn EntityIdFromJSON);
+
+llvm::json::Array entityPointerLevelSetToJSON(
+ llvm::iterator_range<EntityPointerLevelSet::const_iterator> EPLs,
+ JSONFormat::EntityIdToJSONFn EntityId2JSON);
+
+Expected<EntityPointerLevelSet>
+entityPointerLevelSetFromJSON(const llvm::json::Array &EPLsData,
+ JSONFormat::EntityIdFromJSONFn EntityIdFromJSON);
+
+/// Serialize a map<EntityId, EntityPointerLevelSet> as a flat array of
+/// alternating [EntityId, EntityPointerLevelSet, ...] pairs.
+llvm::json::Array entityPointerLevelMapToJSON(
+ const std::map<EntityId, EntityPointerLevelSet> &Map,
+ JSONFormat::EntityIdToJSONFn IdToJSON);
+
+/// Deserialize a flat array of alternating [EntityId, EntityPointerLevelSet,
+/// ...] pairs into a map.
+Expected<std::map<EntityId, EntityPointerLevelSet>>
+entityPointerLevelMapFromJSON(const llvm::json::Array &Content,
+ JSONFormat::EntityIdFromJSONFn IdFromJSON);
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_ENTITYPOINTERLEVEL_ENTITYPOINTERLEVELFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h
new file mode 100644
index 0000000000000..abff90cc37662
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h
@@ -0,0 +1,52 @@
+//===- PointerFlow.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the per-translation-unit summary type for the
+// pointer-flow analysis, which records static pointer assignment sites
+// as directed graph edges (EdgeSet).
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_POINTERFLOW_POINTERFLOW_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_POINTERFLOW_POINTERFLOW_H
+
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+
+namespace clang::ssaf {
+
+/// Maps each LHS pointer (source / assignee) to the set of RHS pointers
+/// (destinations / assigned values) at static assignment sites.
+using EdgeSet = std::map<EntityPointerLevel, EntityPointerLevelSet>;
+
+class PointerFlowEntitySummary final : public EntitySummary {
+ EdgeSet Edges;
+
+ friend PointerFlowEntitySummary buildPointerFlowEntitySummary(EdgeSet Edges);
+ friend llvm::iterator_range<EdgeSet::const_iterator>
+ getEdges(const PointerFlowEntitySummary &);
+
+ explicit PointerFlowEntitySummary(EdgeSet Edges) : Edges(std::move(Edges)) {}
+
+public:
+ static constexpr llvm::StringLiteral Name = "PointerFlow";
+
+ SummaryName getSummaryName() const override { return summaryName(); }
+
+ bool operator==(const EdgeSet &Other) const { return Edges == Other; }
+
+ bool operator==(const PointerFlowEntitySummary &Other) const {
+ return Edges == Other.Edges;
+ }
+
+ bool empty() const { return Edges.empty(); }
+
+ static SummaryName summaryName() { return SummaryName{Name.str()}; }
+};
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_POINTERFLOW_POINTERFLOW_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.h
new file mode 100644
index 0000000000000..645336d1633f0
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.h
@@ -0,0 +1,46 @@
+//===- PointerFlowAnalysis.h ------------------------------------*- C++- *-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines PointerFlowAnalysisResult — the whole-program pointer-flow graph
+// aggregated from per-translation-unit EdgeSet summaries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_POINTERFLOW_POINTERFLOWANALYSIS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_POINTERFLOW_POINTERFLOWANALYSIS_H
+
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "llvm/ADT/StringRef.h"
+#include <map>
+
+namespace clang::ssaf {
+
+constexpr llvm::StringLiteral PointerFlowAnalysisResultName =
+ "PointerFlowAnalysisResult";
+
+/// The whole-program pointer-flow graph. Each directed edge 'src -> dest'
+/// records a static assignment site where 'src' (the LHS / assignee) is
+/// assigned the value of 'dest' (the RHS / assigned value).
+///
+/// This edge direction matches property-propagation direction: if a property
+/// (such as a bounds requirement) holds for 'src', it must also hold for
+/// 'dest', because 'dest' supplies the value that 'src' will hold.
+struct PointerFlowAnalysisResult final : AnalysisResult {
+ static AnalysisName analysisName() {
+ return AnalysisName(PointerFlowAnalysisResultName.str());
+ }
+
+ std::map<EntityId, EdgeSet> Edges;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_POINTERFLOW_POINTERFLOWANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.h
new file mode 100644
index 0000000000000..1f1d5e8210379
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.h
@@ -0,0 +1,37 @@
+//===- PointerFlowFormat.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// JSON serialization helpers for EdgeSet (PointerFlow edge maps).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_POINTERFLOW_POINTERFLOWFORMAT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_POINTERFLOW_POINTERFLOWFORMAT_H
+
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "llvm/ADT/iterator_range.h"
+
+namespace clang::ssaf {
+
+/// Serialize an EdgeSet
+/// {(src1, dest1), (src1, dest2), (src2, dest3), (src2, dest4), ...}
+/// to an array of arrays of EntityPointerLevels:
+/// [ [src1, dest1, dest2, ...], [src2, dest3, dest4, ...], ... ]
+llvm::json::Array
+edgeSetToJSON(llvm::iterator_range<EdgeSet::const_iterator> Edges,
+ JSONFormat::EntityIdToJSONFn IdToJSON);
+
+/// Deserialize an EdgeSet from the array format produced by `edgeSetToJSON`.
+llvm::Expected<EdgeSet>
+edgeSetFromJSON(const llvm::json::Array &EdgesData,
+ JSONFormat::EntityIdFromJSONFn IdFromJSON);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_POINTERFLOW_POINTERFLOWFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
new file mode 100644
index 0000000000000..c84104c10db7e
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h
@@ -0,0 +1,50 @@
+//===- UnsafeBufferUsage.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
+
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+
+namespace clang::ssaf {
+/// An UnsafeBufferUsageEntitySummary contains a set of EntityPointerLevels
+/// extracted from unsafe buffer pointers contributed by an entity.
+class UnsafeBufferUsageEntitySummary final : public EntitySummary {
+ const EntityPointerLevelSet UnsafeBuffers;
+
+ friend class UnsafeBufferUsageTUSummaryExtractor;
+ friend UnsafeBufferUsageEntitySummary
+ buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet);
+ friend llvm::iterator_range<EntityPointerLevelSet::const_iterator>
+ getUnsafeBuffers(const UnsafeBufferUsageEntitySummary &);
+
+ explicit UnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers)
+ : UnsafeBuffers(std::move(UnsafeBuffers)) {}
+
+public:
+ static constexpr llvm::StringLiteral Name = "UnsafeBufferUsage";
+
+ SummaryName getSummaryName() const override { return summaryName(); };
+
+ bool operator==(const EntityPointerLevelSet &Other) const {
+ return UnsafeBuffers == Other;
+ }
+
+ bool operator==(const UnsafeBufferUsageEntitySummary &Other) const {
+ return UnsafeBuffers == Other.UnsafeBuffers;
+ }
+
+ bool empty() const { return UnsafeBuffers.empty(); }
+
+ static SummaryName summaryName() { return SummaryName{Name.str()}; }
+};
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h b/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h
new file mode 100644
index 0000000000000..aa19c8a7e945e
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h
@@ -0,0 +1,62 @@
+//===- UnsafeBufferUsageAnalysis.h ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines:
+// - UnsafeBufferUsageAnalysisResult
+// - the whole-program analysis result
+// type for UnsafeBufferUsageAnalysis. It collects unsafe buffer usages
+// throughout the whole program.
+//
+// - UnsafeBufferReachableAnalysisResult
+// - the whole-program analysis result
+// type for UnsafeBufferReachableAnalysis. It propagates unsafe buffer
+// usages through the pointer flow graph, starting from the initial set
+// collected by UnsafeBufferUsageAnalysis.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEANALYSIS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEANALYSIS_H
+
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "llvm/ADT/StringRef.h"
+#include <map>
+
+namespace clang::ssaf {
+
+constexpr llvm::StringLiteral UnsafeBufferUsageAnalysisResultName =
+ "UnsafeBufferUsageAnalysisResult";
+constexpr llvm::StringLiteral UnsafeBufferReachableAnalysisResultName =
+ "UnsafeBufferReachableAnalysisResult";
+
+struct UnsafeBufferUsageAnalysisResult final : AnalysisResult {
+ static AnalysisName analysisName() {
+ return AnalysisName(UnsafeBufferUsageAnalysisResultName.str());
+ }
+
+ /// Whole-program set of unsafe buffer pointers:
+ std::map<EntityId, EntityPointerLevelSet> UnsafeBuffers;
+
+ auto begin() const { return UnsafeBuffers.begin(); }
+ auto end() const { return UnsafeBuffers.end(); }
+};
+
+struct UnsafeBufferReachableAnalysisResult final : AnalysisResult {
+ static AnalysisName analysisName() {
+ return AnalysisName(UnsafeBufferReachableAnalysisResultName.str());
+ }
+
+ std::map<EntityId, EntityPointerLevelSet> Reachables;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_UNSAFEBUFFERUSAGE_UNSAFEBUFFERUSAGEANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def b/clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def
new file mode 100644
index 0000000000000..ba4944ea984cb
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/BuiltinAnchorSources.def
@@ -0,0 +1,31 @@
+//===- BuiltinAnchorSources.def ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file lists all the SSAF Anchor source names.
+/// This file should be exclusively used by SSAFBuiltinForceLinker.h
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef ANCHOR
+#define ANCHOR(NAME)
+#endif
+
+ANCHOR(AnalysisRegistryAnchorSource)
+ANCHOR(CallGraphExtractorAnchorSource)
+ANCHOR(CallGraphJSONFormatAnchorSource)
+ANCHOR(JSONFormatAnchorSource)
+ANCHOR(PointerFlowAnalysisAnchorSource)
+ANCHOR(PointerFlowExtractorAnchorSource)
+ANCHOR(PointerFlowJSONFormatAnchorSource)
+ANCHOR(SSAFSourceTransformationAnchorSource)
+ANCHOR(UnsafeBufferUsageAnalysisAnchorSource)
+ANCHOR(UnsafeBufferUsageExtractorAnchorSource)
+ANCHOR(UnsafeBufferUsageJSONFormatAnchorSource)
+
+#undef ANCHOR
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h b/clang/include/clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h
new file mode 100644
index 0000000000000..aa8ce469397a0
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h
@@ -0,0 +1,47 @@
+//===- ASTEntityMapping.h - AST to SSAF Entity mapping ----------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ASTENTITYMAPPING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ASTENTITYMAPPING_H
+
+#include "clang/AST/Decl.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "llvm/ADT/StringRef.h"
+#include <optional>
+
+namespace clang::ssaf {
+
+/// Maps a declaration to an EntityName.
+///
+/// Supported declaration types for entity mapping:
+/// - Functions and methods
+/// - Global Variables
+/// - Function parameters
+/// - Struct/class/union type definitions
+/// - Struct/class/union fields
+///
+/// Implicit declarations and compiler builtins are not mapped.
+///
+/// \param D The declaration to map. Must not be null.
+///
+/// \return An EntityName if the declaration can be mapped, std::nullopt
+/// otherwise.
+std::optional<EntityName> getEntityName(const Decl *D);
+
+/// Maps return entity of a function to an EntityName.
+/// The returned name uniquely identifies the return value of function \param
+/// FD.
+///
+/// \param FD The function declaration. Must not be null.
+///
+/// \return An EntityName for the function's return entity.
+std::optional<EntityName> getEntityNameForReturn(const FunctionDecl *FD);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ASTENTITYMAPPING_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h
new file mode 100644
index 0000000000000..f07def1a9b344
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h
@@ -0,0 +1,95 @@
+//===- EntityLinker.h - Class for linking entities --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the EntityLinker class that combines multiple TU summaries
+// into a unified LU summary by deduplicating entities and patching summaries.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYLINKER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYLINKER_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "llvm/Support/Error.h"
+#include "llvm/TargetParser/Triple.h"
+#include <map>
+#include <memory>
+#include <set>
+#include <vector>
+
+namespace clang::ssaf {
+
+class TUSummaryEncoding;
+
+class EntityLinker {
+ LUSummaryEncoding Output;
+ std::set<BuildNamespace> ProcessedTUNamespaces;
+
+public:
+ /// Constructs an EntityLinker to link TU summaries into a LU summary.
+ ///
+ /// \param TargetTriple The target triple of the link unit. Every linked TU
+ /// must report the same triple.
+ /// \param LUNamespace The namespace identifying this link unit.
+ EntityLinker(llvm::Triple TargetTriple, NestedBuildNamespace LUNamespace)
+ : Output(std::move(TargetTriple), std::move(LUNamespace)) {}
+
+ /// Links a TU summary into a LU summary.
+ ///
+ /// Deduplicates entities, patches entity ID references in the entity summary,
+ /// and merges them into a single data store.
+ ///
+ /// \param Summary The TU summary to link. Ownership is transferred.
+ /// \returns Error if the TU namespace has already been linked or if patching
+ /// fails, success otherwise. Corrupted summary data (missing linkage
+ /// information, duplicate entity IDs, etc.) triggers a fatal error.
+ llvm::Error link(std::unique_ptr<TUSummaryEncoding> Summary);
+
+ /// Returns the accumulated LU summary.
+ ///
+ /// \returns LU summary containing all the deduplicated and patched entity
+ /// summaries.
+ LUSummaryEncoding takeOutput() && { return std::move(Output); }
+
+private:
+ /// Resolves a TU entity name to an LU entity name and ID.
+ ///
+ /// \param OldName The entity name in the TU namespace.
+ /// \param Linkage The linkage determining namespace resolution strategy.
+ /// \returns The resolved LU EntityId.
+ EntityId resolveEntity(const EntityName &OldName,
+ const EntityLinkage &Linkage,
+ const NestedBuildNamespace &TUNamespace);
+
+ /// Resolves each TU EntityId to its corresponding LU EntityId.
+ ///
+ /// \param Summary The TU summary whose entities are being resolved.
+ /// \returns A map from TU EntityIds to their corresponding LU EntityIds.
+ std::map<EntityId, EntityId> resolve(const TUSummaryEncoding &Summary);
+
+ /// Merges all summary data from a TU summary into the LU Summary.
+ ///
+ /// \param Summary The TU summary whose data is being merged.
+ /// \param EntityResolutionTable Map from TU EntityIds to LU EntityIds.
+ /// \returns Pointers to each EntitySummaryEncoding successfully merged.
+ std::vector<EntitySummaryEncoding *>
+ merge(TUSummaryEncoding &Summary,
+ const std::map<EntityId, EntityId> &EntityResolutionTable);
+
+ /// Patches EntityId references in merged summary data.
+ ///
+ /// \param PatchTargets Vector of summary encodings that need patching.
+ /// \param EntityResolutionTable Map from TU EntityIds to LU EntityIds.
+ /// \returns Error if patching any encoding fails, success otherwise.
+ llvm::Error patch(const std::vector<EntitySummaryEncoding *> &PatchTargets,
+ const std::map<EntityId, EntityId> &EntityResolutionTable);
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYLINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h
new file mode 100644
index 0000000000000..9442ecbbe24cc
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h
@@ -0,0 +1,42 @@
+//===- EntitySummaryEncoding.h ----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the EntitySummaryEncoding class, which represents
+// EntitySummary data in an encoded, format-specific form.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "llvm/Support/Error.h"
+#include <map>
+
+namespace clang::ssaf {
+
+/// Represents EntitySummary data in its serialized, format-specific encoding.
+///
+/// This abstract base class allows the entity linker to manipulate serialized
+/// entity summary data without knowing the exact schema of the EntitySummary
+/// subclass. The primary operation is patching EntityId references when
+/// entities are merged during linking.
+class EntitySummaryEncoding {
+public:
+ virtual ~EntitySummaryEncoding() = default;
+
+ /// Updates EntityId references in the encoded data.
+ ///
+ /// \param EntityResolutionTable Mapping from old EntityIds to new EntityIds.
+ virtual llvm::Error
+ patch(const std::map<EntityId, EntityId> &EntityResolutionTable) = 0;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_ENTITYSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h
new file mode 100644
index 0000000000000..97142b0dd948a
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h
@@ -0,0 +1,62 @@
+//===- LUSummary.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LUSummary class, which represents a link unit summary
+// containing merged and deduplicated entity summaries from multiple TUs.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARY_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "llvm/TargetParser/Triple.h"
+#include <map>
+#include <memory>
+
+namespace clang::ssaf {
+
+/// Represents a link unit (LU) summary containing merged entity summaries.
+///
+/// LUSummary is the result of linking multiple translation unit summaries
+/// together. It contains deduplicated entities with their linkage information
+/// and the merged entity summaries.
+class LUSummary {
+ friend class AnalysisDriver;
+ friend class LUSummaryConsumer;
+ friend class SerializationFormat;
+ friend class TestFixture;
+
+ /// Target triple of the link unit.
+ llvm::Triple TargetTriple;
+
+ NestedBuildNamespace LUNamespace;
+
+ EntityIdTable IdTable;
+
+ std::map<EntityId, EntityLinkage> LinkageTable;
+
+ std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>
+ Data;
+
+public:
+ LUSummary(llvm::Triple TargetTriple, NestedBuildNamespace LUNamespace)
+ : TargetTriple(std::move(TargetTriple)),
+ LUNamespace(std::move(LUNamespace)) {}
+
+ const NestedBuildNamespace &getNamespace() const { return LUNamespace; }
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h
new file mode 100644
index 0000000000000..663697cdb88b3
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h
@@ -0,0 +1,64 @@
+//===- LUSummaryEncoding.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the LUSummaryEncoding class, which represents a link unit
+// summary in its serialized, format-specific encoding.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "llvm/TargetParser/Triple.h"
+#include <map>
+#include <memory>
+
+namespace clang::ssaf {
+
+/// Represents a link unit summary in its serialized encoding.
+///
+/// LUSummaryEncoding holds the combined entity summary data from multiple
+/// translation units in a format-specific encoding. It is produced by the
+/// entity linker and contains deduplicated and patched entity summaries.
+class LUSummaryEncoding {
+ friend class EntityLinker;
+ friend class SerializationFormat;
+ friend class TestFixture;
+
+ // Target triple of the link unit.
+ llvm::Triple TargetTriple;
+
+ // The namespace identifying this link unit.
+ NestedBuildNamespace LUNamespace;
+
+ // Maps entity names to their unique identifiers within this link unit.
+ EntityIdTable IdTable;
+
+ // Maps entity IDs to their linkage properties.
+ std::map<EntityId, EntityLinkage> LinkageTable;
+
+ // Encoded summary data organized by summary type and entity ID.
+ std::map<SummaryName,
+ std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
+ Data;
+
+public:
+ LUSummaryEncoding(llvm::Triple TargetTriple, NestedBuildNamespace LUNamespace)
+ : TargetTriple(std::move(TargetTriple)),
+ LUNamespace(std::move(LUNamespace)) {}
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_LUSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h
new file mode 100644
index 0000000000000..2c672a55e4873
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h
@@ -0,0 +1,67 @@
+//===- TUSummaryEncoding.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the TUSummaryEncoding class, which represents a
+// translation unit summary in its serialized, format-specific encoding.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "llvm/TargetParser/Triple.h"
+#include <map>
+#include <memory>
+
+namespace clang::ssaf {
+
+/// Represents a translation unit summary in its serialized encoding.
+///
+/// TUSummaryEncoding holds entity summary data in a format-specific encoding
+/// that can be manipulated by the entity linker without deserializing the
+/// full EntitySummary objects. This enables efficient entity ID patching
+/// during the linking process.
+class TUSummaryEncoding {
+ friend class EntityLinker;
+ friend class SerializationFormat;
+ friend class TestFixture;
+
+ // Target triple of the translation unit.
+ llvm::Triple TargetTriple;
+
+ // The namespace identifying this translation unit.
+ BuildNamespace TUNamespace;
+
+ // Maps entity names to their unique identifiers within this TU.
+ EntityIdTable IdTable;
+
+ // Maps entity IDs to their linkage properties (None, Internal, External).
+ std::map<EntityId, EntityLinkage> LinkageTable;
+
+ // Encoded summary data organized by summary type and entity ID.
+ std::map<SummaryName,
+ std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
+ Data;
+
+public:
+ TUSummaryEncoding(llvm::Triple TargetTriple, BuildNamespace TUNamespace)
+ : TargetTriple(std::move(TargetTriple)),
+ TUNamespace(std::move(TUNamespace)) {}
+
+ const llvm::Triple &getTargetTriple() const { return TargetTriple; }
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_ENTITYLINKER_TUSUMMARYENCODING_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h
new file mode 100644
index 0000000000000..6da5a9e42c4da
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h
@@ -0,0 +1,129 @@
+//===- BuildNamespace.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines BuildNamespace and NestedBuildNamespace classes that
+// represent build namespaces in the Scalable Static Analysis Framework.
+//
+// Build namespaces provide an abstraction for grouping program entities (such
+// as those in a shared library or compilation unit) to enable analysis of
+// software projects constructed from individual components.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_BUILDNAMESPACE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_BUILDNAMESPACE_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <optional>
+#include <string>
+#include <vector>
+
+namespace clang::ssaf {
+
+enum class BuildNamespaceKind : unsigned short { CompilationUnit, LinkUnit };
+
+/// Represents a single namespace in the build process.
+///
+/// A BuildNamespace groups program entities, such as those belonging to a
+/// compilation unit or link unit (e.g., a shared library). Each namespace has a
+/// kind (CompilationUnit or LinkUnit) and a unique identifier name within that
+/// kind.
+///
+/// BuildNamespaces can be composed into NestedBuildNamespace to represent
+/// hierarchical namespace structures that model how software is constructed
+/// from its components.
+class BuildNamespace {
+ BuildNamespaceKind Kind;
+ std::string Name;
+
+ auto asTuple() const { return std::tie(Kind, Name); }
+
+public:
+ BuildNamespace(BuildNamespaceKind Kind, llvm::StringRef Name)
+ : Kind(Kind), Name(Name.str()) {}
+
+ /// Creates a BuildNamespace representing a compilation unit.
+ ///
+ /// \param CompilationId The unique identifier for the compilation unit.
+ /// \returns A BuildNamespace with CompilationUnit kind.
+ static BuildNamespace makeCompilationUnit(llvm::StringRef CompilationId);
+
+ bool operator==(const BuildNamespace &Other) const;
+ bool operator!=(const BuildNamespace &Other) const;
+ bool operator<(const BuildNamespace &Other) const;
+
+ friend class EntityLinker;
+ friend class SerializationFormat;
+ friend class TestFixture;
+ friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const BuildNamespace &BN);
+};
+
+/// Represents a hierarchical sequence of build namespaces.
+///
+/// A NestedBuildNamespace captures namespace qualification for program entities
+/// by maintaining an ordered sequence of BuildNamespace steps. This models how
+/// entities are organized through multiple steps of the build process, such as
+/// first being part of a compilation unit, then incorporated into a link unit.
+///
+/// For example, an entity might be qualified by a compilation unit namespace
+/// followed by a shared library namespace.
+class NestedBuildNamespace {
+ std::vector<BuildNamespace> Namespaces;
+
+public:
+ NestedBuildNamespace() = default;
+
+ explicit NestedBuildNamespace(const std::vector<BuildNamespace> &Namespaces)
+ : Namespaces(Namespaces) {}
+
+ explicit NestedBuildNamespace(const BuildNamespace &N) {
+ Namespaces.push_back(N);
+ }
+
+ /// Creates a NestedBuildNamespace representing a compilation unit.
+ ///
+ /// \param CompilationId The unique identifier for the compilation unit.
+ /// \returns A NestedBuildNamespace containing a single CompilationUnit
+ /// BuildNamespace.
+ static NestedBuildNamespace
+ makeCompilationUnit(llvm::StringRef CompilationId);
+
+ /// Creates a new NestedBuildNamespace by appending additional namespace.
+ ///
+ /// \param Namespace The namespace to append.
+ NestedBuildNamespace makeQualified(NestedBuildNamespace Namespace) const {
+ auto Copy = *this;
+ Copy.Namespaces.reserve(Copy.Namespaces.size() +
+ Namespace.Namespaces.size());
+ llvm::append_range(Copy.Namespaces, Namespace.Namespaces);
+ return Copy;
+ }
+
+ bool empty() const;
+
+ bool operator==(const NestedBuildNamespace &Other) const;
+ bool operator!=(const NestedBuildNamespace &Other) const;
+ bool operator<(const NestedBuildNamespace &Other) const;
+
+ friend class SerializationFormat;
+ friend class TestFixture;
+ friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const NestedBuildNamespace &NBN);
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, BuildNamespaceKind BNK);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const BuildNamespace &BN);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const NestedBuildNamespace &NBN);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_BUILDNAMESPACE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityId.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityId.h
new file mode 100644
index 0000000000000..e8e36119927c8
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityId.h
@@ -0,0 +1,54 @@
+//===- EntityId.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the EntityId class, which provides a lightweight opaque
+// handle to entities in an EntityIdTable. EntityIds are index-based for
+// efficient comparison and lookup.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYID_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYID_H
+
+#include "llvm/Support/raw_ostream.h"
+#include <cstddef>
+
+namespace clang::ssaf {
+
+class EntityIdTable;
+
+/// Lightweight opaque handle representing an entity in an EntityIdTable.
+///
+/// EntityIds are created by EntityIdTable. Equality and ordering comparisons
+/// are well-defined for EntityIds created by the same EntityIdTable.
+///
+/// \see EntityIdTable
+class EntityId {
+ friend class EntityIdTable;
+ friend class SerializationFormat;
+ friend class TestFixture;
+ friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const EntityId &Id);
+
+ size_t Index;
+
+ explicit EntityId(size_t Index) : Index(Index) {}
+
+ EntityId() = delete;
+
+public:
+ bool operator==(const EntityId &Other) const { return Index == Other.Index; }
+ bool operator<(const EntityId &Other) const { return Index < Other.Index; }
+ bool operator!=(const EntityId &Other) const { return !(*this == Other); }
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityId &Id);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYID_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h
new file mode 100644
index 0000000000000..316a1f36369ec
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h
@@ -0,0 +1,53 @@
+//===- EntityIdTable.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYIDTABLE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYIDTABLE_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include <functional>
+#include <map>
+
+namespace clang::ssaf {
+
+/// Manages entity name interning and provides efficient EntityId handles.
+///
+/// The table maps each unique EntityName to exactly one EntityId.
+/// Entities are never removed.
+class EntityIdTable {
+ friend class SerializationFormat;
+ friend class TestFixture;
+
+ std::map<EntityName, EntityId> Entities;
+
+public:
+ EntityIdTable() = default;
+
+ /// Creates or retrieves an EntityId for the given EntityName.
+ ///
+ /// If the entity already exists in the table, returns its existing Id.
+ /// Otherwise, creates and returns a new Id. This operation is idempotent.
+ EntityId getId(const EntityName &Name);
+
+ /// Returns true if an entity with the given name exists in the table.
+ bool contains(const EntityName &Name) const;
+
+ /// Invokes the callback for each entity in the table.
+ ///
+ /// Iteration order is unspecified.
+ void forEach(
+ llvm::function_ref<void(const EntityName &, EntityId)> Callback) const;
+
+ /// Returns the number of unique entities in the table.
+ size_t count() const { return Entities.size(); }
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYIDTABLE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h
new file mode 100644
index 0000000000000..f90571c672452
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h
@@ -0,0 +1,53 @@
+//===- EntityLinkage.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYLINKAGE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYLINKAGE_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang::ssaf {
+
+enum class EntityLinkageType {
+ None, ///< local variables
+ Internal, ///< static functions/variables, anonymous namespace
+ External ///< globally visible across translation units (including parameters
+ ///< of functions with external linkage)
+};
+
+/// Represents the linkage properties of an entity in the program model.
+///
+/// EntityLinkage captures whether an entity has no linkage, internal linkage,
+/// or external linkage, which determines its visibility and accessibility
+/// across translation units.
+class EntityLinkage {
+ friend class SerializationFormat;
+ friend class TestFixture;
+
+public:
+ constexpr explicit EntityLinkage(EntityLinkageType L) : Linkage(L) {}
+
+ EntityLinkageType getLinkage() const { return Linkage; }
+
+ bool operator==(const EntityLinkage &Other) const;
+ bool operator!=(const EntityLinkage &Other) const;
+
+private:
+ EntityLinkageType Linkage;
+};
+
+/// Writes a string representation of the linkage type to the stream.
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, EntityLinkageType Linkage);
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const EntityLinkage &Linkage);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYLINKAGE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityName.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityName.h
new file mode 100644
index 0000000000000..ecc402e05d4b8
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/EntityName.h
@@ -0,0 +1,62 @@
+//===- EntityName.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYNAME_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYNAME_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace clang::ssaf {
+/// Uniquely identifies an entity in a program.
+///
+/// EntityName provides a globally unique identifier for program entities that
+/// remains stable across compilation boundaries. This enables whole-program
+/// analysis to track and relate entities across separately compiled translation
+/// units.
+///
+/// Client code should not make assumptions about the implementation details,
+/// such as USRs.
+class EntityName {
+ friend class EntityLinker;
+ friend class SerializationFormat;
+ friend class TestFixture;
+ friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const EntityName &EN);
+
+ std::string USR;
+ llvm::SmallString<16> Suffix;
+ NestedBuildNamespace Namespace;
+
+ auto asTuple() const { return std::tie(USR, Suffix, Namespace); }
+
+public:
+ /// Client code should not use this constructor directly.
+ /// Use getEntityName and other functions in ASTEntityMapping.h to get
+ /// entity names.
+ EntityName(llvm::StringRef USR, llvm::StringRef Suffix,
+ NestedBuildNamespace Namespace);
+
+ bool operator==(const EntityName &Other) const;
+ bool operator!=(const EntityName &Other) const;
+ bool operator<(const EntityName &Other) const;
+
+ /// Creates a new EntityName with additional build namespace qualification.
+ ///
+ /// \param Namespace The namespace steps to append to this entity's namespace.
+ EntityName makeQualified(NestedBuildNamespace Namespace) const;
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityName &EN);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_ENTITYNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def b/clang/include/clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def
new file mode 100644
index 0000000000000..44931026ba428
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def
@@ -0,0 +1,52 @@
+//===- PrivateFieldNames.def ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a list of non-static data members of the SSAF objects.
+// These are used for granting access for:
+// - SerializationFormat
+// - TestFixture
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef FIELD
+#define FIELD(CLASS, FIELD_NAME)
+#endif
+
+FIELD(BuildNamespace, Kind)
+FIELD(BuildNamespace, Name)
+FIELD(EntityId, Index)
+FIELD(EntityIdTable, Entities)
+FIELD(EntityLinkage, Linkage)
+FIELD(EntityName, Namespace)
+FIELD(EntityName, Suffix)
+FIELD(EntityName, USR)
+FIELD(LUSummary, TargetTriple)
+FIELD(LUSummary, Data)
+FIELD(LUSummary, IdTable)
+FIELD(LUSummary, LinkageTable)
+FIELD(LUSummary, LUNamespace)
+FIELD(LUSummaryEncoding, TargetTriple)
+FIELD(LUSummaryEncoding, Data)
+FIELD(LUSummaryEncoding, IdTable)
+FIELD(LUSummaryEncoding, LinkageTable)
+FIELD(LUSummaryEncoding, LUNamespace)
+FIELD(NestedBuildNamespace, Namespaces)
+FIELD(TUSummary, TargetTriple)
+FIELD(TUSummary, Data)
+FIELD(TUSummary, IdTable)
+FIELD(TUSummary, LinkageTable)
+FIELD(TUSummary, TUNamespace)
+FIELD(TUSummaryEncoding, TargetTriple)
+FIELD(TUSummaryEncoding, Data)
+FIELD(TUSummaryEncoding, IdTable)
+FIELD(TUSummaryEncoding, LinkageTable)
+FIELD(TUSummaryEncoding, TUNamespace)
+FIELD(WPASuite, Data)
+FIELD(WPASuite, IdTable)
+
+#undef FIELD
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Model/SummaryName.h b/clang/include/clang/ScalableStaticAnalysis/Core/Model/SummaryName.h
new file mode 100644
index 0000000000000..d299efc6fc638
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Model/SummaryName.h
@@ -0,0 +1,41 @@
+//===- SummaryName.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_SUMMARYNAME_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_SUMMARYNAME_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace clang::ssaf {
+
+/// Uniquely identifies an analysis summary.
+///
+/// This is the key to refer to an analysis or to name a builder to build an
+/// analysis.
+class SummaryName {
+public:
+ explicit SummaryName(std::string Name) : Name(std::move(Name)) {}
+
+ bool operator==(const SummaryName &Other) const { return Name == Other.Name; }
+ bool operator!=(const SummaryName &Other) const { return !(*this == Other); }
+ bool operator<(const SummaryName &Other) const { return Name < Other.Name; }
+
+ /// Explicit conversion to the underlying string representation.
+ llvm::StringRef str() const { return Name; }
+
+private:
+ std::string Name;
+ friend class TestFixture;
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SummaryName &SN);
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_MODEL_SUMMARYNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h
new file mode 100644
index 0000000000000..9d9b1ff0bbb51
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h
@@ -0,0 +1,268 @@
+//===- JSONFormat.h ---------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// JSON serialization format implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/Support/Compiler.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/Registry.h"
+
+#include <set>
+
+namespace clang::ssaf {
+
+class EntityIdTable;
+class EntitySummary;
+class SummaryName;
+
+class JSONFormat final : public SerializationFormat {
+ using Array = llvm::json::Array;
+ using Object = llvm::json::Object;
+ using Value = llvm::json::Value;
+
+ friend class JSONEntitySummaryEncoding;
+
+public:
+ llvm::Expected<TUSummary> readTUSummary(llvm::StringRef Path) override;
+
+ llvm::Error writeTUSummary(const TUSummary &Summary,
+ llvm::StringRef Path) override;
+
+ llvm::Expected<TUSummaryEncoding>
+ readTUSummaryEncoding(llvm::StringRef Path) override;
+
+ llvm::Error writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding,
+ llvm::StringRef Path) override;
+
+ llvm::Expected<LUSummary> readLUSummary(llvm::StringRef Path) override;
+
+ llvm::Error writeLUSummary(const LUSummary &Summary,
+ llvm::StringRef Path) override;
+
+ llvm::Expected<Artifact> readArtifact(llvm::StringRef Path) override;
+
+ llvm::Error writeArtifact(const Artifact &A, llvm::StringRef Path) override;
+
+ llvm::Expected<ArtifactEncoding>
+ readArtifactEncoding(llvm::StringRef Path) override;
+
+ llvm::Error writeArtifactEncoding(const ArtifactEncoding &E,
+ llvm::StringRef Path) override;
+
+ llvm::Expected<LUSummaryEncoding>
+ readLUSummaryEncoding(llvm::StringRef Path) override;
+
+ llvm::Error writeLUSummaryEncoding(const LUSummaryEncoding &SummaryEncoding,
+ llvm::StringRef Path) override;
+
+ llvm::Expected<WPASuite> readWPASuite(llvm::StringRef Path) override;
+
+ llvm::Error writeWPASuite(const WPASuite &Suite,
+ llvm::StringRef Path) override;
+
+ void forEachRegisteredAnalysis(
+ llvm::function_ref<void(llvm::StringRef Name, llvm::StringRef Desc)>
+ Callback) const override;
+
+ using EntityIdToJSONFn = llvm::function_ref<Object(EntityId)>;
+ using EntityIdFromJSONFn =
+ llvm::function_ref<llvm::Expected<EntityId>(const Object &)>;
+
+ using SerializerFn =
+ llvm::function_ref<Object(const EntitySummary &, EntityIdToJSONFn)>;
+ using DeserializerFn =
+ llvm::function_ref<llvm::Expected<std::unique_ptr<EntitySummary>>(
+ const Object &, EntityIdTable &, EntityIdFromJSONFn)>;
+
+ using FormatInfo = FormatInfoEntry<SerializerFn, DeserializerFn>;
+
+ using AnalysisResultSerializerFn =
+ llvm::function_ref<Object(const AnalysisResult &, EntityIdToJSONFn)>;
+ using AnalysisResultDeserializerFn =
+ llvm::function_ref<llvm::Expected<std::unique_ptr<AnalysisResult>>(
+ const Object &, EntityIdFromJSONFn)>;
+
+ using AnalysisResultRegistry =
+ SerializationFormat::AnalysisResultRegistryGenerator<
+ JSONFormat, AnalysisResultSerializerFn, AnalysisResultDeserializerFn>;
+
+private:
+ static std::map<SummaryName, FormatInfo> initFormatInfos();
+ const std::map<SummaryName, FormatInfo> FormatInfos = initFormatInfos();
+
+ /// Parses a TUSummary from an already-validated root JSON object. The
+ /// caller is responsible for verifying the self-describing type field
+ /// and for wrapping any returned error with file-path context.
+ llvm::Expected<TUSummary> readTUSummaryFromObject(const Object &Root);
+
+ /// Parses an LUSummary from an already-validated root JSON object. See
+ /// \c readTUSummaryFromObject for caller responsibilities.
+ llvm::Expected<LUSummary> readLUSummaryFromObject(const Object &Root);
+
+ /// Parses a TUSummaryEncoding from an already-validated root JSON
+ /// object. See \c readTUSummaryFromObject for caller responsibilities.
+ llvm::Expected<TUSummaryEncoding>
+ readTUSummaryEncodingFromObject(const Object &Root);
+
+ /// Parses an LUSummaryEncoding from an already-validated root JSON
+ /// object. See \c readTUSummaryFromObject for caller responsibilities.
+ llvm::Expected<LUSummaryEncoding>
+ readLUSummaryEncodingFromObject(const Object &Root);
+
+ /// Parses a WPASuite from an already-validated root JSON object. See
+ /// \c readTUSummaryFromObject for caller responsibilities.
+ llvm::Expected<WPASuite> readWPASuiteFromObject(const Object &Root);
+
+ EntityId entityIdFromJSON(const uint64_t EntityIdIndex) const;
+ uint64_t entityIdToJSON(EntityId EI) const;
+
+ static llvm::Expected<EntityId>
+ entityIdFromJSONObject(const Object &EntityIdObject);
+ static Object entityIdToJSONObject(EntityId EI);
+
+ llvm::Expected<BuildNamespace>
+ buildNamespaceFromJSON(const Object &BuildNamespaceObject) const;
+ Object buildNamespaceToJSON(const BuildNamespace &BN) const;
+
+ llvm::Expected<NestedBuildNamespace>
+ nestedBuildNamespaceFromJSON(const Array &NestedBuildNamespaceArray) const;
+ Array nestedBuildNamespaceToJSON(const NestedBuildNamespace &NBN) const;
+
+ llvm::Expected<EntityName>
+ tuEntityNameFromJSON(const Object &EntityNameObject) const;
+ Object tuEntityNameToJSON(const EntityName &EN) const;
+
+ llvm::Expected<EntityName>
+ luEntityNameFromJSON(const Object &EntityNameObject) const;
+ Object luEntityNameToJSON(const EntityName &EN) const;
+
+ llvm::Expected<EntityLinkage>
+ entityLinkageFromJSON(const Object &EntityLinkageObject) const;
+ Object entityLinkageToJSON(const EntityLinkage &EL) const;
+
+ llvm::Expected<std::pair<EntityName, EntityId>>
+ tuEntityIdTableEntryFromJSON(const Object &EntityIdTableEntryObject) const;
+ llvm::Expected<EntityIdTable>
+ tuEntityIdTableFromJSON(const Array &EntityIdTableArray) const;
+ Object tuEntityIdTableEntryToJSON(const EntityName &EN, EntityId EI) const;
+ Array tuEntityIdTableToJSON(const EntityIdTable &IdTable) const;
+
+ llvm::Expected<std::pair<EntityName, EntityId>>
+ luEntityIdTableEntryFromJSON(const Object &EntityIdTableEntryObject) const;
+ llvm::Expected<EntityIdTable>
+ luEntityIdTableFromJSON(const Array &EntityIdTableArray) const;
+ Object luEntityIdTableEntryToJSON(const EntityName &EN, EntityId EI) const;
+ Array luEntityIdTableToJSON(const EntityIdTable &IdTable) const;
+
+ llvm::Expected<std::pair<EntityId, EntityLinkage>>
+ linkageTableEntryFromJSON(const Object &LinkageTableEntryObject) const;
+ Object linkageTableEntryToJSON(EntityId EI, const EntityLinkage &EL) const;
+
+ llvm::Expected<std::map<EntityId, EntityLinkage>>
+ linkageTableFromJSON(const Array &LinkageTableArray,
+ std::set<EntityId> ExpectedIds) const;
+ Array linkageTableToJSON(
+ const std::map<EntityId, EntityLinkage> &LinkageTable) const;
+
+ llvm::Expected<std::unique_ptr<EntitySummary>>
+ entitySummaryFromJSON(const SummaryName &SN,
+ const Object &EntitySummaryObject,
+ EntityIdTable &IdTable) const;
+ llvm::Expected<Object> entitySummaryToJSON(const SummaryName &SN,
+ const EntitySummary &ES) const;
+
+ llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummary>>>
+ entityDataMapEntryFromJSON(const Object &EntityDataMapEntryObject,
+ const SummaryName &SN,
+ EntityIdTable &IdTable) const;
+ llvm::Expected<Object>
+ entityDataMapEntryToJSON(const EntityId EI,
+ const std::unique_ptr<EntitySummary> &EntitySummary,
+ const SummaryName &SN) const;
+ llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummary>>>
+ entityDataMapFromJSON(const SummaryName &SN, const Array &EntityDataArray,
+ EntityIdTable &IdTable) const;
+ llvm::Expected<Array>
+ entityDataMapToJSON(const SummaryName &SN,
+ const std::map<EntityId, std::unique_ptr<EntitySummary>>
+ &EntityDataMap) const;
+
+ llvm::Expected<std::pair<SummaryName,
+ std::map<EntityId, std::unique_ptr<EntitySummary>>>>
+ summaryDataMapEntryFromJSON(const Object &SummaryDataObject,
+ EntityIdTable &IdTable) const;
+ llvm::Expected<Object> summaryDataMapEntryToJSON(
+ const SummaryName &SN,
+ const std::map<EntityId, std::unique_ptr<EntitySummary>> &SD) const;
+
+ llvm::Expected<
+ std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>>
+ summaryDataMapFromJSON(const Array &SummaryDataArray,
+ EntityIdTable &IdTable) const;
+ llvm::Expected<Array> summaryDataMapToJSON(
+ const std::map<SummaryName,
+ std::map<EntityId, std::unique_ptr<EntitySummary>>>
+ &SummaryDataMap) const;
+
+ llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
+ encodingDataMapEntryFromJSON(const Object &EntityDataMapEntryObject) const;
+ Object encodingDataMapEntryToJSON(
+ EntityId EI,
+ const std::unique_ptr<EntitySummaryEncoding> &Encoding) const;
+
+ llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
+ encodingDataMapFromJSON(const Array &EntityDataArray) const;
+ Array encodingDataMapToJSON(
+ const std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>
+ &EncodingDataMap) const;
+
+ llvm::Expected<std::pair<
+ SummaryName, std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>>
+ encodingSummaryDataMapEntryFromJSON(
+ const Object &SummaryDataMapEntryObject) const;
+ Object encodingSummaryDataMapEntryToJSON(
+ const SummaryName &SN,
+ const std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>
+ &EncodingMap) const;
+
+ llvm::Expected<std::map<
+ SummaryName, std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>>
+ encodingSummaryDataMapFromJSON(const Array &SummaryDataArray) const;
+ Array encodingSummaryDataMapToJSON(
+ const std::map<SummaryName,
+ std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
+ &EncodingSummaryDataMap) const;
+
+ llvm::Expected<std::pair<AnalysisName, std::unique_ptr<AnalysisResult>>>
+ analysisResultMapEntryFromJSON(const Object &Entry) const;
+ llvm::Expected<Object> analysisResultMapEntryToJSON(
+ const AnalysisName &Name,
+ const std::unique_ptr<AnalysisResult> &Result) const;
+
+ llvm::Expected<std::map<AnalysisName, std::unique_ptr<AnalysisResult>>>
+ analysisResultMapFromJSON(const Array &ResultsArray) const;
+ llvm::Expected<Array> analysisResultMapToJSON(
+ const std::map<AnalysisName, std::unique_ptr<AnalysisResult>> &Data)
+ const;
+};
+
+} // namespace clang::ssaf
+
+LLVM_DECLARE_REGISTRY(llvm::Registry<clang::ssaf::JSONFormat::FormatInfo>)
+LLVM_DECLARE_REGISTRY(
+ llvm::Registry<clang::ssaf::JSONFormat::AnalysisResultRegistry::Codec>)
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_JSONFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h
new file mode 100644
index 0000000000000..ca3ee9ce3362c
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h
@@ -0,0 +1,266 @@
+//===- SerializationFormat.h ------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Abstract SerializationFormat interface for reading and writing
+// TUSummary and LinkUnitResolution data.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Registry.h"
+
+#include <variant>
+
+namespace clang::ssaf {
+
+/// Sum type returned by \c SerializationFormat::readArtifact, used when the
+/// caller does not know up-front which kind of top-level SSAF artifact a
+/// file contains. The active alternative is decided by the file's
+/// self-describing type field.
+using Artifact = std::variant<TUSummary, LUSummary, WPASuite>;
+
+/// Lazily-deserialized counterpart of \c Artifact: the same on-disk
+/// artifacts but with their per-entity summary payloads left as opaque
+/// format-specific encodings rather than fully resolved analysis results.
+using ArtifactEncoding = std::variant<TUSummaryEncoding, LUSummaryEncoding>;
+
+/// Abstract base class for serialization formats.
+class SerializationFormat {
+public:
+ virtual ~SerializationFormat() = default;
+
+ virtual llvm::Expected<TUSummary> readTUSummary(llvm::StringRef Path) = 0;
+
+ virtual llvm::Error writeTUSummary(const TUSummary &Summary,
+ llvm::StringRef Path) = 0;
+
+ virtual llvm::Expected<TUSummaryEncoding>
+ readTUSummaryEncoding(llvm::StringRef Path) = 0;
+
+ virtual llvm::Error
+ writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding,
+ llvm::StringRef Path) = 0;
+
+ virtual llvm::Expected<LUSummary> readLUSummary(llvm::StringRef Path) = 0;
+
+ virtual llvm::Error writeLUSummary(const LUSummary &Summary,
+ llvm::StringRef Path) = 0;
+
+ /// Generic read entry point. Inspects the file's self-describing type
+ /// field and dispatches to \c readTUSummary or \c readLUSummary
+ /// accordingly. Returns an error if the type field is missing or names
+ /// an unrecognized artifact kind.
+ virtual llvm::Expected<Artifact> readArtifact(llvm::StringRef Path) = 0;
+
+ /// Generic write entry point. Dispatches to \c writeTUSummary or
+ /// \c writeLUSummary based on the active variant alternative.
+ virtual llvm::Error writeArtifact(const Artifact &A,
+ llvm::StringRef Path) = 0;
+
+ /// Encoding-flavored counterpart of \c readArtifact. Inspects the
+ /// self-describing type field and dispatches to
+ /// \c readTUSummaryEncoding or \c readLUSummaryEncoding accordingly.
+ virtual llvm::Expected<ArtifactEncoding>
+ readArtifactEncoding(llvm::StringRef Path) = 0;
+
+ /// Encoding-flavored counterpart of \c writeArtifact. Dispatches to
+ /// \c writeTUSummaryEncoding or \c writeLUSummaryEncoding based on the
+ /// active variant alternative.
+ virtual llvm::Error writeArtifactEncoding(const ArtifactEncoding &E,
+ llvm::StringRef Path) = 0;
+
+ virtual llvm::Expected<LUSummaryEncoding>
+ readLUSummaryEncoding(llvm::StringRef Path) = 0;
+
+ virtual llvm::Error
+ writeLUSummaryEncoding(const LUSummaryEncoding &SummaryEncoding,
+ llvm::StringRef Path) = 0;
+
+ virtual llvm::Expected<WPASuite> readWPASuite(llvm::StringRef Path) = 0;
+
+ virtual llvm::Error writeWPASuite(const WPASuite &Suite,
+ llvm::StringRef Path) = 0;
+
+ /// Invokes \p Callback once for each analysis that has registered
+ /// serialization support for this format.
+ virtual void forEachRegisteredAnalysis(
+ llvm::function_ref<void(llvm::StringRef Name, llvm::StringRef Desc)>
+ Callback) const = 0;
+
+protected:
+ // Helpers providing access to implementation details of basic data structures
+ // for efficient serialization/deserialization.
+
+ static EntityId makeEntityId(const size_t Index) { return EntityId(Index); }
+
+ /// Constructs an empty WPASuite. Bypasses the private default constructor
+ /// so that deserialization code can build a WPASuite incrementally.
+ static WPASuite makeWPASuite() { return WPASuite(); }
+
+#define FIELD(CLASS, FIELD_NAME) \
+ static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
+ static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
+#include "clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def"
+
+ /// Per-format plugin registry for analysis result (de)serializers.
+ ///
+ /// Each concrete format (e.g. JSONFormat) instantiates this template once
+ /// via a public \c using alias. Analysis authors register support with:
+ ///
+ /// \code
+ /// static MyFormat::AnalysisResultRegistry::Add<MyAnalysisResult>
+ /// Reg(serializeFn, deserializeFn);
+ /// \endcode
+ ///
+ /// The serializer receives a \c const reference to \c MyAnalysisResult
+ /// directly and the \c Add wrapper handles the downcast from \c
+ /// AnalysisResult internally via virtual dispatch.
+ ///
+ /// \tparam FormatT Phantom type is needed to disambiguate \c llvm::Registry
+ /// instantiations. \c llvm::Registry is keyed on the \c Entry type,
+ /// so two formats sharing the same serializer/deserializer signatures
+ /// would collide on the same registry without this parameter.
+ template <class FormatT, class SerializerFn, class DeserializerFn>
+ class AnalysisResultRegistryGenerator;
+
+ template <class FormatT, class SerRet, class... SerArgs, class DesRet,
+ class... DesArgs>
+ class AnalysisResultRegistryGenerator<
+ FormatT, llvm::function_ref<SerRet(const AnalysisResult &, SerArgs...)>,
+ llvm::function_ref<DesRet(DesArgs...)>> {
+
+ using DeserializerFn = DesRet (*)(DesArgs...);
+
+ public:
+ /// Abstract base type stored in \c llvm::Registry<Codec>.
+ /// Subclasses override \c serialize() and \c deserialize() to
+ /// dispatch to the plugin's concrete functions.
+ ///
+ /// There is one \c Codec type (and one \c llvm::Registry<Codec>) per
+ /// format. All analysis-specific concrete subclasses for a given format
+ /// register into that single registry. The \c FormatT phantom type
+ /// parameter on the enclosing class ensures that different formats
+ /// produce distinct \c Codec types and thus separate registries.
+ struct Codec {
+ virtual ~Codec() = default;
+ virtual SerRet serialize(const AnalysisResult &, SerArgs...) const = 0;
+ virtual DesRet deserialize(DesArgs...) const = 0;
+ };
+
+ template <class AnalysisResultT> struct Add {
+ using TypedSerializerFn = SerRet (*)(const AnalysisResultT &, SerArgs...);
+
+ static inline TypedSerializerFn SavedSerialize;
+ static inline DeserializerFn SavedDeserialize;
+
+ /// Takes the plugin's typed serializer and the deserializer, and
+ /// inserts them into \c llvm::Registry<Codec>.
+ Add(TypedSerializerFn TypedSerialize, DeserializerFn Deserialize) {
+ /// Per-\c AnalysisResultT guard: each template instantiation gets
+ /// its own \c static \c bool, so double-registration of the same
+ /// analysis is caught even across translation units.
+ static bool Registered = false;
+ if (Registered) {
+ ErrorBuilder::fatal("support is already registered for analysis: {0}",
+ AnalysisResultT::analysisName());
+ }
+ Registered = true;
+
+ /// The plugin's serializer and deserializer are captured in
+ /// static inline members of the Add template so that the
+ /// \c ConcreteCodec default constructor (required by \c llvm::Registry)
+ /// can read them. They use raw function pointers to prevent dangling
+ /// references to temporary stack variables during registration.
+ ///
+ /// Once read by the constructor, they are stored as instance members
+ /// of \c ConcreteCodec rather than directly executed from the \c static
+ /// \c inline class members. This prevents symbol visibility issues
+ /// across shared library boundaries on Linux (where \c dlopen with \c
+ /// RTLD_LOCAL can give the host and plugin separate copies of \c static
+ /// \c inline members).
+ SavedSerialize = TypedSerialize;
+ SavedDeserialize = Deserialize;
+
+ /// Concrete subclass of \c Codec for \c AnalysisResultT.
+ /// The \c serialize() override performs the downcast from
+ /// \c AnalysisResult to \c AnalysisResultT.
+ struct ConcreteCodec final : Codec {
+ TypedSerializerFn SerFn;
+ DeserializerFn DesFn;
+
+ ConcreteCodec() : SerFn(SavedSerialize), DesFn(SavedDeserialize) {}
+
+ SerRet serialize(const AnalysisResult &Base,
+ SerArgs... args) const override {
+ return SerFn(static_cast<const AnalysisResultT &>(Base), args...);
+ }
+
+ DesRet deserialize(DesArgs... args) const override {
+ return DesFn(args...);
+ }
+ };
+
+ /// \c llvm::Registry stores the name as a \c StringRef, so the
+ /// underlying string must be kept alive with a static declaration.
+ static std::string NameStr =
+ AnalysisResultT::analysisName().str().str();
+
+ /// This performs the actual registration. It appends a factory for \c
+ /// ConcreteCodec to the global \c llvm::Registry<Codec>. \c static
+ /// ensures the `Registry::Add` object lives for the entire program,
+ /// keeping its codec and node alive in the registry's linked list.
+ [[maybe_unused]] static
+ typename llvm::Registry<Codec>::template Add<ConcreteCodec>
+ RegisterUsingCtorSideEffect(NameStr, "");
+ }
+ };
+
+ /// Looks up the codec for \p Name by walking the registry list.
+ static llvm::Expected<std::unique_ptr<Codec>>
+ instantiate(const AnalysisName &Name) {
+ for (const auto &E : llvm::Registry<Codec>::entries()) {
+ if (E.getName() == Name.str()) {
+ return E.instantiate();
+ }
+ }
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ "no support registered for analysis: {0}",
+ Name)
+ .build();
+ }
+ };
+};
+
+template <class SerializerFn, class DeserializerFn> struct FormatInfoEntry {
+ FormatInfoEntry(SummaryName ForSummary, SerializerFn Serialize,
+ DeserializerFn Deserialize)
+ : ForSummary(ForSummary), Serialize(Serialize), Deserialize(Deserialize) {
+ }
+ virtual ~FormatInfoEntry() = default;
+
+ SummaryName ForSummary;
+ SerializerFn Serialize;
+ DeserializerFn Deserialize;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMAT_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h
new file mode 100644
index 0000000000000..bcb926903d664
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h
@@ -0,0 +1,89 @@
+//===- SerializationFormatRegistry.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Registry for SerializationFormats, and some helper functions.
+//
+// To register some custom serialization format, you will need to add some
+// declarations and definitions.
+//
+// Insert this code to the header file:
+//
+// LLVM_DECLARE_REGISTRY(llvm::Registry<MyFormat::FormatInfo>)
+//
+// Insert this declaration to the MyFormat class:
+//
+// using FormatInfo = FormatInfoEntry<SerializerFn, DeserializerFn>;
+//
+// Insert this code to the cpp file:
+//
+// namespace clang::ssaf {
+// // NOLINTNEXTLINE(misc-use-internal-linkage)
+// volatile int MyFormatAnchorSource = 0;
+// } // namespace clang::ssaf
+// static SerializationFormatRegistry::Add<MyFormat>
+// RegisterFormat("MyFormat", "My awesome serialization format");
+// LLVM_DEFINE_REGISTRY(llvm::Registry<MyFormat::FormatInfo>)
+//
+// Then implement the formatter for the specific analysis and register the
+// format info for it:
+//
+// namespace {
+// using FormatInfo = MyFormat::FormatInfo;
+// struct MyAnalysisFormatInfo final : FormatInfo {
+// MyAnalysisFormatInfo() : FormatInfo{
+// SummaryName("MyAnalysis"),
+// serializeMyAnalysis,
+// deserializeMyAnalysis,
+// } {}
+// };
+// } // namespace
+//
+// static llvm::Registry<FormatInfo>::Add<MyAnalysisFormatInfo>
+// RegisterFormatInfo(
+// "MyAnalysisFormatInfo",
+// "The MyFormat format info implementation for MyAnalysis"
+// );
+//
+// Finally, extend the `AnchorSources` list in the force-linker header:
+// clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h:
+//
+// This anchor is used to force the linker to link the MyFormat registration.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
+
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/Support/Compiler.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Registry.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang::ssaf {
+
+/// Check if a SerializationFormat was registered with a given name.
+bool isFormatRegistered(llvm::StringRef FormatName);
+
+/// Try to instantiate a SerializationFormat with a given name.
+/// This might return null if the construction of the desired
+/// SerializationFormat failed.
+/// It's a fatal error if there is no format registered with the name.
+std::unique_ptr<SerializationFormat> makeFormat(llvm::StringRef FormatName);
+
+/// Print the list of available serialization formats.
+void printAvailableFormats(llvm::raw_ostream &OS);
+
+// Registry for adding new SerializationFormat implementations.
+using SerializationFormatRegistry = llvm::Registry<SerializationFormat>;
+
+} // namespace clang::ssaf
+
+LLVM_DECLARE_REGISTRY(clang::ssaf::SerializationFormatRegistry)
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SERIALIZATION_SERIALIZATIONFORMATREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h
new file mode 100644
index 0000000000000..c0f0308533a46
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h
@@ -0,0 +1,93 @@
+//===- LUSummaryConsumer.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// LUSummaryConsumer constructs SummaryData objects by routing LUSummary entity
+// data to the corresponding SummaryDataBuilder objects.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Error.h"
+#include <memory>
+#include <utility>
+
+namespace clang::ssaf {
+
+/// Consumes a LUSummary by dispatching its entity data to registered
+/// SummaryDataBuilders and returning the results in a SummaryDataStore.
+///
+/// Three consumption patterns are supported:
+/// - \c run() && — processes every analysis present in the
+/// LUSummary, silently skipping any whose data is
+/// absent or whose builder is not registered.
+/// Cannot fail, so it returns \c SummaryDataStore
+/// directly. Requires an rvalue consumer because
+/// this pattern exhausts all remaining data.
+/// - \c run(names) — processes a named subset; returns
+/// \c llvm::Expected<SummaryDataStore> and fails if
+/// any requested name has no data in the LUSummary
+/// or no registered builder.
+/// - \c run<DataTs...>() — type-safe variant of \c run(names) with the
+/// same error semantics and return type.
+///
+/// All patterns consume the underlying LUSummary data, so each analysis can
+/// only be retrieved once across all run() calls.
+class LUSummaryConsumer final {
+public:
+ explicit LUSummaryConsumer(std::unique_ptr<LUSummary> LU)
+ : LU(std::move(LU)) {}
+
+ /// Processes all registered analyses in LUSummary and returns the results.
+ /// Silently skips analyses with no data or no registered builder.
+ ///
+ /// Requires an rvalue consumer (call as \c std::move(Consumer).run()) because
+ /// this pattern exhausts all remaining LUSummary data.
+ [[nodiscard]] SummaryDataStore run() &&;
+
+ /// Processes the named analyses and returns the results.
+ ///
+ /// Returns an error if any name has no data in the LUSummary or no
+ /// registered builder.
+ [[nodiscard]] llvm::Expected<SummaryDataStore>
+ run(llvm::ArrayRef<SummaryName> Names);
+
+ /// Processes analyses for each of the given types and returns the results.
+ ///
+ /// Returns an error if any type has no data in the LUSummary or no
+ /// registered builder.
+ template <typename... DataTs>
+ [[nodiscard]] llvm::Expected<SummaryDataStore> run() {
+ return run({DataTs::summaryName()...});
+ }
+
+private:
+ std::unique_ptr<LUSummary> LU;
+
+ /// Iterator into LUSummary::Data — the map from SummaryName to entity data.
+ using LUDataIterator = decltype(std::declval<LUSummary &>().Data)::iterator;
+
+ /// Core build implementation. Instantiates the registered builder for the
+ /// analysis at \p It, delivers all entities, finalizes, and returns the
+ /// built data. Returns an error if no builder is registered. Erases the
+ /// LUSummary entry on success.
+ llvm::Expected<std::unique_ptr<SummaryData>> build(LUDataIterator It);
+
+ /// Looks up \p SN in the LUSummary and delegates to the iterator overload.
+ /// Returns an error if no data for \p SN exists or no builder is registered.
+ llvm::Expected<std::unique_ptr<SummaryData>> build(const SummaryName &SN);
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_LUSUMMARYCONSUMER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h
new file mode 100644
index 0000000000000..8c7f98622cc25
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h
@@ -0,0 +1,28 @@
+//===- SummaryData.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Base class for all whole-program analysis data built from
+// LUSummary data. Carries no query API — all analysis-specific methods live
+// on concrete subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATA_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATA_H
+
+namespace clang::ssaf {
+
+/// Base class for whole-program analysis data.
+class SummaryData {
+public:
+ virtual ~SummaryData() = default;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATA_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h
new file mode 100644
index 0000000000000..071741e23b56c
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h
@@ -0,0 +1,97 @@
+//===- SummaryDataBuilder.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines SummaryDataBuilderBase (abstract base known to the
+// registry and LUSummaryConsumer) and the typed intermediate template
+// SummaryDataBuilder<DataT, SummaryT> that concrete builders inherit from.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include <memory>
+
+namespace clang::ssaf {
+
+class LUSummaryConsumer;
+
+/// Abstract base class for all summary data builders.
+///
+/// Known to the registry and LUSummaryConsumer. Receives entities one at a
+/// time via \c addSummary(), is finalized via \c finalize(), and transfers
+/// ownership of the built data via \c takeData().
+class SummaryDataBuilderBase {
+ friend class LUSummaryConsumer;
+
+public:
+ virtual ~SummaryDataBuilderBase() = default;
+
+private:
+ /// Called once per entity belonging to this builder's analysis.
+ /// Takes ownership of the summary data.
+ virtual void addSummary(EntityId Id,
+ std::unique_ptr<EntitySummary> Summary) = 0;
+
+ /// Called after all entities have been added.
+ virtual void finalize() {}
+
+ /// Transfers ownership of the built data. Called by LUSummaryConsumer after
+ /// finalize(). The rvalue ref-qualifier enforces single use — the builder
+ /// cannot be accessed after this call.
+ virtual std::unique_ptr<SummaryData> takeData() && = 0;
+};
+
+/// Typed intermediate template that concrete builders inherit from.
+/// Concrete builders must implement the typed
+/// \c addSummary(EntityId, unique_ptr<SummaryT>) overload, and may override
+/// \c finalize() for any post-processing needed after all entities are added.
+template <typename DataT, typename SummaryT>
+class SummaryDataBuilder : public SummaryDataBuilderBase {
+ static_assert(std::is_base_of_v<SummaryData, DataT>,
+ "DataT must derive from SummaryData");
+ static_assert(HasSummaryName_v<DataT>,
+ "DataT must have a static summaryName() method");
+ static_assert(std::is_base_of_v<EntitySummary, SummaryT>,
+ "SummaryT must derive from EntitySummary");
+
+ std::unique_ptr<DataT> Data;
+
+public:
+ SummaryDataBuilder() : Data(std::make_unique<DataT>()) {}
+
+ /// Returns the SummaryName of the data this builder produces.
+ /// Used by SummaryDataBuilderRegistry::Add to derive the registry entry name.
+ static SummaryName summaryName() { return DataT::summaryName(); }
+
+protected:
+ /// Typed customization point — concrete builders override this.
+ virtual void addSummary(EntityId Id, std::unique_ptr<SummaryT> Summary) = 0;
+
+ DataT &getData() & { return *Data; }
+
+private:
+ std::unique_ptr<SummaryData> takeData() && override {
+ return std::move(Data);
+ }
+
+ /// Seals the base overload, downcasts, and dispatches to the typed overload.
+ void addSummary(EntityId Id, std::unique_ptr<EntitySummary> Summary) final {
+ addSummary(Id, std::unique_ptr<SummaryT>(
+ static_cast<SummaryT *>(Summary.release())));
+ }
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h
new file mode 100644
index 0000000000000..f869985779b1a
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h
@@ -0,0 +1,74 @@
+//===- SummaryDataBuilderRegistry.h -----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Registry for SummaryDataBuilders.
+//
+// To register a builder, add a static Add<BuilderT> in the builder's
+// translation unit:
+//
+// static SummaryDataBuilderRegistry::Add<MyDataBuilder>
+// Registered("Data builder for MyAnalysis");
+//
+// The registry entry name is derived automatically from
+// MyDataBuilder::summaryName(), which returns MyData::summaryName().
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
+
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilder.h"
+#include "llvm/Support/Registry.h"
+#include <memory>
+#include <string>
+
+LLVM_DECLARE_REGISTRY(llvm::Registry<clang::ssaf::SummaryDataBuilderBase>)
+
+namespace clang::ssaf {
+
+/// Registry for SummaryDataBuilder implementations.
+///
+/// Provides an Add helper that derives the registry entry name from
+/// BuilderT::summaryName(), eliminating the possibility of registering a
+/// builder under the wrong name.
+class SummaryDataBuilderRegistry {
+ using RegistryT = llvm::Registry<SummaryDataBuilderBase>;
+
+ SummaryDataBuilderRegistry() = delete;
+
+public:
+ /// Registers \p BuilderT under the name returned by
+ /// \c BuilderT::summaryName(). Only a description is required.
+ ///
+ /// \c Add objects must be declared \c static at namespace scope — they
+ /// register an entry in a global linked list on construction and are
+ /// not copyable or movable.
+ template <typename BuilderT> struct Add {
+ explicit Add(llvm::StringRef Desc)
+ : Name(BuilderT::summaryName().str().str()), Node(Name, Desc) {}
+
+ Add(const Add &) = delete;
+ Add &operator=(const Add &) = delete;
+
+ private:
+ std::string Name;
+ RegistryT::Add<BuilderT> Node;
+ };
+
+ /// Returns true if a builder is registered under \p Name.
+ static bool contains(llvm::StringRef Name);
+
+ /// Instantiates the builder registered under \p Name, or returns nullptr
+ /// if no such builder is registered.
+ static std::unique_ptr<SummaryDataBuilderBase>
+ instantiate(llvm::StringRef Name);
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATABUILDERREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h
new file mode 100644
index 0000000000000..b0e71a4f1031f
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataStore.h
@@ -0,0 +1,115 @@
+//===- SummaryDataStore.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Owns a collection of SummaryData objects keyed by SummaryName.
+// Produced by LUSummaryConsumer::run() variants.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryData.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "llvm/Support/Error.h"
+#include <map>
+#include <memory>
+
+namespace clang::ssaf {
+
+class LUSummaryConsumer;
+
+/// Owns a collection of SummaryData objects keyed by SummaryName.
+/// Produced by LUSummaryConsumer::run() variants.
+class SummaryDataStore {
+ friend class LUSummaryConsumer;
+
+ std::map<SummaryName, std::unique_ptr<SummaryData>> Data;
+
+public:
+ /// Returns true if data for \p Name is stored.
+ [[nodiscard]] bool contains(const SummaryName &Name) const {
+ return Data.find(Name) != Data.end();
+ }
+
+ /// Returns true if data for \p DataT is stored.
+ template <typename DataT> [[nodiscard]] bool contains() const {
+ static_assert(std::is_base_of_v<SummaryData, DataT>,
+ "DataT must derive from SummaryData");
+ static_assert(HasSummaryName_v<DataT>,
+ "DataT must have a static summaryName() method");
+
+ return contains(DataT::summaryName());
+ }
+
+ /// Returns a reference to the data for \p DataT, or an error if
+ /// no data for \p DataT is stored.
+ template <typename DataT> [[nodiscard]] llvm::Expected<DataT &> get() {
+ static_assert(std::is_base_of_v<SummaryData, DataT>,
+ "DataT must derive from SummaryData");
+ static_assert(HasSummaryName_v<DataT>,
+ "DataT must have a static summaryName() method");
+
+ auto Result = get(DataT::summaryName());
+ if (!Result) {
+ return Result.takeError();
+ }
+ return static_cast<DataT &>(*Result);
+ }
+
+ /// Returns a reference to the data for \p Name, or an error if
+ /// no data for \p Name is stored.
+ [[nodiscard]] llvm::Expected<SummaryData &> get(const SummaryName &Name) {
+ auto It = Data.find(Name);
+ if (It == Data.end()) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ "no data for analysis '{0}' in store",
+ Name.str())
+ .build();
+ }
+ return *It->second;
+ }
+
+ /// Transfers ownership of the data for \p DataT to the caller, or returns
+ /// an error if no data for \p DataT is stored.
+ template <typename DataT>
+ [[nodiscard]] llvm::Expected<std::unique_ptr<DataT>> take() {
+ static_assert(std::is_base_of_v<SummaryData, DataT>,
+ "DataT must derive from SummaryData");
+ static_assert(HasSummaryName_v<DataT>,
+ "DataT must have a static summaryName() method");
+
+ auto Result = take(DataT::summaryName());
+ if (!Result) {
+ return Result.takeError();
+ }
+ return std::unique_ptr<DataT>(static_cast<DataT *>(Result->release()));
+ }
+
+ /// Transfers ownership of the data for \p Name to the caller, or returns
+ /// an error if no data for \p Name is stored.
+ [[nodiscard]] llvm::Expected<std::unique_ptr<SummaryData>>
+ take(const SummaryName &Name) {
+ auto It = Data.find(Name);
+ if (It == Data.end()) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ "no data for analysis '{0}' in store",
+ Name.str())
+ .build();
+ }
+ auto Ptr = std::move(It->second);
+ Data.erase(It);
+ return std::move(Ptr);
+ }
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATASTORE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h
new file mode 100644
index 0000000000000..d08dd68935bac
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataTraits.h
@@ -0,0 +1,41 @@
+//===- SummaryDataTraits.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Type traits for SummaryData subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include <type_traits>
+
+namespace clang::ssaf {
+
+/// Type trait that checks whether \p T has a static \c summaryName() method
+/// returning \c SummaryName. Used to enforce the convention on SummaryData
+/// subclasses at instantiation time.
+///
+/// The expression \c T::summaryName() is only well-formed for static methods —
+/// calling a non-static member without an object is ill-formed and causes the
+/// partial specialization to be discarded via SFINAE, so non-static overloads
+/// are correctly rejected.
+template <typename T, typename = void>
+struct HasSummaryName : std::false_type {};
+
+template <typename T>
+struct HasSummaryName<T, std::void_t<decltype(T::summaryName())>>
+ : std::is_same<decltype(T::summaryName()), SummaryName> {};
+
+template <typename T>
+inline constexpr bool HasSummaryName_v = HasSummaryName<T>::value;
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUMMARYDATA_SUMMARYDATATRAITS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h b/clang/include/clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h
new file mode 100644
index 0000000000000..2ad4d8e06eb90
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h
@@ -0,0 +1,210 @@
+//===- ErrorBuilder.h - Fluent API for contextual errors --------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the ErrorBuilder class, which provides a fluent API for
+// constructing contextual error messages with layered context information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_ERRORBUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_ERRORBUILDER_H
+
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+#include <optional>
+#include <string>
+#include <system_error>
+#include <vector>
+
+namespace clang::ssaf {
+
+/// Fluent API for constructing contextual errors.
+///
+/// ErrorBuilder allows building error messages with layered context
+/// information. Context is added innermost to outermost, and the final
+/// error message presents the context in reverse order (outermost first).
+///
+/// Example usage:
+/// \code
+/// return ErrorBuilder::create(std::errc::invalid_argument,
+/// "invalid value {0}", value)
+/// .context("processing field '{0}'", fieldName)
+/// .context("reading configuration")
+/// .build();
+/// \endcode
+class ErrorBuilder {
+ std::error_code Code;
+ std::vector<std::string> ContextStack;
+
+ explicit ErrorBuilder(std::error_code EC) : Code(EC) {}
+
+ void pushContext(std::string Msg) {
+ if (!Msg.empty()) {
+ ContextStack.push_back(std::move(Msg));
+ }
+ }
+
+ template <typename... Args>
+ static std::string formatErrorMessage(const char *Fmt, Args &&...ArgVals) {
+ return llvm::formatv(Fmt, std::forward<Args>(ArgVals)...).str();
+ }
+
+ template <typename... Args>
+ void addFormattedContext(const char *Fmt, Args &&...ArgVals) {
+ pushContext(formatErrorMessage(Fmt, std::forward<Args>(ArgVals)...));
+ }
+
+public:
+ /// Create an ErrorBuilder with an error code and formatted message.
+ ///
+ /// \param EC The error code for this error.
+ /// \param Fmt Format string for the error message (using llvm::formatv).
+ /// \param ArgVals Arguments for the format string.
+ /// \returns A new ErrorBuilder with the initial error message.
+ ///
+ /// Example:
+ /// \code
+ /// return ErrorBuilder::create(std::errc::invalid_argument,
+ /// "invalid value: {0}", 42)
+ /// .build();
+ /// \endcode
+ template <typename... Args>
+ static ErrorBuilder create(std::error_code EC, const char *Fmt,
+ Args &&...ArgVals) {
+ ErrorBuilder Builder(EC);
+ Builder.addFormattedContext(Fmt, std::forward<Args>(ArgVals)...);
+ return Builder;
+ }
+
+ /// Convenience overload that accepts std::errc instead of std::error_code.
+ ///
+ /// \param EC The error condition for this error.
+ /// \param Fmt Format string for the error message.
+ /// \param ArgVals Arguments for the format string.
+ /// \returns A new ErrorBuilder with the initial error message.
+ template <typename... Args>
+ static ErrorBuilder create(std::errc EC, const char *Fmt, Args &&...ArgVals) {
+ return create(std::make_error_code(EC), Fmt,
+ std::forward<Args>(ArgVals)...);
+ }
+
+ /// Wrap an existing error and optionally add context.
+ ///
+ /// Extracts the error code and message(s) from the given error. If multiple
+ /// errors are joined (via llvm::joinErrors), their messages are combined
+ /// using " + " separator.
+ ///
+ /// \param E The error to wrap. Must be a failure (cannot be success).
+ /// \returns A new ErrorBuilder containing the wrapped error information.
+ ///
+ /// \pre E must evaluate to true (i.e., must be a failure). Wrapping
+ /// Error::success() is a programming error and will trigger an
+ /// assertion failure in debug builds.
+ ///
+ /// Example:
+ /// \code
+ /// if (auto Err = foo())
+ /// return ErrorBuilder::wrap(std::move(Err))
+ /// .context("while processing file")
+ /// .build();
+ /// \endcode
+ static ErrorBuilder wrap(llvm::Error E);
+
+ /// Add context information as a plain string.
+ ///
+ /// Empty strings are ignored and not added to the context stack.
+ ///
+ /// \param Msg Context message to add. Must be a null-terminated string.
+ /// \returns Reference to this ErrorBuilder for method chaining.
+ ///
+ /// Example:
+ /// \code
+ /// return ErrorBuilder::create(...)
+ /// .context("reading configuration file")
+ /// .build();
+ /// \endcode
+ ErrorBuilder &context(const char *Msg);
+
+ /// Add context information with formatted string.
+ ///
+ /// Uses llvm::formatv for formatting. Empty messages (after formatting)
+ /// are ignored and not added to the context stack.
+ ///
+ /// \param Fmt Format string (using llvm::formatv syntax).
+ /// \param ArgVals Arguments for the format string.
+ /// \returns Reference to this ErrorBuilder for method chaining.
+ ///
+ /// Example:
+ /// \code
+ /// return ErrorBuilder::create(...)
+ /// .context("processing field '{0}'", fieldName)
+ /// .context("at line {0}, column {1}", line, col)
+ /// .build();
+ /// \endcode
+ template <typename... Args>
+ ErrorBuilder &context(const char *Fmt, Args &&...ArgVals) {
+ addFormattedContext(Fmt, std::forward<Args>(ArgVals)...);
+ return *this;
+ }
+
+ /// Build and return the final error.
+ ///
+ /// Constructs an llvm::Error with all accumulated context. The context
+ /// is presented in reverse order: most recent context first, original
+ /// error message last. Each context layer is separated by a newline.
+ ///
+ /// \returns An llvm::Error containing the error code and formatted message.
+ /// Even if no context was added (empty context stack), an error
+ /// with the stored error code is returned.
+ ///
+ /// \pre The ErrorBuilder must have been created via \c create() or \c wrap().
+ /// Constructing an ErrorBuilder directly is not supported.
+ ///
+ /// Example output:
+ /// \code
+ /// ErrorBuilder::create(errc::invalid_argument, "value is 42")
+ /// .context("processing field 'age'")
+ /// .context("reading config")
+ /// .build();
+ ///
+ /// // Produces:
+ /// // "reading config
+ /// // processing field 'age'
+ /// // value is 42"
+ /// \endcode
+ llvm::Error build() const;
+
+ /// Report a fatal error with formatted message and terminate execution.
+ ///
+ /// Combines llvm::formatv and llvm::report_fatal_error. This is a static
+ /// utility method for reporting unrecoverable errors that indicate bugs
+ /// or corrupted data.
+ ///
+ /// \param Fmt Format string for the error message (using llvm::formatv).
+ /// \param ArgVals Arguments for the format string.
+ ///
+ /// \pre \p Fmt must be a valid llvm::formatv format string with the correct
+ /// number and types of arguments. An invalid format string is undefined
+ /// behaviour.
+ ///
+ /// Example:
+ /// \code
+ /// ErrorBuilder::fatal("Entity {0} with {1} linkage already exists",
+ /// entityId, linkageType);
+ /// \endcode
+ template <typename... Args>
+ [[noreturn]] static void fatal(const char *Fmt, Args &&...ArgVals) {
+ llvm::report_fatal_error(llvm::StringRef(formatErrorMessage(
+ Fmt, std::forward<Args>(ArgVals)...)),
+ false);
+ }
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_ERRORBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h b/clang/include/clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h
new file mode 100644
index 0000000000000..e4a7b54033924
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h
@@ -0,0 +1,93 @@
+//===- FormatProviders.h - llvm::formatv support for SSAF types -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file provides llvm::format_provider specialisations for SSAF model
+// types, enabling them to be used directly with llvm::formatv and ErrorBuilder.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_FORMATPROVIDERS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_FORMATPROVIDERS_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "llvm/Support/FormatProviders.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+template <> struct format_provider<clang::ssaf::EntityId> {
+ static void format(const clang::ssaf::EntityId &Val, raw_ostream &OS,
+ StringRef Style) {
+ OS << Val;
+ }
+};
+
+template <> struct format_provider<clang::ssaf::EntityLinkageType> {
+ static void format(clang::ssaf::EntityLinkageType Val, raw_ostream &OS,
+ StringRef Style) {
+ OS << Val;
+ }
+};
+
+template <> struct format_provider<clang::ssaf::EntityLinkage> {
+ static void format(clang::ssaf::EntityLinkage Val, raw_ostream &OS,
+ StringRef Style) {
+ OS << Val;
+ }
+};
+
+template <> struct format_provider<clang::ssaf::BuildNamespaceKind> {
+ static void format(clang::ssaf::BuildNamespaceKind Val, raw_ostream &OS,
+ StringRef Style) {
+ OS << Val;
+ }
+};
+
+template <> struct format_provider<clang::ssaf::BuildNamespace> {
+ static void format(const clang::ssaf::BuildNamespace &Val, raw_ostream &OS,
+ StringRef Style) {
+ OS << Val;
+ }
+};
+
+template <> struct format_provider<clang::ssaf::NestedBuildNamespace> {
+ static void format(const clang::ssaf::NestedBuildNamespace &Val,
+ raw_ostream &OS, StringRef Style) {
+ OS << Val;
+ }
+};
+
+template <> struct format_provider<clang::ssaf::EntityName> {
+ static void format(const clang::ssaf::EntityName &Val, raw_ostream &OS,
+ StringRef Style) {
+ OS << Val;
+ }
+};
+
+template <> struct format_provider<clang::ssaf::SummaryName> {
+ static void format(const clang::ssaf::SummaryName &Val, raw_ostream &OS,
+ StringRef Style) {
+ OS << Val;
+ }
+};
+
+template <> struct format_provider<clang::ssaf::AnalysisName> {
+ static void format(const clang::ssaf::AnalysisName &Val, raw_ostream &OS,
+ StringRef Style) {
+ OS << Val;
+ }
+};
+
+} // namespace llvm
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_SUPPORT_FORMATPROVIDERS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h
new file mode 100644
index 0000000000000..305abc05f19f3
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h
@@ -0,0 +1,30 @@
+//===- EntitySummary.h ------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_ENTITYSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_ENTITYSUMMARY_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include <type_traits>
+
+namespace clang::ssaf {
+
+/// Base class for analysis-specific summary data.
+class EntitySummary {
+public:
+ virtual ~EntitySummary() = default;
+ virtual SummaryName getSummaryName() const = 0;
+};
+
+template <typename Derived>
+using DerivesFromEntitySummary =
+ std::enable_if_t<std::is_base_of_v<EntitySummary, Derived>>;
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_ENTITYSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h
new file mode 100644
index 0000000000000..de0fd85f2a023
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h
@@ -0,0 +1,56 @@
+//===- ExtractorRegistry.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Registry for TUSummaryExtractors, and some helper functions.
+// To register some custom extractor, insert this code:
+//
+// namespace clang::ssaf {
+// // NOLINTNEXTLINE(misc-use-internal-linkage)
+// volatile int MyExtractorAnchorSource = 0;
+// } // namespace clang::ssaf
+// static TUSummaryExtractorRegistry::Add<MyExtractor>
+// X("MyExtractor", "My awesome extractor");
+//
+// Finally, extend the `AnchorSources` list in the force-linker header:
+// clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h:
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
+
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/Support/Compiler.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Registry.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang::ssaf {
+
+/// Check if a TUSummaryExtractor was registered with a given name.
+bool isTUSummaryExtractorRegistered(llvm::StringRef SummaryName);
+
+/// Try to instantiate a TUSummaryExtractor with a given name.
+/// This might return null if the construction of the desired TUSummaryExtractor
+/// failed.
+/// It's a fatal error if there is no extractor registered with the name.
+std::unique_ptr<TUSummaryExtractor>
+makeTUSummaryExtractor(llvm::StringRef SummaryName, TUSummaryBuilder &Builder);
+
+/// Print the list of available TUSummaryExtractors.
+void printAvailableTUSummaryExtractors(llvm::raw_ostream &OS);
+
+// Registry for adding new TUSummaryExtractor implementations.
+using TUSummaryExtractorRegistry =
+ llvm::Registry<TUSummaryExtractor, TUSummaryBuilder &>;
+
+} // namespace clang::ssaf
+
+LLVM_DECLARE_REGISTRY(clang::ssaf::TUSummaryExtractorRegistry)
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_EXTRACTORREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h
new file mode 100644
index 0000000000000..87b814690fb99
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h
@@ -0,0 +1,51 @@
+//===- TUSummary.h ----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARY_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "llvm/TargetParser/Triple.h"
+#include <map>
+#include <memory>
+
+namespace clang::ssaf {
+
+/// Data extracted for a given translation unit and for a given set of analyses.
+class TUSummary {
+ /// Target triple of the translation unit.
+ llvm::Triple TargetTriple;
+
+ /// Identifies the translation unit.
+ BuildNamespace TUNamespace;
+
+ EntityIdTable IdTable;
+
+ std::map<EntityId, EntityLinkage> LinkageTable;
+
+ std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>
+ Data;
+
+public:
+ TUSummary(llvm::Triple TargetTriple, BuildNamespace TUNamespace)
+ : TargetTriple(std::move(TargetTriple)),
+ TUNamespace(std::move(TUNamespace)) {}
+
+ friend class SerializationFormat;
+ friend class TestFixture;
+ friend class TUSummaryBuilder;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h
new file mode 100644
index 0000000000000..5132761ed6bb5
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h
@@ -0,0 +1,81 @@
+//===- TUSummaryBuilder.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include <memory>
+#include <utility>
+
+namespace clang::ssaf {
+
+class EntityName;
+class SSAFOptions;
+class TUSummary;
+
+class TUSummaryBuilder {
+public:
+ TUSummaryBuilder(TUSummary &Summary, const SSAFOptions &Options)
+ : Summary(Summary), Options(Options) {}
+
+ EntityId addEntity(const EntityName &EN, EntityLinkageType Linkage);
+
+ /// Associate the \p Data \c EntitySummary with the \p Entity.
+ /// This consumes the \p Data only if \p Entity wasn't associated yet with the
+ /// same kind of \c EntitySummary.
+ /// \returns a pointer to the \c EntitySummary and whether it inserted or not.
+ template <typename ConcreteEntitySummary,
+ DerivesFromEntitySummary<ConcreteEntitySummary> * = nullptr>
+ std::pair<EntitySummary *, bool>
+ addSummary(EntityId Entity, std::unique_ptr<ConcreteEntitySummary> &&Data);
+
+ /// \returns the \c SSAFOptions of this builder.
+ const SSAFOptions &getOptions() const { return Options; }
+
+private:
+ TUSummary &Summary;
+ const SSAFOptions &Options;
+
+ std::pair<EntitySummary *, bool>
+ addSummaryImpl(EntityId Entity, std::unique_ptr<EntitySummary> &&Data);
+};
+
+// Why is this a template?
+//
+// We use template here to avoid an implicit conversion from
+// `std::unique_ptr<ConcreteEntitySummary>` to `std::unique_ptr<EntitySummary>`
+// because constructing that implicit temporary would unconditionally "consume"
+// the Data. This would make it impossible to recover from the call-site the
+// Data you pass in even if no insertion happens.
+template <typename ConcreteEntitySummary,
+ DerivesFromEntitySummary<ConcreteEntitySummary> *>
+std::pair<EntitySummary *, bool>
+TUSummaryBuilder::addSummary(EntityId Entity,
+ std::unique_ptr<ConcreteEntitySummary> &&Data) {
+ // Prepare a unique_ptr of the base type to avoid implicit conversions at the
+ // call-site.
+ std::unique_ptr<EntitySummary> TypeErasedData = std::move(Data);
+
+ // This only moves (consumes) TypeErasedData if insertion happened.
+ // Otherwise it doesn't touch the `TypeErasedData`.
+ auto [It, Inserted] = addSummaryImpl(Entity, std::move(TypeErasedData));
+
+ // Move it back on failure to keep the `Data` unconsumed.
+ if (!Inserted) {
+ Data = std::unique_ptr<ConcreteEntitySummary>(
+ static_cast<ConcreteEntitySummary *>(TypeErasedData.release()));
+ }
+ return {It, Inserted};
+}
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYBUILDER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h
new file mode 100644
index 0000000000000..db2343959021b
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h
@@ -0,0 +1,45 @@
+//===- TUSummaryExtractor.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/Decl.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include <optional>
+
+namespace clang::ssaf {
+class SSAFOptions;
+class TUSummaryBuilder;
+
+class TUSummaryExtractor : public ASTConsumer {
+public:
+ explicit TUSummaryExtractor(TUSummaryBuilder &Builder)
+ : SummaryBuilder(Builder) {}
+
+ /// Creates EntityName from the Decl, registers the entity, and sets its
+ /// linkage atomically.
+ /// \returns the EntityId, or std::nullopt if EntityName creation fails.
+ std::optional<EntityId> addEntity(const NamedDecl *D);
+
+ /// Creates EntityName for the return value of \p FD, registers the entity,
+ /// and sets its linkage atomically.
+ /// \returns the EntityId, or std::nullopt if EntityName creation fails.
+ std::optional<EntityId> addEntityForReturn(const FunctionDecl *FD);
+
+ /// \returns the \c SSAFOptions of the builder.
+ const SSAFOptions &getOptions() const;
+
+protected:
+ TUSummaryBuilder &SummaryBuilder;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_TUSUMMARY_TUSUMMARYEXTRACTOR_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h
new file mode 100644
index 0000000000000..638791f9b1646
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h
@@ -0,0 +1,60 @@
+//===- AnalysisBase.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Minimal common base for SummaryAnalysisBase and DerivedAnalysisBase.
+// Carries the identity (getAnalysisName()) and dependency list
+// (getDependencyNames()) shared by every analysis regardless of kind.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
+
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include <vector>
+
+namespace clang::ssaf {
+
+class AnalysisDriver;
+class AnalysisResult;
+class DerivedAnalysisBase;
+class SummaryAnalysisBase;
+
+/// Minimal common base for both analysis kinds.
+///
+/// Not subclassed directly -- use SummaryAnalysis<...> or
+/// DerivedAnalysis<...> instead.
+class AnalysisBase {
+ friend class AnalysisDriver;
+ friend class DerivedAnalysisBase;
+ friend class SummaryAnalysisBase;
+
+ enum class Kind { Summary, Derived };
+ Kind TheKind;
+
+protected:
+ explicit AnalysisBase(Kind K) : TheKind(K) {}
+
+public:
+ virtual ~AnalysisBase() = default;
+
+ /// Name of this analysis. Equal to ResultT::analysisName() in both typed
+ /// intermediates.
+ virtual AnalysisName getAnalysisName() const = 0;
+
+ /// AnalysisNames of all AnalysisResult dependencies.
+ virtual const std::vector<AnalysisName> &getDependencyNames() const = 0;
+
+ /// Transfers ownership of the built result. Called once after finalize().
+ /// The rvalue ref-qualifier enforces single use.
+ virtual std::unique_ptr<AnalysisResult> takeResult() && = 0;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISBASE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h
new file mode 100644
index 0000000000000..148234f5c9649
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h
@@ -0,0 +1,95 @@
+//===- AnalysisDriver.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Central orchestrator for whole-program analysis. Takes ownership of an
+// LUSummary, drives all registered analyses in topological dependency order,
+// and returns a WPASuite.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Error.h"
+#include <memory>
+#include <vector>
+
+namespace clang::ssaf {
+
+class AnalysisBase;
+class DerivedAnalysisBase;
+class SummaryAnalysisBase;
+
+/// Orchestrates whole-program analysis over an LUSummary.
+///
+/// Three run() patterns are supported:
+/// - run() && -- all registered analyses in topological dependency
+/// order. Returns an error if any registered analysis
+/// has no matching entity data in the LUSummary.
+/// Requires an rvalue driver because this exhausts the
+/// LUSummary.
+/// - run(names) -- named subset plus transitive dependencies; returns
+/// Expected and fails if any listed name has no
+/// registered analysis or missing entity data.
+/// - run<ResultTs..> -- type-safe variant of run(names).
+class AnalysisDriver final {
+public:
+ explicit AnalysisDriver(std::unique_ptr<LUSummary> LU);
+
+ /// Runs all registered analyses in topological dependency order.
+ /// Returns an error if any registered analysis has no matching entity data
+ /// in the LUSummary.
+ ///
+ /// Requires an rvalue driver (std::move(Driver).run()) because this
+ /// exhausts all remaining LUSummary data.
+ [[nodiscard]] llvm::Expected<WPASuite> run() &&;
+
+ /// Runs only the named analyses (plus their transitive dependencies).
+ ///
+ /// Returns an error if any listed AnalysisName has no registered analysis
+ /// or if a required SummaryAnalysis has no matching entity data in the
+ /// LUSummary. The EntityIdTable is copied (not moved) so the driver remains
+ /// usable for subsequent calls.
+ [[nodiscard]] llvm::Expected<WPASuite>
+ run(llvm::ArrayRef<AnalysisName> Names) const;
+
+ /// Type-safe variant of run(names). Derives names from
+ /// ResultTs::analysisName().
+ template <typename... ResultTs>
+ [[nodiscard]] llvm::Expected<WPASuite> run() const {
+ return run({ResultTs::analysisName()...});
+ }
+
+private:
+ std::unique_ptr<LUSummary> LU;
+
+ /// Instantiates all analyses reachable from \p Roots (plus transitive
+ /// dependencies) and returns them in topological order via a single DFS.
+ /// Reports an error on unregistered names or cycles.
+ static llvm::Expected<std::vector<std::unique_ptr<AnalysisBase>>>
+ toposort(llvm::ArrayRef<AnalysisName> Roots);
+
+ /// Executes a topologically-sorted analysis list and returns a WPASuite.
+ /// \p IdTable is moved into the returned WPASuite.
+ llvm::Expected<WPASuite>
+ execute(EntityIdTable IdTable,
+ llvm::ArrayRef<std::unique_ptr<AnalysisBase>> Sorted) const;
+
+ llvm::Error executeSummaryAnalysis(SummaryAnalysisBase &Summary,
+ WPASuite &Suite) const;
+
+ llvm::Error executeDerivedAnalysis(DerivedAnalysisBase &Derived,
+ WPASuite &Suite) const;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISDRIVER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h
new file mode 100644
index 0000000000000..71a0a26b9853d
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h
@@ -0,0 +1,49 @@
+//===- AnalysisName.h -------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Strong typedef identifying a whole-program analysis and its result type.
+// Distinct from SummaryName, which identifies per-entity EntitySummary types.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace clang::ssaf {
+
+/// Uniquely identifies a whole-program analysis and the AnalysisResult it
+/// produces. Used as the key in WPASuite and AnalysisRegistry.
+///
+/// Distinct from SummaryName, which is used by EntitySummary types for routing
+/// through the LUSummary.
+class AnalysisName {
+public:
+ explicit AnalysisName(std::string Name) : Name(std::move(Name)) {}
+
+ bool operator==(const AnalysisName &Other) const {
+ return Name == Other.Name;
+ }
+ bool operator!=(const AnalysisName &Other) const { return !(*this == Other); }
+ bool operator<(const AnalysisName &Other) const { return Name < Other.Name; }
+
+ /// Explicit conversion to the underlying string representation.
+ llvm::StringRef str() const { return Name; }
+
+private:
+ std::string Name;
+};
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const AnalysisName &AN);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISNAME_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h
new file mode 100644
index 0000000000000..9672b62d1e05f
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h
@@ -0,0 +1,111 @@
+//===- AnalysisRegistry.h ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Unified registry for both SummaryAnalysis and DerivedAnalysis subclasses.
+//
+// To register an analysis, add a static Add<AnalysisT> and an anchor source
+// in its translation unit, then add the anchor source to the `AnchorSources`
+// list in the relevant force-linker header:
+//
+// // MyAnalysis.cpp
+// static AnalysisRegistry::Add<MyAnalysis>
+// Registered("One-line description of MyAnalysis");
+//
+// namespace clang::ssaf {
+// // NOLINTNEXTLINE(misc-use-internal-linkage)
+// volatile int MyAnalysisAnchorSource = 0;
+// } // namespace clang::ssaf
+//
+// // Extend SSAFBuiltinForceLinker.h (or the relevant force-linker header)
+//
+// The registry entry name is derived automatically from
+// MyAnalysis::analysisName(), so name-mismatch bugs are impossible.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
+
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Registry.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+LLVM_DECLARE_REGISTRY(llvm::Registry<clang::ssaf::AnalysisBase>)
+
+namespace clang::ssaf {
+
+/// Unified registry for SummaryAnalysis and DerivedAnalysis implementations.
+///
+/// Internally uses a single llvm::Registry<AnalysisBase>. The correct kind
+/// is carried by the AnalysisBase::TheKind tag set in each subclass
+/// constructor.
+class AnalysisRegistry {
+ using RegistryT = llvm::Registry<AnalysisBase>;
+
+ AnalysisRegistry() = delete;
+
+public:
+ /// Registers AnalysisT with the unified registry.
+ ///
+ /// The registry entry name is derived automatically from
+ /// AnalysisT::ResultType::analysisName(), so name-mismatch bugs are
+ /// impossible.
+ ///
+ /// Add objects must be declared static at namespace scope.
+ template <typename AnalysisT> struct Add {
+ static_assert(std::is_base_of_v<SummaryAnalysisBase, AnalysisT> ||
+ std::is_base_of_v<DerivedAnalysisBase, AnalysisT>,
+ "AnalysisT must derive from SummaryAnalysis<...> or "
+ "DerivedAnalysis<...>");
+
+ explicit Add(llvm::StringRef Desc)
+ : Name(AnalysisT::ResultType::analysisName().str().str()),
+ Node(Name, Desc) {
+ if (contains(AnalysisT::ResultType::analysisName())) {
+ ErrorBuilder::fatal("duplicate analysis registration for '{0}'", Name);
+ }
+ getAnalysisNames().push_back(AnalysisT::ResultType::analysisName());
+ }
+
+ Add(const Add &) = delete;
+ Add &operator=(const Add &) = delete;
+
+ private:
+ std::string Name;
+ RegistryT::Add<AnalysisT> Node;
+ };
+
+ /// Returns true if an analysis is registered under \p Name.
+ static bool contains(const AnalysisName &Name);
+
+ /// Returns the names of all registered analyses.
+ static const std::vector<AnalysisName> &names();
+
+ /// Instantiates the analysis registered under \p Name, or returns an error
+ /// if no such analysis is registered.
+ static llvm::Expected<std::unique_ptr<AnalysisBase>>
+ instantiate(const AnalysisName &Name);
+
+private:
+ /// Returns the global list of registered analysis names.
+ ///
+ /// Uses a function-local static to avoid static initialization order
+ /// fiasco: Add<T> objects in other translation units may push names before
+ /// a plain static data member could be constructed.
+ static std::vector<AnalysisName> &getAnalysisNames();
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h
new file mode 100644
index 0000000000000..fc10a6f2707fb
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h
@@ -0,0 +1,30 @@
+//===- AnalysisResult.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Base class for all whole-program analysis results produced by AnalysisDriver.
+// Concrete subclasses carry a static analysisName().
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
+
+namespace clang::ssaf {
+
+/// Base class for whole-program analysis results.
+///
+/// Concrete subclasses must provide:
+/// static AnalysisName analysisName();
+class AnalysisResult {
+public:
+ virtual ~AnalysisResult() = default;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISRESULT_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h
new file mode 100644
index 0000000000000..f4daf01b2660f
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h
@@ -0,0 +1,36 @@
+//===- AnalysisTraits.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Type traits for AnalysisResult subclasses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
+
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include <type_traits>
+
+namespace clang::ssaf {
+
+/// Type trait that checks whether \p T has a static \c analysisName() method
+/// returning \c AnalysisName. Used to enforce the convention on AnalysisResult
+/// subclasses and analysis classes at instantiation time.
+template <typename T, typename = void>
+struct HasAnalysisName : std::false_type {};
+
+template <typename T>
+struct HasAnalysisName<T, std::void_t<decltype(T::analysisName())>>
+ : std::is_same<decltype(T::analysisName()), AnalysisName> {};
+
+template <typename T>
+inline constexpr bool HasAnalysisName_v = HasAnalysisName<T>::value;
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_ANALYSISTRAITS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h
new file mode 100644
index 0000000000000..1fb33c83ed6b0
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h
@@ -0,0 +1,133 @@
+//===- DerivedAnalysis.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines DerivedAnalysisBase (type-erased base known to AnalysisDriver) and
+// the typed intermediate DerivedAnalysis<ResultT, DepResultTs...> that
+// concrete analyses inherit from.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
+
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h"
+#include "llvm/Support/Error.h"
+#include <map>
+#include <memory>
+#include <vector>
+
+namespace clang::ssaf {
+
+class AnalysisDriver;
+class AnalysisRegistry;
+
+/// Type-erased base for derived analyses. Known to AnalysisDriver.
+///
+/// Not subclassed directly -- use DerivedAnalysis<ResultT, DepResultTs...>.
+/// A derived analysis consumes previously produced AnalysisResult objects
+/// and computes a new one via an initialize/step/finalize lifecycle.
+class DerivedAnalysisBase : public AnalysisBase {
+ friend class AnalysisDriver;
+
+protected:
+ DerivedAnalysisBase() : AnalysisBase(AnalysisBase::Kind::Derived) {}
+
+private:
+ /// Called once with the dependency results before the step() loop.
+ ///
+ /// \param DepResults Immutable results of all declared dependencies, keyed
+ /// by AnalysisName. Guaranteed to contain every name
+ /// returned by dependencyNames().
+ virtual llvm::Error initialize(
+ const std::map<AnalysisName, const AnalysisResult *> &DepResults) = 0;
+
+ /// Performs one pass.
+ /// Returns true if another pass is needed; false when converged.
+ virtual llvm::Expected<bool> step() = 0;
+
+ /// Called after the step() loop converges. Default is a no-op.
+ virtual llvm::Error finalize() { return llvm::Error::success(); }
+};
+
+/// Typed intermediate that concrete derived analyses inherit from.
+///
+/// Concrete analyses must implement:
+/// llvm::Error initialize(const DepResultTs &...) override;
+/// llvm::Expected<bool> step() override;
+/// and may override finalize().
+///
+/// Dependencies are fixed for the lifetime of the analysis: initialize()
+/// binds them once, step() is called until it returns false, and
+/// finalize() post-processes after convergence.
+template <typename ResultT, typename... DepResultTs>
+class DerivedAnalysis : public DerivedAnalysisBase {
+ static_assert(std::is_base_of_v<AnalysisResult, ResultT>,
+ "ResultT must derive from AnalysisResult");
+ static_assert(HasAnalysisName_v<ResultT>,
+ "ResultT must have a static analysisName() method");
+ static_assert((std::is_base_of_v<AnalysisResult, DepResultTs> && ...),
+ "Every DepResultT must derive from AnalysisResult");
+ static_assert((HasAnalysisName_v<DepResultTs> && ...),
+ "Every DepResultT must have a static analysisName() method");
+
+ friend class AnalysisRegistry;
+ using ResultType = ResultT;
+
+ std::unique_ptr<ResultT> Result = std::make_unique<ResultT>();
+
+public:
+ /// Used by AnalysisRegistry::Add to derive the registry entry name.
+ AnalysisName getAnalysisName() const final { return ResultT::analysisName(); }
+
+ const std::vector<AnalysisName> &getDependencyNames() const final {
+ static const std::vector<AnalysisName> Names = {
+ DepResultTs::analysisName()...};
+ return Names;
+ }
+
+ /// Called once with the fixed dependency results before the step() loop.
+ virtual llvm::Error initialize(const DepResultTs &...) = 0;
+
+protected:
+ /// Read-only access to the result being built.
+ const ResultT &getResult() const & { return *Result; }
+
+ /// Mutable access to the result being built.
+ ResultT &getResult() & { return *Result; }
+
+private:
+ /// Seals the type-erased base overload, downcasts, and dispatches to the
+ /// typed initialize(). All dependencies are guaranteed present by the driver.
+ llvm::Error
+ initialize(const std::map<AnalysisName, const AnalysisResult *> &Map) final {
+ auto lookup = [&Map](const AnalysisName &Name) -> const AnalysisResult * {
+ auto It = Map.find(Name);
+ if (It == Map.end()) {
+ ErrorBuilder::fatal("dependency '{0}' missing from DepResults map; "
+ "dependency graph is not topologically sorted",
+ Name);
+ }
+ return It->second;
+ };
+ return initialize(*static_cast<const DepResultTs *>(
+ lookup(DepResultTs::analysisName()))...);
+ }
+
+ /// Type-erased result extraction for the driver.
+ std::unique_ptr<AnalysisResult> takeResult() && final {
+ return std::move(Result);
+ }
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_DERIVEDANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h
new file mode 100644
index 0000000000000..cf3bec9bb3b5e
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h
@@ -0,0 +1,121 @@
+//===- SummaryAnalysis.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines SummaryAnalysisBase (type-erased base known to AnalysisDriver) and
+// the typed intermediate SummaryAnalysis<ResultT, EntitySummaryT> that
+// concrete analyses inherit from.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisBase.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h"
+#include "llvm/Support/Error.h"
+#include <memory>
+
+namespace clang::ssaf {
+
+class AnalysisDriver;
+class AnalysisRegistry;
+
+/// Type-erased base for summary analyses. Known to AnalysisDriver.
+///
+/// Not subclassed directly -- use SummaryAnalysis<ResultT, EntitySummaryT>.
+/// A summary analysis processes per-entity EntitySummary objects from the
+/// LUSummary one at a time, accumulating whole-program data into an
+/// AnalysisResult.
+class SummaryAnalysisBase : public AnalysisBase {
+ friend class AnalysisDriver;
+
+protected:
+ SummaryAnalysisBase() : AnalysisBase(AnalysisBase::Kind::Summary) {}
+
+public:
+ /// SummaryName of the EntitySummary type this analysis consumes.
+ /// Used by the driver to route entities from the LUSummary.
+ virtual SummaryName getSummaryName() const = 0;
+
+private:
+ /// Called once before any add() calls. Default is a no-op.
+ virtual llvm::Error initialize() { return llvm::Error::success(); }
+
+ /// Called once per matching entity. The driver retains ownership of the
+ /// summary; multiple SummaryAnalysis instances may receive the same entity.
+ virtual llvm::Error add(EntityId Id, const EntitySummary &Summary) = 0;
+
+ /// Called after all entities have been processed. Default is a no-op.
+ virtual llvm::Error finalize() { return llvm::Error::success(); }
+};
+
+/// Typed intermediate that concrete summary analyses inherit from.
+///
+/// Concrete analyses must implement:
+/// llvm::Error add(EntityId Id, const EntitySummaryT &Summary) override;
+/// and may override initialize() and finalize().
+///
+/// The result being built is accessible via getResult() const & (read-only) and
+/// getResult() & (mutable) within the analysis implementation.
+template <typename ResultT, typename EntitySummaryT>
+class SummaryAnalysis : public SummaryAnalysisBase {
+ static_assert(std::is_base_of_v<AnalysisResult, ResultT>,
+ "ResultT must derive from AnalysisResult");
+ static_assert(HasAnalysisName_v<ResultT>,
+ "ResultT must have a static analysisName() method");
+ static_assert(std::is_base_of_v<EntitySummary, EntitySummaryT>,
+ "EntitySummaryT must derive from EntitySummary");
+
+ friend class AnalysisRegistry;
+ using ResultType = ResultT;
+
+ std::unique_ptr<ResultT> Result = std::make_unique<ResultT>();
+
+public:
+ /// Used by AnalysisRegistry::Add to derive the registry entry name.
+ AnalysisName getAnalysisName() const final { return ResultT::analysisName(); }
+
+ SummaryName getSummaryName() const final {
+ return EntitySummaryT::summaryName();
+ }
+
+ const std::vector<AnalysisName> &getDependencyNames() const final {
+ static const std::vector<AnalysisName> Empty;
+ return Empty;
+ }
+
+ /// Called once per matching entity. Implement to accumulate data.
+ virtual llvm::Error add(EntityId Id, const EntitySummaryT &Summary) = 0;
+
+protected:
+ /// Read-only access to the result being built.
+ const ResultT &getResult() const & { return *Result; }
+
+ /// Mutable access to the result being built.
+ ResultT &getResult() & { return *Result; }
+
+private:
+ /// Seals the type-erased base overload, downcasts, and dispatches to the
+ /// typed add().
+ llvm::Error add(EntityId Id, const EntitySummary &Summary) final {
+ return add(Id, static_cast<const EntitySummaryT &>(Summary));
+ }
+
+ /// Type-erased result extraction for the driver.
+ std::unique_ptr<AnalysisResult> takeResult() && final {
+ return std::move(Result);
+ }
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_SUMMARYANALYSIS_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h
new file mode 100644
index 0000000000000..cdc74ded19443
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h
@@ -0,0 +1,99 @@
+//===- WPASuite.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// The value returned by AnalysisDriver::run(). Bundles the EntityIdTable
+// with the analysis results keyed by AnalysisName.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisTraits.h"
+#include "llvm/Support/Error.h"
+#include <map>
+#include <memory>
+
+namespace clang::ssaf {
+
+class AnalysisDriver;
+class SerializationFormat;
+class TestFixture;
+
+/// Bundles the EntityIdTable (moved from the LUSummary) and the analysis
+/// results produced by one AnalysisDriver::run() call, keyed by AnalysisName.
+///
+/// This is the natural unit of persistence: entity names and analysis results
+/// are self-contained in one object.
+class WPASuite {
+ friend class AnalysisDriver;
+ friend class SerializationFormat;
+ friend class TestFixture;
+
+ EntityIdTable IdTable;
+ std::map<AnalysisName, std::unique_ptr<AnalysisResult>> Data;
+
+ WPASuite() = default;
+
+public:
+ /// Returns the EntityIdTable that maps EntityId values to their symbolic
+ /// names.
+ const EntityIdTable &getIdTable() const { return IdTable; }
+
+ /// Returns true if a result for \p ResultT is present.
+ template <typename ResultT> [[nodiscard]] bool contains() const {
+ static_assert(std::is_base_of_v<AnalysisResult, ResultT>,
+ "ResultT must derive from AnalysisResult");
+ static_assert(HasAnalysisName_v<ResultT>,
+ "ResultT must have a static analysisName() method");
+
+ return contains(ResultT::analysisName());
+ }
+
+ /// Returns true if a result for \p Name is present.
+ [[nodiscard]] bool contains(AnalysisName Name) const {
+ return Data.find(Name) != Data.end();
+ }
+
+ /// Returns a const reference to the result for \p ResultT, or an error if
+ /// absent.
+ template <typename ResultT>
+ [[nodiscard]] llvm::Expected<const ResultT &> get() const {
+ static_assert(std::is_base_of_v<AnalysisResult, ResultT>,
+ "ResultT must derive from AnalysisResult");
+ static_assert(HasAnalysisName_v<ResultT>,
+ "ResultT must have a static analysisName() method");
+
+ auto Result = get(ResultT::analysisName());
+ if (!Result) {
+ return Result.takeError();
+ }
+ return static_cast<const ResultT &>(*Result);
+ }
+
+ /// Returns a const reference to the result for \p Name, or an error if
+ /// absent.
+ [[nodiscard]] llvm::Expected<const AnalysisResult &>
+ get(AnalysisName Name) const {
+ auto It = Data.find(Name);
+ if (It == Data.end()) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ "no result for '{0}' in WPASuite", Name)
+ .build();
+ }
+ return *It->second;
+ }
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_CORE_WHOLEPROGRAMANALYSIS_WPASUITE_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h b/clang/include/clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h
new file mode 100644
index 0000000000000..300aab9560be2
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h
@@ -0,0 +1,33 @@
+//===- TUSummaryExtractorFrontendAction.h -----------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
+
+#include "clang/Frontend/FrontendAction.h"
+#include <memory>
+
+namespace clang::ssaf {
+
+/// Wraps the existing \c FrontendAction and injects the extractor
+/// \c ASTConsumers into the pipeline after the ASTConsumers of the wrapped
+/// action.
+class TUSummaryExtractorFrontendAction final : public WrapperFrontendAction {
+public:
+ explicit TUSummaryExtractorFrontendAction(
+ std::unique_ptr<FrontendAction> WrappedAction);
+ ~TUSummaryExtractorFrontendAction();
+
+protected:
+ std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) override;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_FRONTEND_TUSUMMARYEXTRACTORFRONTENDACTION_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h b/clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h
new file mode 100644
index 0000000000000..97783c05d8fd0
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h
@@ -0,0 +1,43 @@
+//===- SSAFBuiltinForceLinker.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file pulls in all built-in SSAF extractor and format registrations
+/// by referencing their anchor symbols, preventing the static linker from
+/// discarding the containing object files.
+///
+/// Include this header (with IWYU pragma: keep) in any translation unit that
+/// must guarantee these registrations are active — typically the entry point
+/// of a binary that uses clangScalableStaticAnalysisCore.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFBUILTINFORCELINKER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFBUILTINFORCELINKER_H
+
+namespace clang::ssaf {
+
+#define ANCHOR(NAME) extern volatile int NAME;
+#include "BuiltinAnchorSources.def"
+
+// Force the linker to link in the built-in SSAF registrations.
+[[maybe_unused]] static const int BuiltinAnchorDestination = [] {
+ int AnchorSources[]{
+#define ANCHOR(NAME) NAME,
+#include "BuiltinAnchorSources.def"
+ };
+
+ int SomeUse = 0;
+ for (int V : AnchorSources)
+ SomeUse |= V;
+ return SomeUse;
+}();
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFBUILTINFORCELINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h b/clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h
new file mode 100644
index 0000000000000..bf0b74e3955f3
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/SSAFForceLinker.h
@@ -0,0 +1,25 @@
+//===- SSAFForceLinker.h ----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file pulls in all built-in SSAF extractor and format registrations
+/// by referencing their anchor symbols, preventing the static linker from
+/// discarding the containing object files.
+///
+/// Include this header (with IWYU pragma: keep) in any translation unit that
+/// must guarantee these registrations are active — typically the entry point
+/// of a binary that uses clangScalableStaticAnalysisCore.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFFORCELINKER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFFORCELINKER_H
+
+#include "SSAFBuiltinForceLinker.h" // IWYU pragma: keep
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_SSAFFORCELINKER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/SourceEditEmitter.h b/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/SourceEditEmitter.h
new file mode 100644
index 0000000000000..160d30bfbc665
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/SourceEditEmitter.h
@@ -0,0 +1,29 @@
+//===- SourceEditEmitter.h --------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Abstract accumulator for source edits.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_SOURCEEDITEMITTER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_SOURCEEDITEMITTER_H
+
+#include "clang/Tooling/Core/Replacement.h"
+
+namespace clang::ssaf {
+
+class SourceEditEmitter {
+public:
+ virtual ~SourceEditEmitter() = default;
+
+ virtual void addReplacement(clang::tooling::Replacement R) = 0;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_SOURCEEDITEMITTER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/Transformation.h b/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/Transformation.h
new file mode 100644
index 0000000000000..fae222cda0e84
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/Transformation.h
@@ -0,0 +1,38 @@
+//===- Transformation.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Abstract base class for source transformations. A Transformation is an
+// ASTConsumer that consumes a previously computed WPASuite.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_TRANSFORMATION_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_TRANSFORMATION_H
+
+#include "clang/AST/ASTConsumer.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "clang/ScalableStaticAnalysis/SourceTransformation/SourceEditEmitter.h"
+#include "clang/ScalableStaticAnalysis/SourceTransformation/TransformationReportEmitter.h"
+
+namespace clang::ssaf {
+
+class Transformation : public clang::ASTConsumer {
+public:
+ Transformation(const WPASuite &Suite, SourceEditEmitter &Edits,
+ TransformationReportEmitter &Report)
+ : Suite(Suite), Edits(Edits), Report(Report) {}
+
+protected:
+ const WPASuite &Suite;
+ SourceEditEmitter &Edits;
+ TransformationReportEmitter &Report;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_TRANSFORMATION_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.h b/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.h
new file mode 100644
index 0000000000000..97301d005e496
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.h
@@ -0,0 +1,66 @@
+//===- TransformationRegistry.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Registry for Transformations, and some helper functions.
+// To register a transformation, insert this code:
+//
+// namespace clang::ssaf {
+// // NOLINTNEXTLINE(misc-use-internal-linkage)
+// volatile int MyTransformationAnchorSource = 0;
+// } // namespace clang::ssaf
+// static TransformationRegistry::Add<MyTransformation>
+// X("MyTransformation", "My awesome transformation");
+//
+// For a statically-linked transformation also extend the `AnchorSources`
+// list in
+// clang/include/clang/ScalableStaticAnalysis/SSAFBuiltinForceLinker.h
+// (plugin-loaded transformations do not need an anchor — the dynamic loader
+// runs every global ctor on load).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_TRANSFORMATIONREGISTRY_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_TRANSFORMATIONREGISTRY_H
+
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "clang/ScalableStaticAnalysis/SourceTransformation/SourceEditEmitter.h"
+#include "clang/ScalableStaticAnalysis/SourceTransformation/Transformation.h"
+#include "clang/ScalableStaticAnalysis/SourceTransformation/TransformationReportEmitter.h"
+#include "clang/Support/Compiler.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Registry.h"
+#include "llvm/Support/raw_ostream.h"
+#include <memory>
+
+namespace clang::ssaf {
+
+/// Check if a Transformation was registered with a given name.
+bool isTransformationRegistered(llvm::StringRef Name);
+
+/// Try to instantiate a Transformation with a given name.
+/// This might return null if the construction of the desired Transformation
+/// failed.
+/// It's a fatal error if there is no transformation registered with the name.
+std::unique_ptr<Transformation>
+makeTransformation(llvm::StringRef Name, const WPASuite &Suite,
+ SourceEditEmitter &Edits,
+ TransformationReportEmitter &Report);
+
+/// Print the list of available Transformations.
+void printAvailableTransformations(llvm::raw_ostream &OS);
+
+// Registry for adding new Transformation implementations.
+using TransformationRegistry =
+ llvm::Registry<Transformation, const WPASuite &, SourceEditEmitter &,
+ TransformationReportEmitter &>;
+
+} // namespace clang::ssaf
+
+LLVM_DECLARE_REGISTRY(clang::ssaf::TransformationRegistry)
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_TRANSFORMATIONREGISTRY_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/TransformationReportEmitter.h b/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/TransformationReportEmitter.h
new file mode 100644
index 0000000000000..2f0e47064cd1a
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/SourceTransformation/TransformationReportEmitter.h
@@ -0,0 +1,33 @@
+//===- TransformationReportEmitter.h ----------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Abstract accumulator for the transformation report.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_TRANSFORMATIONREPORTEMITTER_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_TRANSFORMATIONREPORTEMITTER_H
+
+#include "clang/Basic/Sarif.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace clang::ssaf {
+
+class TransformationReportEmitter {
+public:
+ virtual ~TransformationReportEmitter() = default;
+
+ virtual void addResult(llvm::StringRef RuleId, clang::SarifResultLevel Level,
+ clang::CharSourceRange Range,
+ llvm::StringRef Message) = 0;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_SOURCETRANSFORMATION_TRANSFORMATIONREPORTEMITTER_H
diff --git a/clang/include/clang/ScalableStaticAnalysis/Tool/Utils.h b/clang/include/clang/ScalableStaticAnalysis/Tool/Utils.h
new file mode 100644
index 0000000000000..f02bb8152cfd1
--- /dev/null
+++ b/clang/include/clang/ScalableStaticAnalysis/Tool/Utils.h
@@ -0,0 +1,95 @@
+//===- Utils.h - Shared utilities for SSAF tools ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Shared error-handling, format-registry cache, and summary-file abstraction
+// used by clang-ssaf tools.
+//
+// All declarations live in the clang::ssaf namespace.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_TOOL_UTILS_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_TOOL_UTILS_H
+
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FormatVariadic.h"
+#include <string>
+
+namespace clang::ssaf {
+
+//===----------------------------------------------------------------------===//
+// Tool Identity
+//===----------------------------------------------------------------------===//
+
+/// Returns the name of the running tool, as set by initTool().
+llvm::StringRef getToolName();
+
+//===----------------------------------------------------------------------===//
+// Diagnostic Utilities
+//===----------------------------------------------------------------------===//
+
+[[noreturn]] void fail(const char *Msg);
+
+template <typename... Ts>
+[[noreturn]] inline void fail(const char *Fmt, Ts &&...Args) {
+ std::string Message = llvm::formatv(Fmt, std::forward<Ts>(Args)...);
+ fail(Message.data());
+}
+
+[[noreturn]] void fail(llvm::Error Err);
+
+//===----------------------------------------------------------------------===//
+// Plugin Loading
+//===----------------------------------------------------------------------===//
+
+void loadPlugins(llvm::ArrayRef<std::string> Paths);
+
+//===----------------------------------------------------------------------===//
+// Initialization
+//===----------------------------------------------------------------------===//
+
+/// Sets ToolName, ToolVersion, and the version printer, hides unrelated
+/// command-line options, and parses arguments. Must be called after InitLLVM.
+void initTool(int argc, const char **argv, llvm::StringRef Version,
+ llvm::cl::OptionCategory &Category, llvm::StringRef ToolHeading);
+
+//===----------------------------------------------------------------------===//
+// Data Structures
+//===----------------------------------------------------------------------===//
+
+struct FormatFile {
+ std::string Path;
+ SerializationFormat *Format = nullptr;
+
+ /// Validates an input path and returns a FormatFile.
+ ///
+ /// Checks that the path exists and is a regular file, then resolves the
+ /// serialization format from the file extension. Read permission is not
+ /// checked here because llvm::sys::fs::AccessMode does not support Read; read
+ /// errors are caught when the file is opened during deserialization.
+ ///
+ /// Calls fail() and exits on any validation error.
+ static FormatFile fromInputPath(llvm::StringRef Path);
+
+ /// Validates an output path and returns a FormatFile.
+ ///
+ /// Checks that the output file does not already exist, that the parent
+ /// directory exists and is writable, then resolves the serialization format
+ /// from the file extension.
+ ///
+ /// Calls fail() and exits on any validation error.
+ static FormatFile fromOutputPath(llvm::StringRef Path);
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_TOOL_UTILS_H
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
new file mode 100644
index 0000000000000..dc72eb6d645d5
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/CMakeLists.txt
@@ -0,0 +1,28 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ TargetParser
+ )
+
+add_clang_library(clangScalableStaticAnalysisAnalyses
+ CallGraph/CallGraphExtractor.cpp
+ CallGraph/CallGraphJSONFormat.cpp
+ EntityPointerLevel/EntityPointerLevel.cpp
+ EntityPointerLevel/EntityPointerLevelFormat.cpp
+ PointerFlow/PointerFlow.cpp
+ PointerFlow/PointerFlowAnalysis.cpp
+ PointerFlow/PointerFlowExtractor.cpp
+ PointerFlow/PointerFlowFormat.cpp
+ SSAFAnalysesCommon.cpp
+ UnsafeBufferUsage/UnsafeBufferUsage.cpp
+ UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
+ UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
+ UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
+
+ LINK_LIBS
+ clangAST
+ clangAnalysis
+ clangBasic
+ clangScalableStaticAnalysisCore
+
+ DEPENDS
+ )
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractor.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractor.cpp
new file mode 100644
index 0000000000000..112a1666bea99
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractor.cpp
@@ -0,0 +1,108 @@
+//===- CallGraphExtractor.cpp - Call Graph Summary Extractor --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Analysis/CallGraph.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "llvm/ADT/STLExtras.h"
+#include <memory>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+class CallGraphExtractor final : public TUSummaryExtractor {
+public:
+ using TUSummaryExtractor::TUSummaryExtractor;
+
+private:
+ void HandleTranslationUnit(ASTContext &Ctx) override;
+
+ void handleCallGraphNode(const ASTContext &Ctx, const CallGraphNode *N);
+};
+} // namespace
+
+void CallGraphExtractor::HandleTranslationUnit(ASTContext &Ctx) {
+ CallGraph CG;
+ CG.addToCallGraph(
+ const_cast<TranslationUnitDecl *>(Ctx.getTranslationUnitDecl()));
+
+ for (const auto &N : llvm::make_second_range(CG)) {
+ if (N && N->getDecl() && N->getDefinition())
+ handleCallGraphNode(Ctx, N.get());
+ }
+}
+
+void CallGraphExtractor::handleCallGraphNode(const ASTContext &Ctx,
+ const CallGraphNode *N) {
+ const FunctionDecl *Definition = N->getDefinition();
+
+ // FIXME: `clang::CallGraph` does not create entries for primary templates.
+ assert(!Definition->isTemplated());
+
+ auto CallerId = addEntity(Definition);
+ if (!CallerId)
+ return;
+
+ auto FnSummary = std::make_unique<CallGraphSummary>();
+
+ PresumedLoc Loc =
+ Ctx.getSourceManager().getPresumedLoc(Definition->getLocation());
+ FnSummary->Definition.File = Loc.getFilename();
+ FnSummary->Definition.Line = Loc.getLine();
+ FnSummary->Definition.Column = Loc.getColumn();
+ FnSummary->PrettyName = AnalysisDeclContext::getFunctionName(Definition);
+
+ for (const auto &Record : N->callees()) {
+ const Decl *CalleeDecl = Record.Callee->getDecl();
+
+ // FIXME: `clang::CallGraph` does not consider indirect calls, thus this is
+ // never null.
+ assert(CalleeDecl);
+
+ // `clang::CallGraph` resolves ObjCMessageExprs (including property
+ // dot-syntax) to their ObjCMethodDecls and adds them as callees — see
+ // `CGBuilder::VisitObjCMessageExpr` in clang/lib/Analysis/CallGraph.cpp.
+ // ObjC dispatch is dynamic, so recording these as direct callees would be
+ // misleading; skip them until we model ObjC properly.
+ if (isa<ObjCMethodDecl>(CalleeDecl))
+ continue;
+
+ // FIXME: `clang::CallGraph` does not create entries for primary templates.
+ assert(!CalleeDecl->isTemplated());
+
+ auto CalleeId = addEntity(cast<NamedDecl>(CalleeDecl));
+ if (!CalleeId)
+ continue;
+
+ if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(CalleeDecl);
+ MD && MD->isVirtual()) {
+ FnSummary->VirtualCallees.insert(*CalleeId);
+ continue;
+ }
+ FnSummary->DirectCallees.insert(*CalleeId);
+ }
+
+ SummaryBuilder.addSummary(*CallerId, std::move(FnSummary));
+}
+
+static TUSummaryExtractorRegistry::Add<CallGraphExtractor>
+ RegisterExtractor(CallGraphSummary::Name,
+ "Extracts static call-graph information");
+
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int CallGraphExtractorAnchorSource = 0;
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphJSONFormat.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphJSONFormat.cpp
new file mode 100644
index 0000000000000..3260fd3e4cb3a
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphJSONFormat.cpp
@@ -0,0 +1,174 @@
+//===- CallGraphJSONFormat.cpp --------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/JSON.h"
+#include <memory>
+
+using namespace llvm;
+using namespace clang;
+using namespace ssaf;
+
+static const char *FailedToReadObjectAtField =
+ "failed to read {0} from field '{1}': expected JSON {2}";
+static const char *FailedToReadObjectAtIndex =
+ "failed to read {0} from index '{1}': expected JSON {2}";
+static const char *ReadingFromField = "reading {0} from field '{1}'";
+static const char *ReadingFromIndex = "reading {0} from index '{1}'";
+
+static json::Object serialize(const EntitySummary &Summary,
+ JSONFormat::EntityIdToJSONFn ToJSON) {
+ const auto &S = static_cast<const CallGraphSummary &>(Summary);
+
+ json::Array DirectCalleesArray;
+ DirectCalleesArray.reserve(S.DirectCallees.size());
+ append_range(DirectCalleesArray, map_range(S.DirectCallees, ToJSON));
+
+ json::Array VirtualCalleesArray;
+ VirtualCalleesArray.reserve(S.VirtualCallees.size());
+ append_range(VirtualCalleesArray, map_range(S.VirtualCallees, ToJSON));
+
+ return json::Object{
+ {"pretty_name", json::Value(S.PrettyName)},
+ {"direct_callees", std::move(DirectCalleesArray)},
+ {"virtual_callees", std::move(VirtualCalleesArray)},
+ {"def",
+ json::Object{
+ {"file", json::Value(S.Definition.File)},
+ {"line", json::Value(S.Definition.Line)},
+ {"col", json::Value(S.Definition.Column)},
+ }},
+ };
+}
+
+static Expected<std::unique_ptr<EntitySummary>>
+deserialize(const json::Object &Obj, EntityIdTable &IdTable,
+ JSONFormat::EntityIdFromJSONFn FromJSON) {
+ auto Result = std::make_unique<CallGraphSummary>();
+
+ auto PrettyName = Obj.getString("pretty_name");
+ if (!PrettyName) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ FailedToReadObjectAtField, "PrettyName",
+ "pretty_name", "string")
+ .build();
+ }
+ Result->PrettyName = PrettyName->str();
+
+ const json::Array *CalleesArray = Obj.getArray("direct_callees");
+ if (!CalleesArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ FailedToReadObjectAtField, "DirectCallees",
+ "direct_callees", "array")
+ .build();
+ }
+ for (const auto &[Index, Value] : llvm::enumerate(*CalleesArray)) {
+ const json::Object *CalleeObj = Value.getAsObject();
+ if (!CalleeObj) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ FailedToReadObjectAtIndex, "EntityId", Index,
+ "object")
+ .context(ReadingFromField, "DirectCallees", "direct_callees")
+ .build();
+ }
+ auto ExpectedId = FromJSON(*CalleeObj);
+ if (!ExpectedId) {
+ return ErrorBuilder::wrap(ExpectedId.takeError())
+ .context(ReadingFromIndex, "EntityId", Index)
+ .context(ReadingFromField, "DirectCallees", "direct_callees")
+ .build();
+ }
+ Result->DirectCallees.insert(*ExpectedId);
+ }
+
+ const json::Array *VirtualCalleesArray = Obj.getArray("virtual_callees");
+ if (!VirtualCalleesArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ FailedToReadObjectAtField, "VirtualCallees",
+ "virtual_callees", "array")
+ .build();
+ }
+ for (const auto &[Index, Value] : llvm::enumerate(*VirtualCalleesArray)) {
+ const json::Object *CalleeObj = Value.getAsObject();
+ if (!CalleeObj) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ FailedToReadObjectAtIndex, "EntityId", Index,
+ "object")
+ .context(ReadingFromField, "VirtualCallees", "virtual_callees")
+ .build();
+ }
+ auto ExpectedId = FromJSON(*CalleeObj);
+ if (!ExpectedId) {
+ return ErrorBuilder::wrap(ExpectedId.takeError())
+ .context(ReadingFromIndex, "EntityId", Index)
+ .context(ReadingFromField, "VirtualCallees", "virtual_callees")
+ .build();
+ }
+ Result->VirtualCallees.insert(*ExpectedId);
+ }
+
+ const json::Object *DefObj = Obj.getObject("def");
+ if (!DefObj) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ FailedToReadObjectAtField, "SourceLocation",
+ "def", "object")
+ .build();
+ }
+ auto File = DefObj->getString("file");
+ if (!File) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ FailedToReadObjectAtField, "File", "file",
+ "string")
+ .context(ReadingFromField, "SourceLocation", "def")
+ .build();
+ }
+ auto Line = DefObj->getInteger("line");
+ if (!Line) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ FailedToReadObjectAtField, "Line", "line",
+ "number")
+ .context(ReadingFromField, "SourceLocation", "def")
+ .build();
+ }
+ auto Col = DefObj->getInteger("col");
+ if (!Col) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ FailedToReadObjectAtField, "Column", "col",
+ "number")
+ .context(ReadingFromField, "SourceLocation", "def")
+ .build();
+ }
+ Result->Definition = {
+ File->str(),
+ static_cast<unsigned>(*Line),
+ static_cast<unsigned>(*Col),
+ };
+
+ return std::move(Result);
+}
+
+namespace {
+struct CallGraphJSONFormatInfo final : JSONFormat::FormatInfo {
+ CallGraphJSONFormatInfo()
+ : JSONFormat::FormatInfo(SummaryName(CallGraphSummary::Name.str()),
+ serialize, deserialize) {}
+};
+} // namespace
+
+static llvm::Registry<JSONFormat::FormatInfo>::Add<CallGraphJSONFormatInfo>
+ RegisterFormatInfo(CallGraphSummary::Name,
+ "JSON Format info for CallGraph summary");
+
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int CallGraphJSONFormatAnchorSource = 0;
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
new file mode 100644
index 0000000000000..eb8dfdc5d9ace
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.cpp
@@ -0,0 +1,366 @@
+//===- EntityPointerLevel.cpp -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "SSAFAnalysesCommon.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include <optional>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace clang::ssaf {
+// Translate a pointer type expression 'E' to a (set of) EntityPointerLevel(s)
+// associated with the declared type of the base address of `E`. If the base
+// address of `E` is not associated with an entity, the translation result is an
+// empty set.
+//
+// The translation is a process of traversing into the pointer 'E' until its
+// base address can be represented by an entity, with the number of dereferences
+// tracked by incrementing the pointer level. Naturally, taking address of, as
+// the inverse operation of dereference, is tracked by decrementing the pointer
+// level.
+//
+// For example, suppose there are pointers and arrays declared as
+// int *ptr, **p1, **p2;
+// int arr[10][10];
+// , the translation of expressions involving these base addresses will be:
+// Translate(ptr + 5) -> {(ptr, 1)}
+// Translate(arr[5]) -> {(arr, 2)}
+// Translate(cond ? p1[5] : p2) -> {(p1, 2), (p2, 1)}
+// Translate(&arr[5]) -> {(arr, 1)}
+class EntityPointerLevelTranslator
+ : ConstStmtVisitor<EntityPointerLevelTranslator,
+ Expected<EntityPointerLevelSet>> {
+ friend class StmtVisitorBase;
+
+ // Fallback method for all unsupported expression kind:
+ Expected<EntityPointerLevelSet> fallback(const Stmt *S) {
+ // Report an error/warning (at least in debug mode) for any unsupported kind
+ // of pointer/array typed expression, because we want to understand every
+ // pointer/array expression. But for non-pointer/array typed expressions, we
+ // could silently ignore unsupported kinds. This translator visits
+ // non-pointer/array typed expressions because of address-of expressions.
+ if (const Expr *E = dyn_cast<Expr>(S); E && hasPtrOrArrType(E))
+ return makeErrAtNode(Ctx, E,
+ "attempt to translate %s to EntityPointerLevels",
+ E->getStmtClassName());
+ return EntityPointerLevelSet{};
+ }
+
+ Expected<EntityPointerLevel>
+ createEntityPointerLevelFor(const NamedDecl *ND) {
+ std::optional<EntityId> Id = Extractor.addEntity(ND);
+ if (!Id)
+ return makeErrAtNode(Ctx, ND, "failed to create EntityId for %s",
+ ND->getDeclKindName());
+ return EntityPointerLevel{buildEntityPointerLevel(*Id, 1)};
+ }
+
+ Expected<EntityPointerLevel>
+ createEntityPointerLevelForReturn(const FunctionDecl *FD) {
+ std::optional<EntityId> Id = Extractor.addEntityForReturn(FD);
+ if (!Id) {
+ return makeErrAtNode(Ctx, FD, "failed to create EntityId for function %s",
+ cast<NamedDecl>(FD)->getNameAsString().c_str());
+ }
+ return EntityPointerLevel{buildEntityPointerLevel(*Id, 1)};
+ }
+
+ // The common helper function for Translate(*base):
+ // Translate(*base) -> Translate(base) with .pointerLevel + 1
+ Expected<EntityPointerLevelSet> translateDereferencePointer(const Expr *Ptr) {
+ assert(hasPtrOrArrType(Ptr));
+
+ Expected<EntityPointerLevelSet> SubResult = Visit(Ptr);
+ if (!SubResult)
+ return SubResult.takeError();
+
+ auto Incremented = llvm::map_range(*SubResult, incrementPointerLevel);
+ return EntityPointerLevelSet{Incremented.begin(), Incremented.end()};
+ }
+
+ TUSummaryExtractor &Extractor;
+ ASTContext &Ctx;
+
+public:
+ EntityPointerLevelTranslator(TUSummaryExtractor &Extractor, ASTContext &Ctx)
+ : Extractor(Extractor), Ctx(Ctx) {}
+
+ Expected<EntityPointerLevelSet> translate(const Expr *E) { return Visit(E); }
+ Expected<EntityPointerLevel> translate(const NamedDecl *D, bool IsRet) {
+ if (!IsRet)
+ return createEntityPointerLevelFor(D);
+
+ if (const auto *FD = dyn_cast<FunctionDecl>(D))
+ return createEntityPointerLevelForReturn(FD);
+
+ return makeErrAtNode(Ctx, D, "attempt to get entity for return of %s",
+ D->getDeclKindName());
+ }
+
+ static EntityPointerLevel incrementPointerLevel(const EntityPointerLevel &E) {
+ return EntityPointerLevel({E.getEntity(), E.getPointerLevel() + 1});
+ }
+
+ static EntityPointerLevel decrementPointerLevel(const EntityPointerLevel &E) {
+ assert(E.getPointerLevel() > 0);
+ return EntityPointerLevel({E.getEntity(), E.getPointerLevel() - 1});
+ }
+
+private:
+ Expected<EntityPointerLevelSet> VisitStmt(const Stmt *E) {
+ return fallback(E);
+ }
+
+ // Translate(base + x) -> Translate(base)
+ // Translate(x + base) -> Translate(base)
+ // Translate(base - x) -> Translate(base)
+ // Translate(base {+=, -=, =} x) -> Translate(base)
+ // Translate(x, base) -> Translate(base)
+ Expected<EntityPointerLevelSet> VisitBinaryOperator(const BinaryOperator *E) {
+ switch (E->getOpcode()) {
+ case clang::BO_Add:
+ if (hasPtrOrArrType(E->getLHS()))
+ return Visit(E->getLHS());
+ return Visit(E->getRHS());
+ case clang::BO_Sub:
+ case clang::BO_AddAssign:
+ case clang::BO_SubAssign:
+ case clang::BO_Assign:
+ return Visit(E->getLHS());
+ case clang::BO_Comma:
+ return Visit(E->getRHS());
+ default:
+ return fallback(E);
+ }
+ }
+
+ // Translate({++, --}base) -> Translate(base)
+ // Translate(base{++, --}) -> Translate(base)
+ // Translate(*base) -> Translate(base) with .pointerLevel += 1
+ // Translate(&base) -> {}, if Translate(base) is {}
+ // -> Translate(base) with .pointerLevel -= 1
+ // Translate(+base) -> Translate(base)
+ Expected<EntityPointerLevelSet> VisitUnaryOperator(const UnaryOperator *E) {
+ switch (E->getOpcode()) {
+ case clang::UO_PostInc:
+ case clang::UO_PostDec:
+ case clang::UO_PreInc:
+ case clang::UO_PreDec:
+ return Visit(E->getSubExpr());
+ case clang::UO_AddrOf: {
+ Expected<EntityPointerLevelSet> SubResult = Visit(E->getSubExpr());
+ if (!SubResult)
+ return SubResult.takeError();
+
+ auto Decremented = llvm::map_range(*SubResult, decrementPointerLevel);
+ return EntityPointerLevelSet{Decremented.begin(), Decremented.end()};
+ }
+ case clang::UO_Deref:
+ return translateDereferencePointer(E->getSubExpr());
+ case clang::UO_Plus:
+ return Visit(E->getSubExpr());
+ default:
+ return fallback(E);
+ }
+ }
+
+ // Translate((T*)base) -> Translate(base) if base has pointer type
+ // -> {} otherwise
+ Expected<EntityPointerLevelSet> VisitCastExpr(const CastExpr *E) {
+ if (hasPtrOrArrType(E->getSubExpr()))
+ return Visit(E->getSubExpr());
+ return EntityPointerLevelSet{};
+ }
+
+ // Translate(f(...)) -> {} if it is an indirect call
+ // -> {(f_return, 1)}, otherwise
+ Expected<EntityPointerLevelSet> VisitCallExpr(const CallExpr *E) {
+ if (auto *FD = E->getDirectCallee()) {
+ if (auto ReturnId = Extractor.addEntityForReturn(FD))
+ return EntityPointerLevelSet{buildEntityPointerLevel(*ReturnId, 1)};
+ }
+ return EntityPointerLevelSet{};
+ }
+
+ // Translate(base[x]) -> Translate(*base)
+ Expected<EntityPointerLevelSet>
+ VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
+ return translateDereferencePointer(E->getBase());
+ }
+
+ // Translate(cond ? base1 : base2) := Translate(base1) U Translate(base2)
+ Expected<EntityPointerLevelSet>
+ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
+ Expected<EntityPointerLevelSet> ReT = Visit(E->getTrueExpr());
+ Expected<EntityPointerLevelSet> ReF = Visit(E->getFalseExpr());
+
+ if (ReT && ReF) {
+ ReT->insert(ReF->begin(), ReF->end());
+ return ReT;
+ }
+ if (!ReF && !ReT)
+ return llvm::joinErrors(ReT.takeError(), ReF.takeError());
+ if (!ReF)
+ return ReF.takeError();
+ return ReT.takeError();
+ }
+
+ Expected<EntityPointerLevelSet> VisitParenExpr(const ParenExpr *E) {
+ return Visit(E->getSubExpr());
+ }
+
+ // Translate("string-literal") -> {} // no entity involved
+ Expected<EntityPointerLevelSet> VisitStringLiteral(const StringLiteral *E) {
+ return EntityPointerLevelSet{};
+ }
+
+ // Translate(predefined-expr) -> {} // treated the same as string literals
+ Expected<EntityPointerLevelSet> VisitPredefinedExpr(const PredefinedExpr *E) {
+ return EntityPointerLevelSet{};
+ }
+
+ // Translate(integer-literal) -> {} // no entity involved
+ Expected<EntityPointerLevelSet> VisitIntegerLiteral(const IntegerLiteral *E) {
+ return EntityPointerLevelSet{};
+ }
+
+ // Translate(DRE) -> {(Decl, 1)}
+ Expected<EntityPointerLevelSet> VisitDeclRefExpr(const DeclRefExpr *E) {
+ auto Res = createEntityPointerLevelFor(E->getDecl());
+ if (!Res)
+ return Res.takeError();
+ return EntityPointerLevelSet{*Res};
+ }
+
+ // Translate({., ->}f) -> {(MemberDecl, 1)}
+ Expected<EntityPointerLevelSet> VisitMemberExpr(const MemberExpr *E) {
+ auto Res = createEntityPointerLevelFor(E->getMemberDecl());
+ if (!Res)
+ return Res.takeError();
+ return EntityPointerLevelSet{*Res};
+ }
+
+ // Unwrap CXXDefaultArgExpr
+ Expected<EntityPointerLevelSet>
+ VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {
+ return Visit(E->getExpr());
+ }
+
+ // Unwrap OpaqueValueExpr
+ Expected<EntityPointerLevelSet>
+ VisitOpaqueValueExpr(const OpaqueValueExpr *S) {
+ return Visit(S->getSourceExpr());
+ }
+
+ // Unwrap ExprWithCleanups
+ Expected<EntityPointerLevelSet>
+ VisitExprWithCleanups(const ExprWithCleanups *S) {
+ return Visit(S->getSubExpr());
+ }
+
+ // Unwrap MaterializeTemporaryExpr
+ Expected<EntityPointerLevelSet>
+ VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *S) {
+ return Visit(S->getSubExpr());
+ }
+
+ // Unwrap CXXDefaultInitExpr
+ Expected<EntityPointerLevelSet>
+ VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
+ return Visit(E->getExpr());
+ }
+
+ // Translate(`nullptr`) -> {}
+ Expected<EntityPointerLevelSet>
+ VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *S) {
+ return EntityPointerLevelSet{};
+ }
+
+ // Translate(`this`) -> {}
+ Expected<EntityPointerLevelSet> VisitCXXThisExpr(const CXXThisExpr *S) {
+ return EntityPointerLevelSet{};
+ }
+
+ // Translate(`new`/`new [*]`) -> {}
+ Expected<EntityPointerLevelSet> VisitCXXNewExpr(const CXXNewExpr *S) {
+ return EntityPointerLevelSet{};
+ }
+
+ // ImplicitValueInitExpr, for raw pointer type,
+ // evaluates to a compile-time constant zero (or null). So no EPL in the
+ // result.
+ Expected<EntityPointerLevelSet>
+ VisitImplicitValueInitExpr(const ImplicitValueInitExpr *S) {
+ return EntityPointerLevelSet{};
+ }
+
+ // The InitListExpr must be an empty or singleton list that
+ // initializes a pointer scalar. Other cases are unexpected thus an error.
+ Expected<EntityPointerLevelSet> VisitInitListExpr(const InitListExpr *E) {
+ if (E->getNumInits() < 1)
+ return EntityPointerLevelSet{};
+ if (E->getType()->isPointerType())
+ return Visit(E->getInit(0));
+ return llvm::createStringError(
+ "Cannot translate an InitListExpr to EntityPointerLevels if it is not "
+ "an empty or singleton list that initializes a pointer scalar");
+ }
+
+ // Clang may default initializes an array with a CXXConstructExpr. Fallback on
+ // other cases, if they exist.
+ // When a CXXConstructExpr has an array type, clang is initializing an array
+ // of class-type objects with default values. In this case, no entity is
+ // associated with the initializer.
+ Expected<EntityPointerLevelSet>
+ VisitCXXConstructExpr(const CXXConstructExpr *E) {
+ if (E->getType()->isArrayType()) {
+ return EntityPointerLevelSet{};
+ }
+ return fallback(E);
+ }
+
+ // No entity is associated with a CXXScalarValueInitExpr:
+ Expected<EntityPointerLevelSet>
+ VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr *E) {
+ return EntityPointerLevelSet{};
+ }
+};
+} // namespace clang::ssaf
+
+Expected<EntityPointerLevelSet>
+clang::ssaf::translateEntityPointerLevel(const Expr *E, ASTContext &Ctx,
+ TUSummaryExtractor &Extractor) {
+ EntityPointerLevelTranslator Translator(Extractor, Ctx);
+
+ return Translator.translate(E);
+}
+
+/// Create an EntityPointerLevel from a ValueDecl of a pointer type.
+Expected<EntityPointerLevel> clang::ssaf::createEntityPointerLevel(
+ const NamedDecl *ND, TUSummaryExtractor &Extractor, bool IsFunRet) {
+ EntityPointerLevelTranslator Translator(Extractor, ND->getASTContext());
+
+ return Translator.translate(ND, IsFunRet);
+}
+
+EntityPointerLevel
+clang::ssaf::incrementPointerLevel(const EntityPointerLevel &E) {
+ return EntityPointerLevelTranslator::incrementPointerLevel(E);
+}
+
+EntityPointerLevel clang::ssaf::buildEntityPointerLevel(EntityId Id,
+ unsigned PtrLv) {
+ return EntityPointerLevel({Id, PtrLv});
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.cpp
new file mode 100644
index 0000000000000..db417195ceb0a
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.cpp
@@ -0,0 +1,134 @@
+//===- EntityPointerLevelFormat.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
+#include "SSAFAnalysesCommon.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
+
+using namespace clang;
+using namespace ssaf;
+
+// Writes an EntityPointerLevel as
+// Array [
+// Object { "@" : [entity-id]},
+// [pointer-level-integer]
+// ]
+llvm::json::Value clang::ssaf::entityPointerLevelToJSON(
+ const EntityPointerLevel &EPL, JSONFormat::EntityIdToJSONFn EntityId2JSON) {
+ return llvm::json::Array{EntityId2JSON(EPL.getEntity()),
+ llvm::json::Value(EPL.getPointerLevel())};
+}
+
+llvm::Expected<EntityPointerLevel> clang::ssaf::entityPointerLevelFromJSON(
+ const llvm::json::Value &EPLData,
+ JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
+ auto *AsArr = EPLData.getAsArray();
+
+ if (!AsArr || AsArr->size() != 2)
+ return makeSawButExpectedError(
+ EPLData, "an array with exactly two elements representing "
+ "EntityId and PointerLevel, respectively");
+
+ auto *EntityIdObj = (*AsArr)[0].getAsObject();
+
+ if (!EntityIdObj)
+ return makeSawButExpectedError((*AsArr)[0],
+ "an object representing EntityId");
+
+ llvm::Expected<EntityId> Id = EntityIdFromJSON(*EntityIdObj);
+
+ if (!Id)
+ return Id.takeError();
+
+ std::optional<uint64_t> PtrLv = (*AsArr)[1].getAsInteger();
+
+ if (!PtrLv)
+ return makeSawButExpectedError((*AsArr)[1],
+ "an integer representing PointerLevel");
+
+ return buildEntityPointerLevel(*Id, *PtrLv);
+}
+
+llvm::json::Array clang::ssaf::entityPointerLevelSetToJSON(
+ llvm::iterator_range<EntityPointerLevelSet::const_iterator> EPLs,
+ JSONFormat::EntityIdToJSONFn EntityId2JSON) {
+ llvm::json::Array Result;
+
+ for (const auto &EPL : EPLs)
+ Result.push_back(entityPointerLevelToJSON(EPL, EntityId2JSON));
+ return Result;
+}
+
+Expected<EntityPointerLevelSet> clang::ssaf::entityPointerLevelSetFromJSON(
+ const llvm::json::Array &EPLsData,
+ JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
+ EntityPointerLevelSet EPLs;
+
+ for (const auto &EltData : EPLsData) {
+ llvm::Expected<EntityPointerLevel> EPL =
+ entityPointerLevelFromJSON(EltData, EntityIdFromJSON);
+
+ if (!EPL)
+ return EPL.takeError();
+ EPLs.insert(*EPL);
+ }
+ return EPLs;
+}
+
+llvm::json::Array clang::ssaf::entityPointerLevelMapToJSON(
+ const std::map<EntityId, EntityPointerLevelSet> &Map,
+ JSONFormat::EntityIdToJSONFn IdToJSON) {
+ llvm::json::Array Content;
+
+ for (const auto &[Id, EPLs] : Map) {
+ Content.push_back(IdToJSON(Id));
+ Content.push_back(entityPointerLevelSetToJSON(EPLs, IdToJSON));
+ }
+ return Content;
+}
+
+Expected<std::map<EntityId, EntityPointerLevelSet>>
+clang::ssaf::entityPointerLevelMapFromJSON(
+ const llvm::json::Array &Content,
+ JSONFormat::EntityIdFromJSONFn IdFromJSON) {
+ if (Content.size() % 2 != 0)
+ return makeSawButExpectedError(Content,
+ "an even number of elements, got %lu",
+ static_cast<size_t>(Content.size()));
+
+ std::map<EntityId, EntityPointerLevelSet> Result;
+
+ for (size_t I = 0; I < Content.size(); I += 2) {
+ const llvm::json::Object *IdData = Content[I].getAsObject();
+
+ if (!IdData)
+ return makeSawButExpectedError(Content[I],
+ "an object representing EntityId");
+
+ auto Id = IdFromJSON(*IdData);
+
+ if (!Id)
+ return Id.takeError();
+
+ const llvm::json::Array *EPLsData = Content[I + 1].getAsArray();
+
+ if (!EPLsData)
+ return makeSawButExpectedError(
+ Content[I + 1], "an array representing EntityPointerLevelSet");
+
+ auto EPLs = entityPointerLevelSetFromJSON(*EPLsData, IdFromJSON);
+
+ if (!EPLs)
+ return EPLs.takeError();
+ Result[*Id] = std::move(*EPLs);
+ }
+ return Result;
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.cpp
new file mode 100644
index 0000000000000..9f90f562c1294
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.cpp
@@ -0,0 +1,22 @@
+//===- PointerFlow.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h"
+
+using namespace clang;
+using namespace ssaf;
+
+ssaf::PointerFlowEntitySummary
+ssaf::buildPointerFlowEntitySummary(EdgeSet Edges) {
+ return PointerFlowEntitySummary(std::move(Edges));
+}
+
+llvm::iterator_range<EdgeSet::const_iterator>
+ssaf::getEdges(const PointerFlowEntitySummary &Sum) {
+ return Sum.Edges;
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.cpp
new file mode 100644
index 0000000000000..bb68bb4353536
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.cpp
@@ -0,0 +1,122 @@
+//===- PointerFlowAnalysis.cpp - WPA for PointerFlow ----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.h"
+#include "SSAFAnalysesCommon.h"
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h"
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
+#include <memory>
+
+using namespace clang::ssaf;
+using namespace llvm;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+// PointerFlowAnalysis---converts PointerFlowEntitySummary(s) in an LUSummary to
+// a PointerFlowAnalysisResult
+//===----------------------------------------------------------------------===//
+
+// Serialized as a flat array of alternating [EntityId, EdgesArray, ...] pairs.
+json::Object
+serializePointerFlowAnalysisResult(const PointerFlowAnalysisResult &R,
+ JSONFormat::EntityIdToJSONFn IdToJSON) {
+ json::Array Content;
+
+ for (const auto &[Id, EntityEdges] : R.Edges) {
+ Content.push_back(IdToJSON(Id));
+ Content.push_back(json::Value(edgeSetToJSON(EntityEdges, IdToJSON)));
+ }
+
+ json::Object Result;
+
+ Result[PointerFlowAnalysisResultName] = std::move(Content);
+ return Result;
+}
+
+Expected<std::unique_ptr<AnalysisResult>> deserializePointerFlowAnalysisResult(
+ const json::Object &Obj, JSONFormat::EntityIdFromJSONFn IdFromJSON) {
+ const json::Array *Content = Obj.getArray(PointerFlowAnalysisResultName);
+
+ if (!Content)
+ return makeSawButExpectedError(Obj, "an object with a key %s",
+ PointerFlowAnalysisResultName.data());
+
+ if (Content->size() % 2 != 0)
+ return makeSawButExpectedError(*Content,
+ "an even number of elements, got %lu",
+ static_cast<size_t>(Content->size()));
+
+ std::map<EntityId, EdgeSet> Edges;
+
+ for (size_t I = 0; I < Content->size(); I += 2) {
+ const json::Object *IdData = (*Content)[I].getAsObject();
+
+ if (!IdData)
+ return makeSawButExpectedError((*Content)[I],
+ "an object representing EntityId");
+
+ auto Id = IdFromJSON(*IdData);
+
+ if (!Id)
+ return Id.takeError();
+
+ const json::Array *EdgesData = (*Content)[I + 1].getAsArray();
+
+ if (!EdgesData)
+ return makeSawButExpectedError((*Content)[I + 1],
+ "an array of arrays representing EdgeSet");
+
+ auto EntityEdges = edgeSetFromJSON(*EdgesData, IdFromJSON);
+
+ if (!EntityEdges)
+ return EntityEdges.takeError();
+ Edges[*Id] = std::move(*EntityEdges);
+ }
+
+ auto Ret = std::make_unique<PointerFlowAnalysisResult>();
+
+ Ret->Edges = std::move(Edges);
+ return Ret;
+}
+
+JSONFormat::AnalysisResultRegistry::Add<PointerFlowAnalysisResult>
+ RegisterPointerFlowResultForJSON(serializePointerFlowAnalysisResult,
+ deserializePointerFlowAnalysisResult);
+
+class PointerFlowAnalysis final
+ : public SummaryAnalysis<PointerFlowAnalysisResult,
+ PointerFlowEntitySummary> {
+public:
+ llvm::Error add(EntityId Id,
+ const PointerFlowEntitySummary &Summary) override {
+ auto EdgesOfEntity = getEdges(Summary);
+
+ getResult().Edges[Id] = EdgeSet(EdgesOfEntity.begin(), EdgesOfEntity.end());
+ return llvm::Error::success();
+ }
+};
+
+AnalysisRegistry::Add<PointerFlowAnalysis>
+ RegisterPointerFlowAnalysis("Whole-program pointer flow analysis");
+
+} // namespace
+
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int PointerFlowAnalysisAnchorSource = 0;
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp
new file mode 100644
index 0000000000000..27918ca930a11
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowExtractor.cpp
@@ -0,0 +1,372 @@
+//===- PointerFlowExtractor.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SSAFAnalysesCommon.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/TypeBase.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/ADT/Sequence.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
+#include <memory>
+#include <optional>
+
+namespace clang::ssaf {
+extern PointerFlowEntitySummary buildPointerFlowEntitySummary(EdgeSet Edges);
+} // namespace clang::ssaf
+
+namespace {
+using namespace clang;
+using namespace ssaf;
+
+class PointerFlowMatcher {
+public:
+ EdgeSet Results;
+ ASTContext &Ctx;
+ TUSummaryExtractor &Extractor;
+
+ PointerFlowMatcher(ASTContext &Ctx, TUSummaryExtractor &Extractor)
+ : Ctx(Ctx), Extractor(Extractor) {}
+
+ llvm::Error matches(const DynTypedNode &DynNode, const NamedDecl *RootDecl);
+
+ llvm::Error matchesInitializerList(const ValueDecl *Base,
+ const Expr *InitExpr,
+ unsigned ArrayElementIndirectLevel = 0);
+
+ llvm::Error matchesStmt(const Stmt *S, const NamedDecl *RootDecl);
+
+ llvm::Error matchesDecl(const Decl *D, const NamedDecl *RootDecl);
+
+private:
+ std::function<EntityId(const EntityName &)> AddEntity;
+
+ Expected<EntityPointerLevelSet> toEPL(const NamedDecl *N,
+ bool IsRet = false) const;
+
+ Expected<EntityPointerLevelSet> toEPL(const Expr *N) const;
+
+ llvm::Error addEdges(Expected<EntityPointerLevelSet> &&LHS,
+ Expected<EntityPointerLevelSet> &&RHS);
+
+ template <typename ParmsProvider, typename ArgsProvider>
+ llvm::Error matchesArgsWithParams(unsigned ArgIdxStart, ParmsProvider *PP,
+ ArgsProvider *AP) {
+ unsigned ArgIdx = ArgIdxStart;
+
+ for (unsigned ParmIdx = 0;
+ ParmIdx < PP->getNumParams() && ArgIdx < AP->getNumArgs();
+ ++ArgIdx, ++ParmIdx) {
+ if (const ParmVarDecl *PD = PP->getParamDecl(ParmIdx);
+ PD && hasPtrOrArrType(PD)) {
+ if (auto Err = addEdges(toEPL(PD), toEPL(AP->getArg(ArgIdx))))
+ return Err;
+ }
+ }
+ return llvm::Error::success();
+ }
+};
+
+Expected<EntityPointerLevelSet> PointerFlowMatcher::toEPL(const NamedDecl *N,
+ bool IsRet) const {
+ auto Ret = createEntityPointerLevel(N, Extractor, IsRet);
+
+ if (Ret)
+ return EntityPointerLevelSet{*Ret};
+ return Ret.takeError();
+}
+
+Expected<EntityPointerLevelSet> PointerFlowMatcher::toEPL(const Expr *N) const {
+ return translateEntityPointerLevel(N, Ctx, Extractor);
+}
+
+llvm::Error
+PointerFlowMatcher::addEdges(Expected<EntityPointerLevelSet> &&LHS,
+ Expected<EntityPointerLevelSet> &&RHS) {
+ if (!LHS && !RHS)
+ return llvm::joinErrors(LHS.takeError(), RHS.takeError());
+ if (!LHS)
+ return LHS.takeError();
+ if (!RHS)
+ return RHS.takeError();
+ if (RHS->empty())
+ return llvm::Error::success();
+ for (auto L : *LHS)
+ Results[L].insert(RHS->begin(), RHS->end());
+ return llvm::Error::success();
+}
+
+/// Match and extract pointer flow.
+/// The extraction function 'XF' can be described by the following rules:
+///
+/// XF(l = r) := add edge "toEPL(l) -> toEPL(r))"
+/// XF(foo(a, b, ...)) := XF(Param_1 = a), XF(Param_2 = b), ...
+/// XF(return e;) := XF(FunRet = e), where 'FunRet' is the return
+/// entity of the enclosing
+/// function
+/// XF(ctor(a, ...) : x1(y1), ... {...})
+/// := XF(Param_1 = a), ...,
+/// XF(x1 = y1), ...,
+/// ctor's body will be visited separately.
+/// XF(T var = e) := XF(var = e)
+/// XF(T var = init-list) := see \ref
+/// PointerFlowMatcher::matchInitializerList
+llvm::Error PointerFlowMatcher::matches(const DynTypedNode &DynNode,
+ const NamedDecl *RootDecl) {
+ if (const Stmt *S = DynNode.get<Stmt>())
+ return matchesStmt(S, RootDecl);
+ if (const Decl *D = DynNode.get<Decl>())
+ return matchesDecl(D, RootDecl);
+ return llvm::Error::success();
+}
+
+llvm::Error PointerFlowMatcher::matchesStmt(const Stmt *S,
+ const NamedDecl *RootDecl) {
+ // Match 'p = q' whenever it has pointer or array type:
+ if (const auto *BO = dyn_cast<BinaryOperator>(S);
+ BO && BO->getOpcode() == BO_Assign && hasPtrOrArrType(BO)) {
+ return addEdges(toEPL(BO->getLHS()), toEPL(BO->getRHS()));
+ }
+
+ // Match arg-to-param passing (in CallExpr) for any pointer type argument:
+ if (const auto *CE = dyn_cast<CallExpr>(S)) {
+ const FunctionDecl *FD = CE->getDirectCallee();
+
+ if (!FD)
+ return llvm::Error::success();
+
+ unsigned ArgIdx = 0;
+
+ if (isa<CXXOperatorCallExpr>(CE))
+ if (auto *MD = dyn_cast<CXXMethodDecl>(FD);
+ MD && !MD->isExplicitObjectMemberFunction())
+ ArgIdx = 1;
+ return matchesArgsWithParams(ArgIdx, FD, CE);
+ }
+ // Match arg-to-param passing (in CXXConstructExpr) for any pointer type
+ // argument:
+ if (const auto *CCE = dyn_cast<CXXConstructExpr>(S)) {
+ return matchesArgsWithParams(/*ArgIdxStart=*/0, CCE->getConstructor(), CCE);
+ }
+ if (const auto *RS = dyn_cast<ReturnStmt>(S)) {
+ const Expr *RetExpr = RS->getRetValue();
+ if (!RetExpr || !hasPtrOrArrType(RetExpr))
+ return llvm::Error::success();
+ return addEdges(toEPL(RootDecl, true), toEPL(RetExpr));
+ }
+ return llvm::Error::success();
+}
+
+llvm::Error PointerFlowMatcher::matchesDecl(const Decl *D,
+ const NamedDecl *RootDecl) {
+ const Expr *InitExpr = nullptr;
+
+ if (const auto *VD = dyn_cast<ValueDecl>(D)) {
+ if (const auto *Var = dyn_cast<VarDecl>(VD))
+ InitExpr = Var->getInit();
+ if (const auto *Fd = dyn_cast<FieldDecl>(VD))
+ InitExpr = Fd->getInClassInitializer();
+
+ // Match initializer-list:
+ if (auto *InitLst = dyn_cast_or_null<InitListExpr>(InitExpr))
+ return matchesInitializerList(VD, InitLst);
+
+ // Match initializers to variables/fields of a pointer type:
+ if (InitExpr && hasPtrOrArrType(VD))
+ return addEdges(toEPL(VD), toEPL(InitExpr));
+ }
+
+ // Match C++ constructor member-initializers:
+ if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D)) {
+ for (auto *E : CtorD->inits()) {
+ if (E->isDelegatingInitializer())
+ return matches(DynTypedNode::create(*E->getInit()), RootDecl);
+ if (const FieldDecl *FD = E->getMember(); FD && hasPtrOrArrType(FD)) {
+ if (auto Err = addEdges(toEPL(E->getMember()), toEPL(E->getInit())))
+ return Err;
+ }
+ }
+ }
+ return llvm::Error::success();
+}
+
+// Helper function for matchInitializerList that handles record:
+llvm::Error matchInitializerListForRecordDecl(PointerFlowMatcher &Matcher,
+ const RecordDecl *RecordTy,
+ const InitListExpr *ILE) {
+ if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RecordTy))
+ if (CXXRD->getNumBases() != 0) {
+ // FIXME: support this:
+ return makeErrAtNode(
+ Matcher.Ctx, ILE,
+ "attempt to create pointer assignment edges between "
+ "CXXRecordDecls with base classes and initializer-lists");
+ }
+ // Handle union:
+ if (RecordTy->isUnion()) {
+ auto *InitField = ILE->getInitializedFieldInUnion();
+
+ if (!InitField || ILE->inits().empty())
+ return llvm::Error::success();
+ return Matcher.matchesInitializerList(InitField, ILE->getInit(0));
+ }
+ // Handle struct/class:
+ ILE = ILE->isSemanticForm() ? ILE : ILE->getSemanticForm();
+
+ auto FieldIter = RecordTy->field_begin();
+
+ assert(RecordTy->getNumFields() >= ILE->getNumInits());
+ for (auto *Init : ILE->inits())
+ if (auto Err = Matcher.matchesInitializerList(*(FieldIter++), Init))
+ return Err;
+ return llvm::Error::success();
+}
+
+// Helper function for matchInitializerList that handles array:
+llvm::Error matchInitializerListForArray(PointerFlowMatcher &Matcher,
+ const ValueDecl *Array,
+ const InitListExpr *ILE,
+ unsigned ArrayIndirectLevel = 0) {
+ for (auto *E : ILE->inits())
+ if (auto Err =
+ Matcher.matchesInitializerList(Array, E, ArrayIndirectLevel + 1))
+ return Err;
+ return llvm::Error::success();
+}
+
+/// Match initializer lists of the form 'Var = {a, b, c, ...}':
+///
+/// If 'Var' is a struct/union:
+/// XF(Var = {a, b, c, ...}) := XF(Var.field_1 = a)
+/// XF(Var.field_2 = b)
+/// ...
+/// If 'Var' is an array:
+/// XF(Var = {a, b, c, ...}) := XF(*Var = a)
+/// XF(*Var = b)
+/// ...
+///
+/// The process is recursive: 'a', 'b', 'c', ... may themselves be
+/// initializer lists. We therefore use \p ArrayElementIndirectLevel to keep
+/// track of the pointer level the left-hand side.
+llvm::Error
+PointerFlowMatcher::matchesInitializerList(const ValueDecl *Base,
+ const Expr *InitExpr,
+ unsigned ArrayElementIndirectLevel) {
+ const InitListExpr *ILE = dyn_cast<InitListExpr>(InitExpr);
+
+ if (!ILE) {
+ if (!hasPtrOrArrType(InitExpr))
+ return llvm::Error::success();
+
+ auto BaseEPL = toEPL(Base);
+
+ if (!BaseEPL)
+ return BaseEPL.takeError();
+
+ // Apply ArrayElementIndirectLevel to BaseEPL
+ auto R = llvm::map_range(*BaseEPL, [&ArrayElementIndirectLevel](
+ const EntityPointerLevel &EPL) {
+ EntityPointerLevel Result = EPL;
+ for ([[maybe_unused]] auto Ignored : llvm::seq(ArrayElementIndirectLevel))
+ Result = incrementPointerLevel(Result);
+ return Result;
+ });
+ return addEdges(EntityPointerLevelSet{R.begin(), R.end()}, toEPL(InitExpr));
+ }
+ // Note that `Base`'s type is NOT the real LHS type when
+ // ArrayElementIndirectLevel > 0:
+ QualType Type = InitExpr->getType();
+
+ if (auto *RD = Type->getAsRecordDecl())
+ return matchInitializerListForRecordDecl(*this, RD, ILE);
+ if (Type->isArrayType())
+ return matchInitializerListForArray(*this, Base, ILE,
+ ArrayElementIndirectLevel);
+
+ // Must be the case of using a initializer-list for a scalar.
+ // The initializer-list can be either singleton or empty:
+ if (ILE->getNumInits() == 0)
+ return llvm::Error::success();
+ return matchesInitializerList(Base, ILE->getInit(0));
+}
+
+class PointerFlowTUSummaryExtractor : public TUSummaryExtractor {
+public:
+ using TUSummaryExtractor::TUSummaryExtractor;
+
+ /// \return a non-null unique pointer to a PointerFlowEntitySummary
+ std::unique_ptr<PointerFlowEntitySummary>
+ extractEntitySummary(const NamedDecl *Contributor, ASTContext &Ctx,
+ TUSummaryExtractor &Extractor) {
+ PointerFlowMatcher Matcher(Ctx, Extractor);
+ auto MatchAction = [&Matcher, &Contributor](const DynTypedNode &Node) {
+ auto Err = Matcher.matches(Node, Contributor);
+
+ if (Err)
+ logWarningFromError(std::move(Err));
+ };
+
+ findMatchesIn(Contributor, MatchAction);
+ return std::make_unique<PointerFlowEntitySummary>(
+ buildPointerFlowEntitySummary(std::move(Matcher.Results)));
+ }
+
+ void HandleTranslationUnit(ASTContext &Ctx) override {
+ std::vector<const NamedDecl *> Contributors;
+
+ findContributors(Ctx, 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
+ // instantiations.
+ if (CD->isTemplated())
+ continue;
+
+ auto EntitySummary = extractEntitySummary(CD, Ctx, *this);
+
+ assert(EntitySummary);
+ if (EntitySummary->empty())
+ continue;
+
+ std::optional<EntityId> ContributorId = addEntity(CD);
+ if (!ContributorId) {
+ logWarningFromError(makeEntityNameErr(Ctx, CD));
+ continue;
+ }
+
+ [[maybe_unused]] auto [_, InsertionSucceeded] =
+ SummaryBuilder.addSummary(*ContributorId, std::move(EntitySummary));
+
+ assert(InsertionSucceeded && "duplicated contributor extraction");
+ }
+ }
+};
+} // namespace
+
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int PointerFlowExtractorAnchorSource = 0;
+} // namespace clang::ssaf
+
+static TUSummaryExtractorRegistry::Add<PointerFlowTUSummaryExtractor>
+ RegisterExtractor(PointerFlowEntitySummary::Name,
+ "Extract pointer flow information");
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.cpp
new file mode 100644
index 0000000000000..ccad92be9b745
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.cpp
@@ -0,0 +1,132 @@
+//===- PointerFlowFormat.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowFormat.h"
+#include "SSAFAnalysesCommon.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
+
+using namespace clang;
+using namespace ssaf;
+using Object = llvm::json::Object;
+using Array = llvm::json::Array;
+using Value = llvm::json::Value;
+
+ssaf::PointerFlowEntitySummary
+ssaf::buildPointerFlowEntitySummary(EdgeSet Edges);
+
+llvm::iterator_range<EdgeSet::const_iterator>
+ssaf::getEdges(const PointerFlowEntitySummary &Sum);
+
+namespace {
+constexpr const char *const PointerFlowKey = "PointerFlow";
+} // namespace
+
+// Writes an EdgeSet as an array of arrays of EntityPointerLevels:
+// [
+// [ [src-node], [dest-node], [dest-node], ...],
+// [ [src-node], [dest-node], [dest-node], ...],
+// ...
+// ]
+Array clang::ssaf::edgeSetToJSON(
+ llvm::iterator_range<EdgeSet::const_iterator> Edges,
+ JSONFormat::EntityIdToJSONFn EntityId2JSON) {
+ Array EdgesData;
+
+ for (const auto &[LHS, RHSSet] : Edges) {
+ Array EdgeEntry;
+ EdgeEntry.push_back(entityPointerLevelToJSON(LHS, EntityId2JSON));
+ for (const auto &RHS : RHSSet)
+ EdgeEntry.push_back(entityPointerLevelToJSON(RHS, EntityId2JSON));
+ EdgesData.push_back(Value(std::move(EdgeEntry)));
+ }
+ return EdgesData;
+}
+
+llvm::Expected<EdgeSet>
+clang::ssaf::edgeSetFromJSON(const Array &EdgesData,
+ JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
+ EdgeSet Edges;
+
+ for (const auto &EdgesEntryData : EdgesData) {
+ const auto *EPLArray = EdgesEntryData.getAsArray();
+
+ if (!EPLArray || EPLArray->size() <= 1)
+ return makeSawButExpectedError(
+ EdgesEntryData, "a JSON array of EntityPointerLevels with a size "
+ "greater than 1: [src, dest, dest, ...]");
+
+ auto SrcEPL =
+ entityPointerLevelFromJSON(*EPLArray->begin(), EntityIdFromJSON);
+
+ if (!SrcEPL)
+ return SrcEPL.takeError();
+ for (const auto &EPLData :
+ llvm::make_range(EPLArray->begin() + 1, EPLArray->end())) {
+ auto EPL = entityPointerLevelFromJSON(EPLData, EntityIdFromJSON);
+ if (!EPL)
+ return EPL.takeError();
+ Edges[*SrcEPL].insert(*EPL);
+ }
+ }
+ return Edges;
+}
+
+static llvm::json::Object
+summaryToJSON(const EntitySummary &ES,
+ JSONFormat::EntityIdToJSONFn EntityId2JSON) {
+ Object Data;
+ Data[PointerFlowKey] = Value(
+ edgeSetToJSON(getEdges(static_cast<const PointerFlowEntitySummary &>(ES)),
+ EntityId2JSON));
+ return Data;
+}
+
+static llvm::Expected<std::unique_ptr<EntitySummary>>
+summaryFromJSON(const Object &Data, EntityIdTable &,
+ JSONFormat::EntityIdFromJSONFn EntityIdFromJSON) {
+ const Value *EdgesData = Data.get(PointerFlowKey);
+
+ if (!EdgesData)
+ return makeSawButExpectedError(
+ Object(Data), "a JSON object with the key: %s", PointerFlowKey);
+
+ const auto *EdgesDataAsArr = EdgesData->getAsArray();
+
+ if (!EdgesDataAsArr)
+ return makeSawButExpectedError(
+ *EdgesData, "a JSON array of array of EntityPointerLevels");
+
+ auto Edges = edgeSetFromJSON(*EdgesDataAsArr, EntityIdFromJSON);
+
+ if (!Edges)
+ return Edges.takeError();
+ return std::make_unique<PointerFlowEntitySummary>(
+ buildPointerFlowEntitySummary(std::move(*Edges)));
+}
+
+namespace {
+struct PointerFlowJSONFormatInfo final : JSONFormat::FormatInfo {
+ PointerFlowJSONFormatInfo()
+ : JSONFormat::FormatInfo(PointerFlowEntitySummary::summaryName(),
+ summaryToJSON, summaryFromJSON) {}
+};
+} // namespace
+
+static llvm::Registry<JSONFormat::FormatInfo>::Add<PointerFlowJSONFormatInfo>
+ RegisterPointerFlowJSONFormatInfo(
+ "PointerFlow", "JSON Format info for PointerFlowEntitySummary");
+
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int PointerFlowJSONFormatAnchorSource = 0;
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp
new file mode 100644
index 0000000000000..660bc424fb32f
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.cpp
@@ -0,0 +1,145 @@
+//===- SSAFAnalysesCommon.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SSAFAnalysesCommon.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
+#include "clang/AST/ExprCXX.h"
+#include <set>
+
+using namespace clang;
+
+std::string ssaf::describeJSONValue(const llvm::json::Value &V) {
+ return llvm::formatv("{0:2}", V).str();
+}
+
+std::string ssaf::describeJSONValue(const llvm::json::Array &A) {
+ return llvm::formatv("array of size {0}", A.size()).str();
+}
+
+std::string ssaf::describeJSONValue(const llvm::json::Object &O) {
+ return llvm::formatv("an object of {0} key(s)", O.size()).str();
+}
+
+namespace {
+// Traverses the AST and finds contributors.
+class ContributorFinder : public DynamicRecursiveASTVisitor {
+public:
+ std::set<const NamedDecl *> Contributors;
+
+ ContributorFinder() {
+ ShouldVisitTemplateInstantiations = true;
+ ShouldVisitImplicitCode = false;
+ }
+
+ bool VisitFunctionDecl(FunctionDecl *D) override {
+ Contributors.insert(D);
+ return true;
+ }
+
+ bool VisitRecordDecl(RecordDecl *D) override {
+ Contributors.insert(D);
+ return true;
+ }
+
+ bool VisitVarDecl(VarDecl *D) override {
+ DeclContext *DC = D->getDeclContext();
+
+ // Collects Decl for global variables or static data members:
+ if (DC->isFileContext() || D->isStaticDataMember())
+ Contributors.insert(D);
+ return true;
+ }
+
+ bool VisitLambdaExpr(LambdaExpr *L) override {
+ // TraverseLambdaExpr directly visits the body stmt, skipping the
+ // CXXMethodDecl, which is a contributor that needs to be collected.
+ VisitFunctionDecl(L->getCallOperator());
+ return true;
+ }
+};
+
+/// An AST visitor that skips the root node's strict-descendants that are
+/// callable Decls and record Decls, because those are separate contributors.
+///
+/// Clients need to implement their own "MatchAction", which is a function that
+/// takes a `DynTypedNode`, decides if the node matches and performs any further
+/// callback actions.
+/// ContributorFactFinder takes a reference to a "MatchAction". It does not own
+/// the "MatchAction", which is usually stateful and may own containers.
+class ContributorFactFinder : public DynamicRecursiveASTVisitor {
+ llvm::function_ref<void(const DynTypedNode &)> MatchActionRef;
+ const NamedDecl *RootDecl = nullptr;
+
+ template <typename NodeTy> void match(const NodeTy &Node) {
+ MatchActionRef(DynTypedNode::create(Node));
+ }
+
+public:
+ ContributorFactFinder(
+ llvm::function_ref<void(const DynTypedNode &)> MatchActionRef)
+ : MatchActionRef(MatchActionRef) {
+ ShouldVisitTemplateInstantiations = true;
+ ShouldVisitImplicitCode = false;
+ }
+
+ // The entry point:
+ void findMatches(const NamedDecl *Contributor) {
+ RootDecl = Contributor;
+ TraverseDecl(const_cast<NamedDecl *>(Contributor));
+ }
+
+ bool TraverseDecl(Decl *Node) override {
+ if (!Node)
+ return true;
+ // To skip callables:
+ if (Node != RootDecl &&
+ isa<FunctionDecl, BlockDecl, ObjCMethodDecl, RecordDecl>(Node))
+ return true;
+ match(*Node);
+ return DynamicRecursiveASTVisitor::TraverseDecl(Node);
+ }
+
+ bool TraverseStmt(Stmt *Node) override {
+ if (!Node)
+ return true;
+ match(*Node);
+ return DynamicRecursiveASTVisitor::TraverseStmt(Node);
+ }
+
+ bool TraverseLambdaExpr(LambdaExpr *L) override {
+ // TODO: lambda captures of pointer variables (by copy or by reference)
+ // are currently not tracked. Each capture initializes an implicit closure
+ // field from the captured variable, which constitutes a pointer assignment
+ // edge that should be recorded here.
+ return true; // Skip lambda as it is a callable.
+ }
+};
+} // namespace
+
+void ssaf::findContributors(ASTContext &Ctx,
+ std::vector<const NamedDecl *> &Contributors) {
+ ContributorFinder Finder;
+ Finder.TraverseAST(Ctx);
+ Contributors.insert(Contributors.end(), Finder.Contributors.begin(),
+ Finder.Contributors.end());
+}
+
+void ssaf::findMatchesIn(
+ const NamedDecl *Contributor,
+ llvm::function_ref<void(const DynTypedNode &)> MatchActionRef) {
+ ContributorFactFinder{MatchActionRef}.findMatches(Contributor);
+}
+
+llvm::Error clang::ssaf::makeEntityNameErr(clang::ASTContext &Ctx,
+ const clang::NamedDecl *D) {
+ return makeErrAtNode(Ctx, D, "failed to create entity name for %s",
+ D->getNameAsString().data());
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
new file mode 100644
index 0000000000000..a2adb4bc03d87
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/SSAFAnalysesCommon.h
@@ -0,0 +1,82 @@
+//===- SSAFAnalysesCommon.h -------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Common code in SSAF analyses implementations
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_SSAFANALYSESCOMMON_H
+#define LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_SSAFANALYSESCOMMON_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTTypeTraits.h"
+#include "clang/AST/Decl.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang::ssaf {
+///\return a short descriptions of a json::Value
+std::string describeJSONValue(const llvm::json::Value &V);
+///\return a short descriptions of a json::Array
+std::string describeJSONValue(const llvm::json::Array &A);
+///\return a short descriptions of a json::Object
+std::string describeJSONValue(const llvm::json::Object &O);
+
+template <typename NodeTy, typename... Ts>
+llvm::Error makeErrAtNode(clang::ASTContext &Ctx, const NodeTy *N,
+ llvm::StringRef Fmt, const Ts &...Args) {
+ std::string LocStr = N->getBeginLoc().printToString(Ctx.getSourceManager());
+ return llvm::createStringError((Fmt + " at %s").str().c_str(), Args...,
+ LocStr.c_str());
+}
+
+template <typename JSONTy, typename... Ts>
+llvm::Error makeSawButExpectedError(const JSONTy &Saw, llvm::StringRef Expected,
+ const Ts &...ExpectedArgs) {
+ std::string Fmt = ("saw %s but expected " + Expected).str();
+ std::string SawStr = describeJSONValue(Saw);
+
+ return llvm::createStringError(Fmt.c_str(), SawStr.c_str(), ExpectedArgs...);
+}
+
+///\return true iff expression `E` has pointer or array type.
+inline bool hasPtrOrArrType(const Expr *E) {
+ return llvm::isa<clang::PointerType, clang::ArrayType>(
+ E->getType().getCanonicalType());
+}
+
+///\return true iff Decl `D` has (reference-to) pointer or array type.
+inline bool hasPtrOrArrType(const ValueDecl *D) {
+ return llvm::isa<clang::PointerType, clang::ArrayType>(
+ D->getType().getNonReferenceType().getCanonicalType());
+}
+
+llvm::Error makeEntityNameErr(clang::ASTContext &Ctx,
+ const clang::NamedDecl *D);
+
+/// Log a warning from an llvm::Error
+inline void logWarningFromError(llvm::Error Err) {
+ DEBUG_WITH_TYPE("ssaf-analyses", llvm::errs() << Err);
+ llvm::consumeError(std::move(Err));
+}
+
+/// Find all contributors in an AST.
+void findContributors(ASTContext &Ctx,
+ std::vector<const NamedDecl *> &Contributors);
+
+/// Perform "MatchAction" on each Stmt and Decl belonging to the `Contributor`.
+/// \param Contributor
+/// \param MatchActionRef a reference (view) to a "MatchAction"
+void findMatchesIn(
+ const NamedDecl *Contributor,
+ llvm::function_ref<void(const DynTypedNode &)> MatchActionRef);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_SCALABLESTATICANALYSIS_ANALYSES_SSAFANALYSESCOMMON_H
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
new file mode 100644
index 0000000000000..185992efe9977
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.cpp
@@ -0,0 +1,22 @@
+//===- UnsafeBufferUsage.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+
+using namespace clang;
+using namespace ssaf;
+
+UnsafeBufferUsageEntitySummary
+ssaf::buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers) {
+ return UnsafeBufferUsageEntitySummary(std::move(UnsafeBuffers));
+}
+
+llvm::iterator_range<EntityPointerLevelSet::const_iterator>
+ssaf::getUnsafeBuffers(const UnsafeBufferUsageEntitySummary &S) {
+ return llvm::make_range(S.UnsafeBuffers.begin(), S.UnsafeBuffers.end());
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
new file mode 100644
index 0000000000000..f34645ce8449a
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp
@@ -0,0 +1,250 @@
+//===- UnsafeBufferUsageAnalysis.cpp - WPA for UnsafeBufferUsage ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+// UnsafeBufferUsageAnalysis is a noop analysis.
+//
+// UnsafeBufferUsageAnalysisResult is a map from EntityIds to
+// EntityPointerLevelSets
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h"
+#include "SSAFAnalysesCommon.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
+#include <memory>
+
+using namespace clang::ssaf;
+using namespace llvm;
+
+namespace {
+
+json::Object serializeUnsafeBufferUsageAnalysisResult(
+ const UnsafeBufferUsageAnalysisResult &R,
+ JSONFormat::EntityIdToJSONFn IdToJSON) {
+ json::Object Result;
+
+ Result[UnsafeBufferUsageAnalysisResultName] =
+ entityPointerLevelMapToJSON(R.UnsafeBuffers, IdToJSON);
+ return Result;
+}
+
+Expected<std::unique_ptr<AnalysisResult>>
+deserializeUnsafeBufferUsageAnalysisResult(
+ const json::Object &Obj, JSONFormat::EntityIdFromJSONFn IdFromJSON) {
+ const json::Array *Content =
+ Obj.getArray(UnsafeBufferUsageAnalysisResultName);
+
+ if (!Content)
+ return makeSawButExpectedError(Obj, "an object with a key %s",
+ UnsafeBufferUsageAnalysisResultName.data());
+
+ auto UnsafeBuffers = entityPointerLevelMapFromJSON(*Content, IdFromJSON);
+
+ if (!UnsafeBuffers)
+ return UnsafeBuffers.takeError();
+
+ auto Ret = std::make_unique<UnsafeBufferUsageAnalysisResult>();
+
+ Ret->UnsafeBuffers = std::move(*UnsafeBuffers);
+ return Ret;
+}
+
+JSONFormat::AnalysisResultRegistry::Add<UnsafeBufferUsageAnalysisResult>
+ RegisterUnsafeBufferUsageResultForJSON(
+ serializeUnsafeBufferUsageAnalysisResult,
+ deserializeUnsafeBufferUsageAnalysisResult);
+
+class UnsafeBufferUsageAnalysis final
+ : public SummaryAnalysis<UnsafeBufferUsageAnalysisResult,
+ UnsafeBufferUsageEntitySummary> {
+public:
+ llvm::Error add(EntityId Id,
+ const UnsafeBufferUsageEntitySummary &Summary) override {
+ auto UnsafeBuffersOfEntity = getUnsafeBuffers(Summary);
+
+ getResult().UnsafeBuffers[Id] = EntityPointerLevelSet(
+ UnsafeBuffersOfEntity.begin(), UnsafeBuffersOfEntity.end());
+ return llvm::Error::success();
+ }
+};
+
+AnalysisRegistry::Add<UnsafeBufferUsageAnalysis>
+ RegisterUnsafeBufferUsageAnalysis(
+ "Whole-program unsafe buffer usage analysis");
+
+//===----------------------------------------------------------------------===//
+// UnsafeBufferReachableAnalysis---computes reachable unsafe buffer nodes
+//===----------------------------------------------------------------------===//
+
+json::Object serializeUnsafeBufferReachableAnalysisResult(
+ const UnsafeBufferReachableAnalysisResult &R,
+ JSONFormat::EntityIdToJSONFn IdToJSON) {
+ json::Object Result;
+
+ Result[UnsafeBufferReachableAnalysisResultName] =
+ entityPointerLevelMapToJSON(R.Reachables, IdToJSON);
+ return Result;
+}
+
+Expected<std::unique_ptr<AnalysisResult>>
+deserializeUnsafeBufferReachableAnalysisResult(
+ const json::Object &Obj, JSONFormat::EntityIdFromJSONFn IdFromJSON) {
+ const json::Array *Content =
+ Obj.getArray(UnsafeBufferReachableAnalysisResultName);
+
+ if (!Content)
+ return makeSawButExpectedError(
+ Obj, "an object with a key %s",
+ UnsafeBufferReachableAnalysisResultName.data());
+
+ auto Reachables = entityPointerLevelMapFromJSON(*Content, IdFromJSON);
+
+ if (!Reachables)
+ return Reachables.takeError();
+
+ auto Ret = std::make_unique<UnsafeBufferReachableAnalysisResult>();
+
+ Ret->Reachables = std::move(*Reachables);
+ return Ret;
+}
+
+JSONFormat::AnalysisResultRegistry::Add<UnsafeBufferReachableAnalysisResult>
+ RegisterUnsafeBufferReachableResultForJSON(
+ serializeUnsafeBufferReachableAnalysisResult,
+ deserializeUnsafeBufferReachableAnalysisResult);
+
+/// Computes all the reachable "nodes" (pointers) in a pointer flow graph from a
+/// provided starter node set. Specifically, the starter set is the unsafe
+/// pointers found by `UnsafeBufferUsageAnalysis`.
+class UnsafeBufferReachableAnalysis
+ : public DerivedAnalysis<UnsafeBufferReachableAnalysisResult,
+ PointerFlowAnalysisResult,
+ UnsafeBufferUsageAnalysisResult> {
+
+ /// BoundsPropagationGraph adds bounds propagation semantics to the
+ /// pointer-flow graph, which represents the set of static pointer assignment
+ /// sites collected from the source code. Consider the following example:
+ ///
+ /// void f(int ***p, int **q) {
+ /// *p = q;
+ /// (**p)[5] = 0;
+ /// }
+ ///
+ /// There is one static pointer assignment thus one pointer-flow edge: (p, 2)
+ /// -> (q, 1). In terms of bounds propagation, this assignment implies that if
+ /// 'p' at pointer level 2 requires bounds, 'q' at pointer level 1 must also
+ /// have them. Furthermore, this relationship propagates to deeper indirection
+ /// levels: if 'p' at level 3 requires bounds, so does 'q' at level 2.
+ ///
+ /// In the example above, `(**p)` requires bounds (due to the array index),
+ /// and therefore `*q` must require bounds as well.
+ ///
+ /// To generalize the idea, the BoundsPropagationGraph is defined as a super
+ /// graph of the input pointer-flow graph by:
+ ///
+ /// For each edge (src, i) -> (dest, j) in the pointer-flow graph, the
+ /// BoundsPropagationGraph has a finite set of edges
+ /// {(src, i + d) -> (dest, j + d) | 0 <= d < UB}, where UB is an upper
+ /// bound based on the maximum pointer level the pointer type can have.
+ struct BoundsPropagationGraph {
+ private:
+ const std::map<EntityPointerLevel, EntityPointerLevelSet> &PointerFlows;
+
+ public:
+ BoundsPropagationGraph(const EdgeSet &PointerFlows)
+ : PointerFlows(PointerFlows) {}
+
+ /// Returns the EntityPointerLevelSet that are reachable from \p Src by
+ /// one edge in the BoundsPropagationGraph.
+ EntityPointerLevelSet getDestNodes(const EntityPointerLevel &Src) const {
+ unsigned SrcPtrLv = Src.getPointerLevel();
+ EntityPointerLevelSet Result;
+
+ for (unsigned P = 1; P <= SrcPtrLv; ++P) {
+ auto I = PointerFlows.find(buildEntityPointerLevel(Src.getEntity(), P));
+
+ if (I != PointerFlows.end()) {
+ unsigned Delta = SrcPtrLv - P;
+ for (const auto &EPL : I->second)
+ Result.insert(buildEntityPointerLevel(
+ EPL.getEntity(), EPL.getPointerLevel() + Delta));
+ }
+ }
+ return Result;
+ }
+ };
+
+ std::map<EntityId, BoundsPropagationGraph> BPG;
+
+ // Use pointers for efficiency. EPLs are in tree-based containers that only
+ // grow. So pointers to them are stable.
+ using EPLPtr = const EntityPointerLevel *;
+
+ // Find all outgoing edges from `EPL` in the `Graph`, insert their
+ // destination nodes into `Reachables`, and add newly discovered nodes to
+ // `Worklist`:
+ void updateReachablesWithOutgoings(EPLPtr EPL,
+ std::vector<EPLPtr> &WorkList) {
+ for (auto &[Id, SubGraph] : BPG) {
+ auto R = SubGraph.getDestNodes(*EPL);
+
+ for (const auto &Dst : R) {
+ auto [It, Inserted] = getResult().Reachables[Id].insert(Dst);
+ if (Inserted)
+ WorkList.push_back(&*It);
+ }
+ }
+ }
+
+public:
+ llvm::Error
+ initialize(const PointerFlowAnalysisResult &PtrFlowGraph,
+ const UnsafeBufferUsageAnalysisResult &Starter) override {
+ for (auto &[Id, SubGraph] : PtrFlowGraph.Edges)
+ BPG.try_emplace(Id, BoundsPropagationGraph(SubGraph));
+ assert(getResult().Reachables.empty());
+ getResult().Reachables.insert(Starter.begin(), Starter.end());
+ return llvm::Error::success();
+ }
+
+ llvm::Expected<bool> step() override {
+ auto &Reachables = getResult().Reachables;
+ // Simple DFS:
+ std::vector<EPLPtr> Worklist;
+
+ for (auto &[Id, EPLs] : Reachables)
+ for (auto &EPL : EPLs)
+ Worklist.push_back(&EPL);
+
+ while (!Worklist.empty()) {
+ EPLPtr Node = Worklist.back();
+ Worklist.pop_back();
+
+ updateReachablesWithOutgoings(Node, Worklist);
+ }
+ // This is not an iterative algorithm so stop iteration by retruning false:
+ return false;
+ }
+};
+
+AnalysisRegistry::Add<UnsafeBufferReachableAnalysis>
+ RegisterUnsafeBufferReachableAnalysis(
+ "Reachable pointers from unsafe buffer usage in pointer flow graph");
+
+} // namespace
+
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int UnsafeBufferUsageAnalysisAnchorSource = 0;
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
new file mode 100644
index 0000000000000..b634cbffe0a28
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp
@@ -0,0 +1,110 @@
+//===- UnsafeBufferUsageExtractor.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SSAFAnalysesCommon.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
+#include "clang/Analysis/Analyses/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+using namespace ssaf;
+
+namespace clang::ssaf {
+class UnsafeBufferUsageTUSummaryExtractor : public TUSummaryExtractor {
+public:
+ UnsafeBufferUsageTUSummaryExtractor(TUSummaryBuilder &Builder)
+ : TUSummaryExtractor(Builder) {}
+
+ /// \return a non-null unique pointer to a UnsafeBufferUsageEntitySummary
+ std::unique_ptr<UnsafeBufferUsageEntitySummary>
+ extractEntitySummary(const NamedDecl *Contributor, ASTContext &Ctx);
+ void HandleTranslationUnit(ASTContext &Ctx) override;
+};
+} // namespace clang::ssaf
+
+std::unique_ptr<UnsafeBufferUsageEntitySummary>
+clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::extractEntitySummary(
+ const NamedDecl *Contributor, ASTContext &Ctx) {
+ std::set<const Expr *> UnsafePointers;
+
+ auto MatchAction = [&UnsafePointers, &Ctx](const DynTypedNode &Node) {
+ matchUnsafePointers(Node, Ctx, UnsafePointers);
+ };
+ findMatchesIn(Contributor, MatchAction);
+
+ EntityPointerLevelSet Results;
+
+ for (const Expr *Ptr : UnsafePointers) {
+ Expected<EntityPointerLevelSet> Translation =
+ translateEntityPointerLevel(Ptr, Ctx, *this);
+
+ if (Translation) {
+ // Filter out those temporary invalid EntityPointerLevels associated
+ // with `&E` pointers. They need no transformation of entities:
+ auto FilteredTranslation = llvm::make_filter_range(
+ *Translation, [](const EntityPointerLevel &E) -> bool {
+ return E.getPointerLevel() > 0;
+ });
+ Results.insert(FilteredTranslation.begin(), FilteredTranslation.end());
+ continue;
+ }
+ logWarningFromError(Translation.takeError());
+ }
+
+ return std::make_unique<UnsafeBufferUsageEntitySummary>(
+ UnsafeBufferUsageEntitySummary(std::move(Results)));
+}
+
+void clang::ssaf::UnsafeBufferUsageTUSummaryExtractor::HandleTranslationUnit(
+ ASTContext &Ctx) {
+ std::vector<const NamedDecl *> Contributors;
+
+ findContributors(Ctx, 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
+ // instantiations.
+ if (CD->isTemplated())
+ continue;
+
+ auto EntitySummary = extractEntitySummary(CD, Ctx);
+
+ assert(EntitySummary);
+ if (EntitySummary->empty())
+ continue;
+
+ auto ContributorId = addEntity(CD);
+
+ if (!ContributorId) {
+ logWarningFromError(makeEntityNameErr(Ctx, CD));
+ continue;
+ }
+
+ [[maybe_unused]] auto [Ignored, InsertionSucceeded] =
+ SummaryBuilder.addSummary(*ContributorId, std::move(EntitySummary));
+
+ assert(InsertionSucceeded && "duplicated contributor extraction");
+ }
+}
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int UnsafeBufferUsageExtractorAnchorSource = 0;
+} // namespace clang::ssaf
+
+static clang::ssaf::TUSummaryExtractorRegistry::Add<
+ UnsafeBufferUsageTUSummaryExtractor>
+ RegisterExtractor(UnsafeBufferUsageEntitySummary::Name,
+ "Extract unsafe buffer pointers");
diff --git a/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
new file mode 100644
index 0000000000000..5fafe0e92abfa
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp
@@ -0,0 +1,86 @@
+//===- UnsafeBufferUsageFormat.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "SSAFAnalysesCommon.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevelFormat.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
+
+using namespace clang;
+using namespace ssaf;
+using Array = llvm::json::Array;
+using Object = llvm::json::Object;
+
+static constexpr llvm::StringLiteral SummarySerializationKey = "UnsafeBuffers";
+
+extern UnsafeBufferUsageEntitySummary
+ssaf::buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers);
+
+extern llvm::iterator_range<EntityPointerLevelSet::const_iterator>
+ssaf::getUnsafeBuffers(const UnsafeBufferUsageEntitySummary &S);
+
+static Object serialize(const EntitySummary &S,
+ JSONFormat::EntityIdToJSONFn Fn) {
+ const auto &SS = static_cast<const UnsafeBufferUsageEntitySummary &>(S);
+ Array UnsafeBuffersData;
+
+ for (const auto &EPL : getUnsafeBuffers(SS))
+ UnsafeBuffersData.push_back(entityPointerLevelToJSON(EPL, Fn));
+ return Object{{SummarySerializationKey.data(), std::move(UnsafeBuffersData)}};
+}
+
+static llvm::Expected<std::unique_ptr<EntitySummary>>
+deserializeImpl(const Object &Data, JSONFormat::EntityIdFromJSONFn Fn) {
+ const Array *UnsafeBuffersData =
+ Data.getArray(SummarySerializationKey.data());
+
+ if (!UnsafeBuffersData)
+ return makeSawButExpectedError(Object(Data), "an Object with a key %s",
+ SummarySerializationKey.data());
+
+ EntityPointerLevelSet EPLs;
+
+ for (const auto &EltData : *UnsafeBuffersData) {
+ llvm::Expected<EntityPointerLevel> EPL =
+ entityPointerLevelFromJSON(EltData, Fn);
+
+ if (!EPL)
+ return EPL.takeError();
+ EPLs.insert(*EPL);
+ }
+ return std::make_unique<UnsafeBufferUsageEntitySummary>(
+ buildUnsafeBufferUsageEntitySummary(std::move(EPLs)));
+}
+
+static llvm::Expected<std::unique_ptr<EntitySummary>>
+deserialize(const Object &Data, EntityIdTable &,
+ JSONFormat::EntityIdFromJSONFn Fn) {
+ return deserializeImpl(Data, Fn);
+}
+
+namespace {
+struct UnsafeBufferUsageJSONFormatInfo final : JSONFormat::FormatInfo {
+ UnsafeBufferUsageJSONFormatInfo()
+ : JSONFormat::FormatInfo(UnsafeBufferUsageEntitySummary::summaryName(),
+ serialize, deserialize) {}
+};
+} // namespace
+
+static llvm::Registry<JSONFormat::FormatInfo>::Add<
+ UnsafeBufferUsageJSONFormatInfo>
+ RegisterUnsafeBufferUsageJSONFormatInfo(
+ UnsafeBufferUsageEntitySummary::Name,
+ "JSON Format info for UnsafeBufferUsageEntitySummary");
+
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int UnsafeBufferUsageJSONFormatAnchorSource = 0;
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/CMakeLists.txt
new file mode 100644
index 0000000000000..b214c06644db7
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/CMakeLists.txt
@@ -0,0 +1,6 @@
+add_subdirectory(Analyses)
+add_subdirectory(Core)
+add_subdirectory(Frontend)
+add_subdirectory(Plugins)
+add_subdirectory(SourceTransformation)
+add_subdirectory(Tool)
diff --git a/clang/lib/ScalableStaticAnalysis/Core/ASTEntityMapping.cpp b/clang/lib/ScalableStaticAnalysis/Core/ASTEntityMapping.cpp
new file mode 100644
index 0000000000000..1f4bf0da274ed
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/ASTEntityMapping.cpp
@@ -0,0 +1,83 @@
+//===- ASTMapping.cpp - AST to SSAF Entity mapping ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements utilities for mapping AST declarations to SSAF entities.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "clang/AST/Decl.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/UnifiedSymbolResolution/USRGeneration.h"
+#include "llvm/ADT/SmallString.h"
+
+namespace clang::ssaf {
+
+std::optional<EntityName> getEntityName(const Decl *D) {
+ if (!D)
+ return std::nullopt;
+
+ if (D->isImplicit())
+ return std::nullopt;
+
+ if (isa<FunctionDecl>(D) && cast<FunctionDecl>(D)->getBuiltinID())
+ return std::nullopt;
+
+ if (!isa<FunctionDecl, ParmVarDecl, VarDecl, FieldDecl, RecordDecl>(D))
+ return std::nullopt;
+
+ llvm::SmallString<16> Suffix;
+ const Decl *USRDecl = D;
+
+ // For parameters, use the parent function's USR with parameter index as
+ // suffix
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
+ const auto *FD =
+ dyn_cast_or_null<FunctionDecl>(PVD->getParentFunctionOrMethod());
+ if (!FD)
+ return std::nullopt;
+ USRDecl = FD;
+
+ const auto ParamIdx = PVD->getFunctionScopeIndex();
+ llvm::raw_svector_ostream OS(Suffix);
+ // Parameter uses function's USR with 1-based index as suffix
+ OS << (ParamIdx + 1);
+ }
+
+ llvm::SmallString<128> USRBuf;
+ if (clang::index::generateUSRForDecl(USRDecl, USRBuf))
+ return std::nullopt;
+
+ if (USRBuf.empty())
+ return std::nullopt;
+
+ return EntityName(USRBuf.str(), Suffix, {});
+}
+
+std::optional<EntityName> getEntityNameForReturn(const FunctionDecl *FD) {
+ if (!FD)
+ return std::nullopt;
+
+ if (FD->isImplicit())
+ return std::nullopt;
+
+ if (FD->getBuiltinID())
+ return std::nullopt;
+
+ llvm::SmallString<128> USRBuf;
+ if (clang::index::generateUSRForDecl(FD, USRBuf)) {
+ return std::nullopt;
+ }
+
+ if (USRBuf.empty())
+ return std::nullopt;
+
+ return EntityName(USRBuf.str(), /*Suffix=*/"0", /*Namespace=*/{});
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Core/CMakeLists.txt
new file mode 100644
index 0000000000000..b2cde5f225445
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/CMakeLists.txt
@@ -0,0 +1,39 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ TargetParser
+ )
+
+add_clang_library(clangScalableStaticAnalysisCore
+ ASTEntityMapping.cpp
+ EntityLinker/EntityLinker.cpp
+ Model/BuildNamespace.cpp
+ Model/EntityId.cpp
+ Model/EntityIdTable.cpp
+ Model/EntityLinkage.cpp
+ Model/EntityName.cpp
+ Model/SummaryName.cpp
+ Serialization/JSONFormat/Artifact.cpp
+ Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
+ Serialization/JSONFormat/JSONFormatImpl.cpp
+ Serialization/JSONFormat/LUSummary.cpp
+ Serialization/JSONFormat/LUSummaryEncoding.cpp
+ Serialization/JSONFormat/TUSummary.cpp
+ Serialization/JSONFormat/TUSummaryEncoding.cpp
+ Serialization/JSONFormat/WPASuite.cpp
+ Serialization/SerializationFormatRegistry.cpp
+ SummaryData/LUSummaryConsumer.cpp
+ SummaryData/SummaryDataBuilderRegistry.cpp
+ Support/ErrorBuilder.cpp
+ TUSummary/ExtractorRegistry.cpp
+ TUSummary/TUSummaryBuilder.cpp
+ TUSummary/TUSummaryExtractor.cpp
+ WholeProgramAnalysis/AnalysisDriver.cpp
+ WholeProgramAnalysis/AnalysisName.cpp
+ WholeProgramAnalysis/AnalysisRegistry.cpp
+
+ LINK_LIBS
+ clangAST
+ clangUnifiedSymbolResolution
+
+ DEPENDS
+ )
diff --git a/clang/lib/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.cpp b/clang/lib/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.cpp
new file mode 100644
index 0000000000000..462978932a53d
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.cpp
@@ -0,0 +1,197 @@
+//===- EntityLinker.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include <cassert>
+
+using namespace clang::ssaf;
+
+//===----------------------------------------------------------------------===//
+// Error Message Constants
+//===----------------------------------------------------------------------===//
+
+namespace ErrorMessages {
+
+static constexpr const char *EntityLinkerFatalErrorPrefix =
+ "EntityLinker: Corrupted TUSummary or logic bug";
+
+static constexpr const char *EntityAlreadyExistsInLinkageTable =
+ "{0} - {1} with {2} already exists in LUSummary";
+
+static constexpr const char *MissingLinkageInformation =
+ "{0} - {1} missing linkage information in TUSummary";
+
+static constexpr const char *DuplicateEntityIdInTUSummary =
+ "{0} - Duplicate {1} in EntityResolutionTable";
+
+static constexpr const char *EntityNotFoundInResolutionTable =
+ "{0} - {1} not found in EntityResolutionTable";
+
+static constexpr const char *FailedToInsertEntityIntoOutputSummary =
+ "{0} - Failed to insert data for {1} with {2} against {3} to LUSummary";
+
+static constexpr const char *DuplicateTUNamespace =
+ "failed to link TU summary: duplicate {0}";
+
+} // namespace ErrorMessages
+
+static NestedBuildNamespace
+resolveNamespace(const NestedBuildNamespace &LUNamespace,
+ const NestedBuildNamespace &TUNamespace,
+ const NestedBuildNamespace &EntityNamespace,
+ EntityLinkageType Linkage) {
+ switch (Linkage) {
+ case EntityLinkageType::None:
+ case EntityLinkageType::Internal:
+ // Qualify with the TU namespace first (to disambiguate across TUs),
+ // then with the LU namespace.
+ return EntityNamespace.makeQualified(TUNamespace)
+ .makeQualified(LUNamespace);
+ case EntityLinkageType::External:
+ return NestedBuildNamespace(LUNamespace);
+ }
+
+ llvm_unreachable("Unhandled EntityLinkageType variant");
+}
+
+EntityId EntityLinker::resolveEntity(const EntityName &OldName,
+ const EntityLinkage &Linkage,
+ const NestedBuildNamespace &TUNamespace) {
+ NestedBuildNamespace NewNamespace = resolveNamespace(
+ Output.LUNamespace, TUNamespace, OldName.Namespace, Linkage.getLinkage());
+
+ EntityName NewName(OldName.USR, OldName.Suffix, NewNamespace);
+
+ // NewId construction will always return a fresh id for `None` and `Internal`
+ // linkage entities since their namespaces will be different even if their
+ // names clash. For `External` linkage entities with identical names this
+ // function will return the id assigned at the first insertion.
+ EntityId NewId = Output.IdTable.getId(NewName);
+
+ auto [_, Inserted] = Output.LinkageTable.try_emplace(NewId, Linkage);
+ if (!Inserted) {
+ // Insertion failure for `None` and `Internal` linkage is a fatal error
+ // because these entities have unique namespaces and should never collide.
+ // `External` linkage entities may collide.
+ if (Linkage.getLinkage() == EntityLinkageType::None ||
+ Linkage.getLinkage() == EntityLinkageType::Internal) {
+ ErrorBuilder::fatal(ErrorMessages::EntityAlreadyExistsInLinkageTable,
+ ErrorMessages::EntityLinkerFatalErrorPrefix, NewId,
+ Linkage);
+ }
+ }
+
+ return NewId;
+}
+
+std::map<EntityId, EntityId>
+EntityLinker::resolve(const TUSummaryEncoding &Summary) {
+ std::map<EntityId, EntityId> EntityResolutionTable;
+
+ Summary.IdTable.forEach([&](const EntityName &OldName, const EntityId OldId) {
+ auto Iter = Summary.LinkageTable.find(OldId);
+ if (Iter == Summary.LinkageTable.end()) {
+ ErrorBuilder::fatal(ErrorMessages::MissingLinkageInformation,
+ ErrorMessages::EntityLinkerFatalErrorPrefix, OldId);
+ }
+
+ const EntityLinkage &Linkage = Iter->second;
+
+ EntityId NewId = resolveEntity(OldName, Linkage,
+ NestedBuildNamespace(Summary.TUNamespace));
+
+ auto [_, Inserted] = EntityResolutionTable.insert({OldId, NewId});
+ if (!Inserted) {
+ ErrorBuilder::fatal(ErrorMessages::DuplicateEntityIdInTUSummary,
+ ErrorMessages::EntityLinkerFatalErrorPrefix, OldId);
+ }
+ });
+
+ return EntityResolutionTable;
+}
+
+std::vector<EntitySummaryEncoding *>
+EntityLinker::merge(TUSummaryEncoding &Summary,
+ const std::map<EntityId, EntityId> &EntityResolutionTable) {
+ std::vector<EntitySummaryEncoding *> PatchTargets;
+
+ for (auto &[SN, DataMap] : Summary.Data) {
+ auto &OutputSummaryData = Output.Data[SN];
+
+ for (auto &[OldId, ES] : DataMap) {
+ auto Iter = EntityResolutionTable.find(OldId);
+ if (Iter == EntityResolutionTable.end()) {
+ ErrorBuilder::fatal(ErrorMessages::EntityNotFoundInResolutionTable,
+ ErrorMessages::EntityLinkerFatalErrorPrefix, OldId);
+ }
+
+ const auto NewId = Iter->second;
+
+ auto [It, Inserted] = OutputSummaryData.try_emplace(NewId, std::move(ES));
+
+ if (Inserted) {
+ PatchTargets.push_back(It->second.get());
+ } else {
+ // Safe to retrieve linkage using .at since the resolve step ensures
+ // linkage information is always present for every OldId.
+ auto Linkage = Summary.LinkageTable.at(OldId);
+
+ // Insertion should never fail for `None` and `Internal` linkage
+ // entities because these entities will have different namespaces across
+ // TUs even if their names match.
+ if (Linkage.getLinkage() == EntityLinkageType::None ||
+ Linkage.getLinkage() == EntityLinkageType::Internal) {
+ ErrorBuilder::fatal(
+ ErrorMessages::FailedToInsertEntityIntoOutputSummary,
+ ErrorMessages::EntityLinkerFatalErrorPrefix, NewId, Linkage, SN);
+ }
+
+ // TODO: Insertion is expected to fail for duplicate occurrences of
+ // `External` linkage entities. Report these cases in a "debug" mode to
+ // help debug potential ODR violations.
+ }
+ }
+ }
+
+ return PatchTargets;
+}
+
+llvm::Error
+EntityLinker::patch(const std::vector<EntitySummaryEncoding *> &PatchTargets,
+ const std::map<EntityId, EntityId> &EntityResolutionTable) {
+ for (auto *PatchTarget : PatchTargets) {
+ assert(PatchTarget && "EntityLinker::patch: Patch target cannot be null");
+
+ if (auto Err = PatchTarget->patch(EntityResolutionTable)) {
+ return Err;
+ }
+ }
+ return llvm::Error::success();
+}
+
+llvm::Error EntityLinker::link(std::unique_ptr<TUSummaryEncoding> Summary) {
+ auto [_, Inserted] = ProcessedTUNamespaces.insert(Summary->TUNamespace);
+ if (!Inserted) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::DuplicateTUNamespace,
+ Summary->TUNamespace)
+ .build();
+ }
+
+ TUSummaryEncoding &SummaryRef = *Summary;
+
+ auto EntityResolutionTable = resolve(SummaryRef);
+ auto PatchTargets = merge(SummaryRef, EntityResolutionTable);
+ return patch(PatchTargets, EntityResolutionTable);
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/BuildNamespace.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/BuildNamespace.cpp
new file mode 100644
index 0000000000000..f68ed961f71b9
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/BuildNamespace.cpp
@@ -0,0 +1,73 @@
+//===- BuildNamespace.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "../ModelStringConversions.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <tuple>
+
+namespace clang::ssaf {
+
+BuildNamespace
+BuildNamespace::makeCompilationUnit(llvm::StringRef CompilationId) {
+ return BuildNamespace{BuildNamespaceKind::CompilationUnit,
+ CompilationId.str()};
+}
+
+bool BuildNamespace::operator==(const BuildNamespace &Other) const {
+ return asTuple() == Other.asTuple();
+}
+
+bool BuildNamespace::operator!=(const BuildNamespace &Other) const {
+ return !(*this == Other);
+}
+
+bool BuildNamespace::operator<(const BuildNamespace &Other) const {
+ return asTuple() < Other.asTuple();
+}
+
+NestedBuildNamespace
+NestedBuildNamespace::makeCompilationUnit(llvm::StringRef CompilationId) {
+ NestedBuildNamespace Result;
+ Result.Namespaces.push_back(
+ BuildNamespace::makeCompilationUnit(CompilationId));
+ return Result;
+}
+
+bool NestedBuildNamespace::empty() const { return Namespaces.empty(); }
+
+bool NestedBuildNamespace::operator==(const NestedBuildNamespace &Other) const {
+ return Namespaces == Other.Namespaces;
+}
+
+bool NestedBuildNamespace::operator!=(const NestedBuildNamespace &Other) const {
+ return !(*this == Other);
+}
+
+bool NestedBuildNamespace::operator<(const NestedBuildNamespace &Other) const {
+ return Namespaces < Other.Namespaces;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, BuildNamespaceKind BNK) {
+ return OS << buildNamespaceKindToString(BNK);
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const BuildNamespace &BN) {
+ return OS << "BuildNamespace(" << BN.Kind << ", " << BN.Name << ")";
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const NestedBuildNamespace &NBN) {
+ OS << "NestedBuildNamespace([";
+ llvm::interleaveComma(NBN.Namespaces, OS);
+ OS << "])";
+ return OS;
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityId.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityId.cpp
new file mode 100644
index 0000000000000..a731bd24da4a0
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityId.cpp
@@ -0,0 +1,17 @@
+//===- EntityId.cpp -------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+
+namespace clang::ssaf {
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityId &Id) {
+ return OS << "EntityId(" << Id.Index << ")";
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityIdTable.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityIdTable.cpp
new file mode 100644
index 0000000000000..651179c24a342
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityIdTable.cpp
@@ -0,0 +1,31 @@
+//===- EntityIdTable.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include <cassert>
+
+namespace clang::ssaf {
+
+EntityId EntityIdTable::getId(const EntityName &Name) {
+ EntityId Id(Entities.size());
+ const auto Res = Entities.try_emplace(Name, Id);
+ return Res.first->second;
+}
+
+bool EntityIdTable::contains(const EntityName &Name) const {
+ return Entities.find(Name) != Entities.end();
+}
+
+void EntityIdTable::forEach(
+ llvm::function_ref<void(const EntityName &, EntityId)> Callback) const {
+ for (const auto &NameIdPair : Entities) {
+ Callback(NameIdPair.first, NameIdPair.second);
+ }
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityLinkage.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityLinkage.cpp
new file mode 100644
index 0000000000000..0bae90cd66a22
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityLinkage.cpp
@@ -0,0 +1,33 @@
+//===- EntityLinkage.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+
+#include "../ModelStringConversions.h"
+
+namespace clang::ssaf {
+
+bool EntityLinkage::operator==(const EntityLinkage &Other) const {
+ return Linkage == Other.Linkage;
+}
+
+bool EntityLinkage::operator!=(const EntityLinkage &Other) const {
+ return !(*this == Other);
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ EntityLinkageType Linkage) {
+ return OS << entityLinkageTypeToString(Linkage);
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+ const EntityLinkage &Linkage) {
+ return OS << "EntityLinkage(" << Linkage.getLinkage() << ")";
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/EntityName.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityName.cpp
new file mode 100644
index 0000000000000..c9e09df84143b
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/EntityName.cpp
@@ -0,0 +1,41 @@
+//===- EntityName.cpp -----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+
+namespace clang::ssaf {
+
+EntityName::EntityName(llvm::StringRef USR, llvm::StringRef Suffix,
+ NestedBuildNamespace Namespace)
+ : USR(USR.str()), Suffix(Suffix), Namespace(std::move(Namespace)) {}
+
+bool EntityName::operator==(const EntityName &Other) const {
+ return asTuple() == Other.asTuple();
+}
+
+bool EntityName::operator!=(const EntityName &Other) const {
+ return !(*this == Other);
+}
+
+bool EntityName::operator<(const EntityName &Other) const {
+ return asTuple() < Other.asTuple();
+}
+
+EntityName EntityName::makeQualified(NestedBuildNamespace Namespace) const {
+ auto Copy = *this;
+ Copy.Namespace = Copy.Namespace.makeQualified(Namespace);
+
+ return Copy;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const EntityName &EN) {
+ return OS << "EntityName(" << EN.USR << ", " << EN.Suffix << ", "
+ << EN.Namespace << ")";
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Model/SummaryName.cpp b/clang/lib/ScalableStaticAnalysis/Core/Model/SummaryName.cpp
new file mode 100644
index 0000000000000..66c7726a9da90
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Model/SummaryName.cpp
@@ -0,0 +1,17 @@
+//===- SummaryName.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+
+namespace clang::ssaf {
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SummaryName &SN) {
+ return OS << "SummaryName(" << SN.str() << ")";
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/ModelStringConversions.h b/clang/lib/ScalableStaticAnalysis/Core/ModelStringConversions.h
new file mode 100644
index 0000000000000..ee1603e50025f
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/ModelStringConversions.h
@@ -0,0 +1,87 @@
+//===- ModelStringConversions.h ---------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Internal string conversion utilities for SSAF model types.
+//
+// These functions are shared by the model .cpp files (for operator<<) and
+// JSONFormat.cpp (for serialization). They are not part of the public API.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_ScalableStaticAnalysis_CORE_MODELSTRINGCONVERSIONS_H
+#define LLVM_CLANG_LIB_ScalableStaticAnalysis_CORE_MODELSTRINGCONVERSIONS_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <optional>
+
+namespace clang::ssaf {
+
+//===----------------------------------------------------------------------===//
+// BuildNamespaceKind
+//===----------------------------------------------------------------------===//
+
+/// Returns the canonical string representation of \p BNK used for
+/// serialization and display (e.g. "CompilationUnit", "LinkUnit").
+inline llvm::StringRef buildNamespaceKindToString(BuildNamespaceKind BNK) {
+ switch (BNK) {
+ case BuildNamespaceKind::CompilationUnit:
+ return "CompilationUnit";
+ case BuildNamespaceKind::LinkUnit:
+ return "LinkUnit";
+ }
+ llvm_unreachable("Unhandled BuildNamespaceKind variant");
+}
+
+/// Parses a string produced by buildNamespaceKindToString(). Returns
+/// std::nullopt if \p Str does not match any known BuildNamespaceKind value.
+inline std::optional<BuildNamespaceKind>
+buildNamespaceKindFromString(llvm::StringRef Str) {
+ if (Str == "CompilationUnit")
+ return BuildNamespaceKind::CompilationUnit;
+ if (Str == "LinkUnit")
+ return BuildNamespaceKind::LinkUnit;
+ return std::nullopt;
+}
+
+//===----------------------------------------------------------------------===//
+// EntityLinkageType
+//===----------------------------------------------------------------------===//
+
+/// Returns the canonical string representation of \p LT used for
+/// serialization and display (e.g. "None", "Internal", "External").
+inline llvm::StringRef entityLinkageTypeToString(EntityLinkageType LT) {
+ switch (LT) {
+ case EntityLinkageType::None:
+ return "None";
+ case EntityLinkageType::Internal:
+ return "Internal";
+ case EntityLinkageType::External:
+ return "External";
+ }
+ llvm_unreachable("Unhandled EntityLinkageType variant");
+}
+
+/// Parses a string produced by entityLinkageTypeToString(). Returns
+/// std::nullopt if \p Str does not match any known EntityLinkageType value.
+inline std::optional<EntityLinkageType>
+entityLinkageTypeFromString(llvm::StringRef Str) {
+ if (Str == "None")
+ return EntityLinkageType::None;
+ if (Str == "Internal")
+ return EntityLinkageType::Internal;
+ if (Str == "External")
+ return EntityLinkageType::External;
+ return std::nullopt;
+}
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_LIB_ScalableStaticAnalysis_CORE_MODELSTRINGCONVERSIONS_H
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/Artifact.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/Artifact.cpp
new file mode 100644
index 0000000000000..424d7368cf33f
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/Artifact.cpp
@@ -0,0 +1,173 @@
+//===- Artifact.cpp -------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic artifact read/write entry points that dispatch on the
+// self-describing "type" field of the JSON document.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONFormatImpl.h"
+
+namespace clang::ssaf {
+
+llvm::Expected<Artifact> JSONFormat::readArtifact(llvm::StringRef Path) {
+ auto ExpectedJSON = readJSON(Path);
+ if (!ExpectedJSON) {
+ return ErrorBuilder::wrap(ExpectedJSON.takeError())
+ .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
+ .build();
+ }
+
+ Object *RootObjectPtr = ExpectedJSON->getAsObject();
+ if (!RootObjectPtr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObject, "Artifact",
+ "object")
+ .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
+ .build();
+ }
+
+ auto ExpectedType = readSummaryType(*RootObjectPtr);
+ if (!ExpectedType) {
+ return ErrorBuilder::wrap(ExpectedType.takeError())
+ .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
+ .build();
+ }
+
+ // Dispatch by the self-describing type field. The helpers operate on
+ // the already-parsed root object so the file is read and parsed only
+ // once per readArtifact call.
+ if (*ExpectedType == JSONTypeValueTUSummary) {
+ auto ExpectedTU = readTUSummaryFromObject(*RootObjectPtr);
+ if (!ExpectedTU) {
+ return ErrorBuilder::wrap(ExpectedTU.takeError())
+ .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
+ .build();
+ }
+ return Artifact{std::move(*ExpectedTU)};
+ }
+
+ if (*ExpectedType == JSONTypeValueLUSummary) {
+ auto ExpectedLU = readLUSummaryFromObject(*RootObjectPtr);
+ if (!ExpectedLU) {
+ return ErrorBuilder::wrap(ExpectedLU.takeError())
+ .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
+ .build();
+ }
+ return Artifact{std::move(*ExpectedLU)};
+ }
+
+ if (*ExpectedType == JSONTypeValueWPASuite) {
+ auto ExpectedWPA = readWPASuiteFromObject(*RootObjectPtr);
+ if (!ExpectedWPA) {
+ return ErrorBuilder::wrap(ExpectedWPA.takeError())
+ .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
+ .build();
+ }
+ return Artifact{std::move(*ExpectedWPA)};
+ }
+
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::UnknownArtifactType, *ExpectedType,
+ JSONTypeKey, JSONTypeValueTUSummary,
+ JSONTypeValueLUSummary, JSONTypeValueWPASuite)
+ .context(ErrorMessages::ReadingFromFile, "Artifact", Path)
+ .build();
+}
+
+llvm::Error JSONFormat::writeArtifact(const Artifact &A, llvm::StringRef Path) {
+ return std::visit(
+ [&](const auto &S) -> llvm::Error {
+ using T = std::decay_t<decltype(S)>;
+ if constexpr (std::is_same_v<T, TUSummary>) {
+ return writeTUSummary(S, Path);
+ } else if constexpr (std::is_same_v<T, LUSummary>) {
+ return writeLUSummary(S, Path);
+ } else {
+ static_assert(std::is_same_v<T, WPASuite>,
+ "Artifact visitor must cover all variant alternatives");
+ return writeWPASuite(S, Path);
+ }
+ },
+ A);
+}
+
+llvm::Expected<ArtifactEncoding>
+JSONFormat::readArtifactEncoding(llvm::StringRef Path) {
+ auto ExpectedJSON = readJSON(Path);
+ if (!ExpectedJSON) {
+ return ErrorBuilder::wrap(ExpectedJSON.takeError())
+ .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
+ .build();
+ }
+
+ Object *RootObjectPtr = ExpectedJSON->getAsObject();
+ if (!RootObjectPtr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObject,
+ "ArtifactEncoding", "object")
+ .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
+ .build();
+ }
+
+ auto ExpectedType = readSummaryType(*RootObjectPtr);
+ if (!ExpectedType) {
+ return ErrorBuilder::wrap(ExpectedType.takeError())
+ .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
+ .build();
+ }
+
+ // Dispatch by the self-describing type field. The helpers operate on
+ // the already-parsed root object so the file is read and parsed only
+ // once per readArtifactEncoding call.
+ if (*ExpectedType == JSONTypeValueTUSummary) {
+ auto ExpectedTU = readTUSummaryEncodingFromObject(*RootObjectPtr);
+ if (!ExpectedTU) {
+ return ErrorBuilder::wrap(ExpectedTU.takeError())
+ .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
+ .build();
+ }
+ return ArtifactEncoding{std::move(*ExpectedTU)};
+ }
+
+ if (*ExpectedType == JSONTypeValueLUSummary) {
+ auto ExpectedLU = readLUSummaryEncodingFromObject(*RootObjectPtr);
+ if (!ExpectedLU) {
+ return ErrorBuilder::wrap(ExpectedLU.takeError())
+ .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
+ .build();
+ }
+ return ArtifactEncoding{std::move(*ExpectedLU)};
+ }
+
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::UnknownArtifactEncodingType,
+ *ExpectedType, JSONTypeKey,
+ JSONTypeValueTUSummary, JSONTypeValueLUSummary)
+ .context(ErrorMessages::ReadingFromFile, "ArtifactEncoding", Path)
+ .build();
+}
+
+llvm::Error JSONFormat::writeArtifactEncoding(const ArtifactEncoding &E,
+ llvm::StringRef Path) {
+ return std::visit(
+ [&](const auto &Enc) -> llvm::Error {
+ using T = std::decay_t<decltype(Enc)>;
+ if constexpr (std::is_same_v<T, TUSummaryEncoding>) {
+ return writeTUSummaryEncoding(Enc, Path);
+ } else {
+ static_assert(
+ std::is_same_v<T, LUSummaryEncoding>,
+ "ArtifactEncoding visitor must cover all variant alternatives");
+ return writeLUSummaryEncoding(Enc, Path);
+ }
+ },
+ E);
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
new file mode 100644
index 0000000000000..35c45ac108e07
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp
@@ -0,0 +1,86 @@
+//===- JSONEntitySummaryEncoding.cpp --------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONEntitySummaryEncoding.h"
+#include "JSONFormatImpl.h"
+
+namespace clang::ssaf {
+
+llvm::Error JSONEntitySummaryEncoding::patchEntityIdObject(
+ llvm::json::Object &Obj, const std::map<EntityId, EntityId> &Table,
+ llvm::json::Value *AtVal) {
+
+ if (Obj.size() != 1) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadEntityIdObject,
+ JSONEntityIdKey)
+ .build();
+ }
+
+ std::optional<uint64_t> OptEntityIdIndex = AtVal->getAsUINT64();
+ if (!OptEntityIdIndex) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadEntityIdObject,
+ JSONEntityIdKey)
+ .build();
+ }
+
+ auto OldId = JSONFormat::makeEntityId(*OptEntityIdIndex);
+ auto It = Table.find(OldId);
+ if (It == Table.end()) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToPatchEntityIdNotInTable,
+ OldId)
+ .build();
+ }
+
+ *AtVal = static_cast<uint64_t>(JSONFormat::getIndex(It->second));
+
+ return llvm::Error::success();
+}
+
+llvm::Error JSONEntitySummaryEncoding::patchRegularObject(
+ llvm::json::Object &Obj, const std::map<EntityId, EntityId> &Table) {
+ for (auto &[Key, Val] : Obj) {
+ if (auto Err = patchValue(Val, Table)) {
+ return Err;
+ }
+ }
+ return llvm::Error::success();
+}
+
+llvm::Error JSONEntitySummaryEncoding::patchObject(
+ llvm::json::Object &Obj, const std::map<EntityId, EntityId> &Table) {
+
+ llvm::json::Value *AtVal = Obj.get(JSONEntityIdKey);
+ return AtVal ? patchEntityIdObject(Obj, Table, AtVal)
+ : patchRegularObject(Obj, Table);
+}
+
+llvm::Error JSONEntitySummaryEncoding::patchValue(
+ llvm::json::Value &V, const std::map<EntityId, EntityId> &Table) {
+ if (llvm::json::Object *Obj = V.getAsObject()) {
+ if (auto Err = patchObject(*Obj, Table)) {
+ return Err;
+ }
+ } else if (llvm::json::Array *Arr = V.getAsArray()) {
+ for (auto &Val : *Arr) {
+ if (auto Err = patchValue(Val, Table)) {
+ return Err;
+ }
+ }
+ }
+ return llvm::Error::success();
+}
+
+llvm::Error JSONEntitySummaryEncoding::patch(
+ const std::map<EntityId, EntityId> &EntityResolutionTable) {
+ return patchValue(Data, EntityResolutionTable);
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
new file mode 100644
index 0000000000000..5203e9d8ffc6f
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONEntitySummaryEncoding.h
@@ -0,0 +1,52 @@
+//===- JSONEntitySummaryEncoding.h ------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Opaque JSON-based entity summary encoding used by JSONFormat. Stores raw
+// EntitySummary JSON blobs and patches embedded entity ID references without
+// requiring knowledge of the analysis schema.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_ScalableStaticAnalysis_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
+#define LLVM_CLANG_LIB_ScalableStaticAnalysis_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "llvm/Support/JSON.h"
+
+#include <map>
+
+namespace clang::ssaf {
+
+class JSONEntitySummaryEncoding final : public EntitySummaryEncoding {
+ friend JSONFormat;
+
+public:
+ llvm::Error
+ patch(const std::map<EntityId, EntityId> &EntityResolutionTable) override;
+
+private:
+ explicit JSONEntitySummaryEncoding(llvm::json::Value Data)
+ : Data(std::move(Data)) {}
+
+ llvm::Error patchEntityIdObject(llvm::json::Object &Obj,
+ const std::map<EntityId, EntityId> &Table,
+ llvm::json::Value *AtVal);
+ llvm::Error patchRegularObject(llvm::json::Object &Obj,
+ const std::map<EntityId, EntityId> &Table);
+ llvm::Error patchObject(llvm::json::Object &Obj,
+ const std::map<EntityId, EntityId> &Table);
+ llvm::Error patchValue(llvm::json::Value &V,
+ const std::map<EntityId, EntityId> &Table);
+
+ llvm::json::Value Data;
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_LIB_ScalableStaticAnalysis_CORE_SERIALIZATION_JSONFORMAT_JSONENTITYSUMMARYENCODING_H
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
new file mode 100644
index 0000000000000..8dcbb707c3a22
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.cpp
@@ -0,0 +1,1380 @@
+//===- JSONFormatImpl.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONFormatImpl.h"
+
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "llvm/Support/Registry.h"
+#include "llvm/TargetParser/Triple.h"
+
+using namespace clang;
+using namespace ssaf;
+
+LLVM_DEFINE_REGISTRY(llvm::Registry<JSONFormat::FormatInfo>)
+LLVM_DEFINE_REGISTRY(llvm::Registry<JSONFormat::AnalysisResultRegistry::Codec>)
+
+static SerializationFormatRegistry::Add<JSONFormat>
+ RegisterJSONFormat("json", "JSON serialization format");
+
+namespace clang::ssaf {
+
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int JSONFormatAnchorSource = 0;
+
+//----------------------------------------------------------------------------
+// JSON Reader and Writer
+//----------------------------------------------------------------------------
+
+llvm::Expected<Value> readJSON(llvm::StringRef Path) {
+ if (!llvm::sys::fs::exists(Path)) {
+ return ErrorBuilder::create(std::errc::no_such_file_or_directory,
+ ErrorMessages::FailedToReadFile, Path,
+ ErrorMessages::FileNotFound)
+ .build();
+ }
+
+ if (llvm::sys::fs::is_directory(Path)) {
+ return ErrorBuilder::create(std::errc::is_a_directory,
+ ErrorMessages::FailedToReadFile, Path,
+ ErrorMessages::FileIsDirectory)
+ .build();
+ }
+
+ if (!Path.ends_with(JSONFormatFileExtension)) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadFile, Path,
+ llvm::formatv(ErrorMessages::FileIsNotJSON,
+ JSONFormatFileExtension))
+ .build();
+ }
+
+ auto BufferOrError = llvm::MemoryBuffer::getFile(Path);
+ if (!BufferOrError) {
+ const std::error_code EC = BufferOrError.getError();
+ return ErrorBuilder::create(EC, ErrorMessages::FailedToReadFile, Path,
+ EC.message())
+ .build();
+ }
+
+ return llvm::json::parse(BufferOrError.get()->getBuffer());
+}
+
+llvm::Error writeJSON(Value &&V, llvm::StringRef Path) {
+ if (llvm::sys::fs::exists(Path)) {
+ return ErrorBuilder::create(std::errc::file_exists,
+ ErrorMessages::FailedToWriteFile, Path,
+ ErrorMessages::FileExists)
+ .build();
+ }
+
+ llvm::StringRef Dir = llvm::sys::path::parent_path(Path);
+ if (!Dir.empty() && !llvm::sys::fs::is_directory(Dir)) {
+ return ErrorBuilder::create(std::errc::no_such_file_or_directory,
+ ErrorMessages::FailedToWriteFile, Path,
+ ErrorMessages::ParentDirectoryNotFound)
+ .build();
+ }
+
+ if (!Path.ends_with(JSONFormatFileExtension)) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToWriteFile, Path,
+ llvm::formatv(ErrorMessages::FileIsNotJSON,
+ JSONFormatFileExtension))
+ .build();
+ }
+
+ std::error_code EC;
+ llvm::raw_fd_ostream OutStream(Path, EC, llvm::sys::fs::OF_Text);
+
+ if (EC) {
+ return ErrorBuilder::create(EC, ErrorMessages::FailedToWriteFile, Path,
+ EC.message())
+ .build();
+ }
+
+ OutStream << llvm::formatv("{0:2}\n", V);
+ OutStream.flush();
+
+ // This path handles post-write stream errors (e.g. ENOSPC after buffered
+ // writes). It is difficult to exercise in unit tests so it is intentionally
+ // left without test coverage.
+ if (OutStream.has_error()) {
+ return ErrorBuilder::create(OutStream.error(),
+ ErrorMessages::FailedToWriteFile, Path,
+ OutStream.error().message())
+ .build();
+ }
+
+ return llvm::Error::success();
+}
+
+//----------------------------------------------------------------------------
+// JSONFormat Static Methods
+//----------------------------------------------------------------------------
+
+std::map<SummaryName, JSONFormat::FormatInfo> JSONFormat::initFormatInfos() {
+ std::map<SummaryName, FormatInfo> FormatInfos;
+ for (const auto &FormatInfoEntry : llvm::Registry<FormatInfo>::entries()) {
+ std::unique_ptr<FormatInfo> Info = FormatInfoEntry.instantiate();
+ bool Inserted = FormatInfos.try_emplace(Info->ForSummary, *Info).second;
+ if (!Inserted) {
+ llvm::report_fatal_error(
+ "FormatInfo is already registered for summary: " +
+ Info->ForSummary.str());
+ }
+ }
+ return FormatInfos;
+}
+
+void JSONFormat::forEachRegisteredAnalysis(
+ llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> Callback) const {
+ for (const auto &Entry : llvm::Registry<FormatInfo>::entries())
+ Callback(Entry.getName(), Entry.getDesc());
+}
+
+//----------------------------------------------------------------------------
+// SummaryName
+//----------------------------------------------------------------------------
+
+SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr) {
+ return SummaryName(SummaryNameStr.str());
+}
+
+llvm::StringRef summaryNameToJSON(const SummaryName &SN) { return SN.str(); }
+
+//----------------------------------------------------------------------------
+// Summary Type field
+//----------------------------------------------------------------------------
+
+llvm::Expected<llvm::StringRef> readSummaryType(const Object &RootObject) {
+ std::optional<llvm::StringRef> OptType = RootObject.getString(JSONTypeKey);
+ if (!OptType) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "summary type", JSONTypeKey, "string")
+ .build();
+ }
+ return *OptType;
+}
+
+llvm::Error checkSummaryType(const Object &RootObject,
+ llvm::StringRef ExpectedType) {
+ auto ExpectedActual = readSummaryType(RootObject);
+ if (!ExpectedActual) {
+ return ExpectedActual.takeError();
+ }
+ if (*ExpectedActual != ExpectedType) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::MismatchedSummaryType,
+ ExpectedType, JSONTypeKey, *ExpectedActual)
+ .build();
+ }
+ return llvm::Error::success();
+}
+
+//----------------------------------------------------------------------------
+// AnalysisName
+//----------------------------------------------------------------------------
+
+AnalysisName analysisNameFromJSON(llvm::StringRef AnalysisNameStr) {
+ return AnalysisName(AnalysisNameStr.str());
+}
+
+llvm::StringRef analysisNameToJSON(const AnalysisName &AN) { return AN.str(); }
+
+//----------------------------------------------------------------------------
+// EntityId
+//----------------------------------------------------------------------------
+
+EntityId JSONFormat::entityIdFromJSON(const uint64_t EntityIdIndex) const {
+ return makeEntityId(static_cast<size_t>(EntityIdIndex));
+}
+
+uint64_t JSONFormat::entityIdToJSON(EntityId EI) const {
+ return static_cast<uint64_t>(getIndex(EI));
+}
+
+llvm::Expected<EntityId>
+JSONFormat::entityIdFromJSONObject(const Object &EntityIdObject) {
+ if (EntityIdObject.size() != 1) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadEntityIdObject,
+ JSONEntityIdKey)
+ .build();
+ }
+
+ const llvm::json::Value *AtVal = EntityIdObject.get(JSONEntityIdKey);
+ if (!AtVal) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadEntityIdObject,
+ JSONEntityIdKey)
+ .build();
+ }
+
+ std::optional<uint64_t> OptEntityIdIndex = AtVal->getAsUINT64();
+ if (!OptEntityIdIndex) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadEntityIdObject,
+ JSONEntityIdKey)
+ .build();
+ }
+
+ return makeEntityId(static_cast<size_t>(*OptEntityIdIndex));
+}
+
+Object JSONFormat::entityIdToJSONObject(EntityId EI) {
+ Object Result;
+ Result[JSONEntityIdKey] = static_cast<uint64_t>(getIndex(EI));
+ return Result;
+}
+
+//----------------------------------------------------------------------------
+// BuildNamespaceKind
+//----------------------------------------------------------------------------
+
+llvm::Expected<BuildNamespaceKind>
+buildNamespaceKindFromJSON(llvm::StringRef BuildNamespaceKindStr) {
+ auto OptBuildNamespaceKind =
+ buildNamespaceKindFromString(BuildNamespaceKindStr);
+ if (!OptBuildNamespaceKind) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::InvalidBuildNamespaceKind,
+ BuildNamespaceKindStr)
+ .build();
+ }
+ return *OptBuildNamespaceKind;
+}
+
+// Provided for consistency with respect to rest of the codebase.
+llvm::StringRef buildNamespaceKindToJSON(BuildNamespaceKind BNK) {
+ return buildNamespaceKindToString(BNK);
+}
+
+//----------------------------------------------------------------------------
+// BuildNamespace
+//----------------------------------------------------------------------------
+
+llvm::Expected<BuildNamespace>
+JSONFormat::buildNamespaceFromJSON(const Object &BuildNamespaceObject) const {
+ auto OptBuildNamespaceKindStr = BuildNamespaceObject.getString("kind");
+ if (!OptBuildNamespaceKindStr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "BuildNamespaceKind", "kind", "string")
+ .build();
+ }
+
+ auto ExpectedKind = buildNamespaceKindFromJSON(*OptBuildNamespaceKindStr);
+ if (!ExpectedKind) {
+ return ErrorBuilder::wrap(ExpectedKind.takeError())
+ .context(ErrorMessages::ReadingFromField, "BuildNamespaceKind", "kind")
+ .build();
+ }
+
+ auto OptNameStr = BuildNamespaceObject.getString("name");
+ if (!OptNameStr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "BuildNamespaceName", "name", "string")
+ .build();
+ }
+
+ return {BuildNamespace(*ExpectedKind, *OptNameStr)};
+}
+
+Object JSONFormat::buildNamespaceToJSON(const BuildNamespace &BN) const {
+ Object Result;
+ Result["kind"] = buildNamespaceKindToJSON(getKind(BN));
+ Result["name"] = getName(BN);
+ return Result;
+}
+
+//----------------------------------------------------------------------------
+// NestedBuildNamespace
+//----------------------------------------------------------------------------
+
+llvm::Expected<NestedBuildNamespace> JSONFormat::nestedBuildNamespaceFromJSON(
+ const Array &NestedBuildNamespaceArray) const {
+ std::vector<BuildNamespace> Namespaces;
+
+ size_t NamespaceCount = NestedBuildNamespaceArray.size();
+ Namespaces.reserve(NamespaceCount);
+
+ for (const auto &[Index, BuildNamespaceValue] :
+ llvm::enumerate(NestedBuildNamespaceArray)) {
+ const Object *BuildNamespaceObject = BuildNamespaceValue.getAsObject();
+ if (!BuildNamespaceObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtIndex,
+ "BuildNamespace", Index, "object")
+ .build();
+ }
+
+ auto ExpectedBuildNamespace = buildNamespaceFromJSON(*BuildNamespaceObject);
+ if (!ExpectedBuildNamespace) {
+ return ErrorBuilder::wrap(ExpectedBuildNamespace.takeError())
+ .context(ErrorMessages::ReadingFromIndex, "BuildNamespace", Index)
+ .build();
+ }
+
+ Namespaces.push_back(std::move(*ExpectedBuildNamespace));
+ }
+
+ return NestedBuildNamespace(std::move(Namespaces));
+}
+
+Array JSONFormat::nestedBuildNamespaceToJSON(
+ const NestedBuildNamespace &NBN) const {
+ Array Result;
+ const auto &Namespaces = getNamespaces(NBN);
+ Result.reserve(Namespaces.size());
+
+ for (const auto &BN : Namespaces) {
+ Result.push_back(buildNamespaceToJSON(BN));
+ }
+
+ return Result;
+}
+
+//----------------------------------------------------------------------------
+// EntityName
+//----------------------------------------------------------------------------
+
+/// Reads "usr" and "suffix" fields from an EntityName JSON object.
+/// Shared core logic for both TU and LU entity name deserialization.
+static llvm::Expected<std::pair<llvm::StringRef, llvm::StringRef>>
+entityNameCoreFromJSON(const Object &EntityNameObject) {
+ const auto OptUSR = EntityNameObject.getString("usr");
+ if (!OptUSR) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField, "USR",
+ "usr", "string")
+ .build();
+ }
+
+ const auto OptSuffix = EntityNameObject.getString("suffix");
+ if (!OptSuffix) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "Suffix", "suffix", "string")
+ .build();
+ }
+
+ return std::make_pair(*OptUSR, *OptSuffix);
+}
+
+llvm::Expected<EntityName>
+JSONFormat::tuEntityNameFromJSON(const Object &EntityNameObject) const {
+ auto ExpectedCore = entityNameCoreFromJSON(EntityNameObject);
+ if (!ExpectedCore)
+ return ExpectedCore.takeError();
+
+ auto [USR, Suffix] = *ExpectedCore;
+ return EntityName{USR, Suffix, NestedBuildNamespace()};
+}
+
+Object JSONFormat::tuEntityNameToJSON(const EntityName &EN) const {
+ Object Result;
+ Result["usr"] = getUSR(EN);
+ Result["suffix"] = getSuffix(EN);
+ return Result;
+}
+
+llvm::Expected<EntityName>
+JSONFormat::luEntityNameFromJSON(const Object &EntityNameObject) const {
+ auto ExpectedCore = entityNameCoreFromJSON(EntityNameObject);
+ if (!ExpectedCore)
+ return ExpectedCore.takeError();
+
+ auto [USR, Suffix] = *ExpectedCore;
+
+ const Array *OptNamespaceArray = EntityNameObject.getArray("namespace");
+ if (!OptNamespaceArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "NestedBuildNamespace", "namespace", "array")
+ .build();
+ }
+
+ auto ExpectedNamespace = nestedBuildNamespaceFromJSON(*OptNamespaceArray);
+ if (!ExpectedNamespace) {
+ return ErrorBuilder::wrap(ExpectedNamespace.takeError())
+ .context(ErrorMessages::ReadingFromField, "NestedBuildNamespace",
+ "namespace")
+ .build();
+ }
+
+ return EntityName{USR, Suffix, std::move(*ExpectedNamespace)};
+}
+
+Object JSONFormat::luEntityNameToJSON(const EntityName &EN) const {
+ Object Result;
+ Result["usr"] = getUSR(EN);
+ Result["suffix"] = getSuffix(EN);
+ Result["namespace"] = nestedBuildNamespaceToJSON(getNamespace(EN));
+ return Result;
+}
+
+//----------------------------------------------------------------------------
+// EntityLinkageType
+//----------------------------------------------------------------------------
+
+llvm::Expected<EntityLinkageType>
+entityLinkageTypeFromJSON(llvm::StringRef EntityLinkageTypeStr) {
+ auto OptEntityLinkageType = entityLinkageTypeFromString(EntityLinkageTypeStr);
+ if (!OptEntityLinkageType) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::InvalidEntityLinkageType,
+ EntityLinkageTypeStr)
+ .build();
+ }
+ return *OptEntityLinkageType;
+}
+
+// Provided for consistency with respect to rest of the codebase.
+llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT) {
+ return entityLinkageTypeToString(LT);
+}
+
+//----------------------------------------------------------------------------
+// TargetTriple
+//----------------------------------------------------------------------------
+
+llvm::Error validateNormalizedTargetTriple(llvm::StringRef Triple) {
+ std::string Normalized = llvm::Triple::normalize(Triple);
+ if (Normalized != Triple) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::TargetTripleNotNormalized,
+ Triple, Normalized)
+ .build();
+ }
+ return llvm::Error::success();
+}
+
+//----------------------------------------------------------------------------
+// EntityLinkage
+//----------------------------------------------------------------------------
+
+llvm::Expected<EntityLinkage>
+JSONFormat::entityLinkageFromJSON(const Object &EntityLinkageObject) const {
+ auto OptLinkageStr = EntityLinkageObject.getString("type");
+ if (!OptLinkageStr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityLinkageType", "type", "string")
+ .build();
+ }
+
+ auto ExpectedLinkageType = entityLinkageTypeFromJSON(*OptLinkageStr);
+ if (!ExpectedLinkageType) {
+ return ErrorBuilder::wrap(ExpectedLinkageType.takeError())
+ .context(ErrorMessages::ReadingFromField, "EntityLinkageType", "type")
+ .build();
+ }
+
+ return EntityLinkage(*ExpectedLinkageType);
+}
+
+Object JSONFormat::entityLinkageToJSON(const EntityLinkage &EL) const {
+ Object Result;
+ Result["type"] = entityLinkageTypeToJSON(getLinkage(EL));
+ return Result;
+}
+
+//----------------------------------------------------------------------------
+// EntityIdTableEntry
+//----------------------------------------------------------------------------
+
+/// Shared logic for reading the "id" field from an EntityIdTableEntry object.
+static llvm::Expected<EntityId>
+entityIdTableEntryIdFromJSON(const Object &EntityIdTableEntryObject,
+ llvm::function_ref<EntityId(uint64_t)> MakeId) {
+ const Value *EntityIdIntValue = EntityIdTableEntryObject.get("id");
+ if (!EntityIdIntValue) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityId", "id",
+ "number (unsigned 64-bit integer)")
+ .build();
+ }
+
+ const std::optional<uint64_t> OptEntityIdInt =
+ EntityIdIntValue->getAsUINT64();
+ if (!OptEntityIdInt) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityId", "id",
+ "number (unsigned 64-bit integer)")
+ .build();
+ }
+
+ return MakeId(*OptEntityIdInt);
+}
+
+llvm::Expected<std::pair<EntityName, EntityId>>
+JSONFormat::tuEntityIdTableEntryFromJSON(
+ const Object &EntityIdTableEntryObject) const {
+
+ const Object *OptEntityNameObject =
+ EntityIdTableEntryObject.getObject("name");
+ if (!OptEntityNameObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityName", "name", "object")
+ .build();
+ }
+
+ auto ExpectedEntityName = tuEntityNameFromJSON(*OptEntityNameObject);
+ if (!ExpectedEntityName) {
+ return ErrorBuilder::wrap(ExpectedEntityName.takeError())
+ .context(ErrorMessages::ReadingFromField, "EntityName", "name")
+ .build();
+ }
+
+ auto ExpectedId = entityIdTableEntryIdFromJSON(
+ EntityIdTableEntryObject,
+ [this](uint64_t V) { return entityIdFromJSON(V); });
+ if (!ExpectedId)
+ return ExpectedId.takeError();
+
+ return std::make_pair(std::move(*ExpectedEntityName), std::move(*ExpectedId));
+}
+
+Object JSONFormat::tuEntityIdTableEntryToJSON(const EntityName &EN,
+ EntityId EI) const {
+ Object Entry;
+ Entry["id"] = entityIdToJSON(EI);
+ Entry["name"] = tuEntityNameToJSON(EN);
+ return Entry;
+}
+
+llvm::Expected<std::pair<EntityName, EntityId>>
+JSONFormat::luEntityIdTableEntryFromJSON(
+ const Object &EntityIdTableEntryObject) const {
+
+ const Object *OptEntityNameObject =
+ EntityIdTableEntryObject.getObject("name");
+ if (!OptEntityNameObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityName", "name", "object")
+ .build();
+ }
+
+ auto ExpectedEntityName = luEntityNameFromJSON(*OptEntityNameObject);
+ if (!ExpectedEntityName) {
+ return ErrorBuilder::wrap(ExpectedEntityName.takeError())
+ .context(ErrorMessages::ReadingFromField, "EntityName", "name")
+ .build();
+ }
+
+ auto ExpectedId = entityIdTableEntryIdFromJSON(
+ EntityIdTableEntryObject,
+ [this](uint64_t V) { return entityIdFromJSON(V); });
+ if (!ExpectedId)
+ return ExpectedId.takeError();
+
+ return std::make_pair(std::move(*ExpectedEntityName), std::move(*ExpectedId));
+}
+
+Object JSONFormat::luEntityIdTableEntryToJSON(const EntityName &EN,
+ EntityId EI) const {
+ Object Entry;
+ Entry["id"] = entityIdToJSON(EI);
+ Entry["name"] = luEntityNameToJSON(EN);
+ return Entry;
+}
+
+//----------------------------------------------------------------------------
+// EntityIdTable
+//----------------------------------------------------------------------------
+
+/// Shared logic for deserializing an EntityIdTable from a JSON array.
+/// \p EntryReader is called for each entry object to produce an
+/// (EntityName, EntityId) pair.
+static llvm::Expected<EntityIdTable> entityIdTableFromJSONImpl(
+ const Array &EntityIdTableArray,
+ llvm::function_ref<
+ llvm::Expected<std::pair<EntityName, EntityId>>(const Object &)>
+ EntryReader,
+ llvm::function_ref<std::map<EntityName, EntityId> &(EntityIdTable &)>
+ GetEntities) {
+ EntityIdTable IdTable;
+ std::map<EntityName, EntityId> &Entities = GetEntities(IdTable);
+
+ for (const auto &[Index, EntityIdTableEntryValue] :
+ llvm::enumerate(EntityIdTableArray)) {
+ const Object *OptEntityIdTableEntryObject =
+ EntityIdTableEntryValue.getAsObject();
+ if (!OptEntityIdTableEntryObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtIndex,
+ "EntityIdTable entry", Index, "object")
+ .build();
+ }
+
+ auto ExpectedEntityIdTableEntry = EntryReader(*OptEntityIdTableEntryObject);
+ if (!ExpectedEntityIdTableEntry) {
+ return ErrorBuilder::wrap(ExpectedEntityIdTableEntry.takeError())
+ .context(ErrorMessages::ReadingFromIndex, "EntityIdTable entry",
+ Index)
+ .build();
+ }
+
+ auto [EntityIt, EntityInserted] =
+ Entities.emplace(std::move(*ExpectedEntityIdTableEntry));
+ if (!EntityInserted) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedInsertionOnDuplication,
+ "EntityIdTable entry", Index,
+ EntityIt->second)
+ .build();
+ }
+ }
+
+ return IdTable;
+}
+
+llvm::Expected<EntityIdTable>
+JSONFormat::tuEntityIdTableFromJSON(const Array &EntityIdTableArray) const {
+ return entityIdTableFromJSONImpl(
+ EntityIdTableArray,
+ [this](const Object &O) { return tuEntityIdTableEntryFromJSON(O); },
+ [](EntityIdTable &T) -> std::map<EntityName, EntityId> & {
+ return getEntities(T);
+ });
+}
+
+Array JSONFormat::tuEntityIdTableToJSON(const EntityIdTable &IdTable) const {
+ Array EntityIdTableArray;
+ const auto &Entities = getEntities(IdTable);
+ EntityIdTableArray.reserve(Entities.size());
+
+ for (const auto &[EntityName, EntityId] : Entities) {
+ EntityIdTableArray.push_back(
+ tuEntityIdTableEntryToJSON(EntityName, EntityId));
+ }
+
+ return EntityIdTableArray;
+}
+
+llvm::Expected<EntityIdTable>
+JSONFormat::luEntityIdTableFromJSON(const Array &EntityIdTableArray) const {
+ return entityIdTableFromJSONImpl(
+ EntityIdTableArray,
+ [this](const Object &O) { return luEntityIdTableEntryFromJSON(O); },
+ [](EntityIdTable &T) -> std::map<EntityName, EntityId> & {
+ return getEntities(T);
+ });
+}
+
+Array JSONFormat::luEntityIdTableToJSON(const EntityIdTable &IdTable) const {
+ Array EntityIdTableArray;
+ const auto &Entities = getEntities(IdTable);
+ EntityIdTableArray.reserve(Entities.size());
+
+ for (const auto &[EntityName, EntityId] : Entities) {
+ EntityIdTableArray.push_back(
+ luEntityIdTableEntryToJSON(EntityName, EntityId));
+ }
+
+ return EntityIdTableArray;
+}
+
+//----------------------------------------------------------------------------
+// LinkageTableEntry
+//----------------------------------------------------------------------------
+
+llvm::Expected<std::pair<EntityId, EntityLinkage>>
+JSONFormat::linkageTableEntryFromJSON(
+ const Object &LinkageTableEntryObject) const {
+ const Value *EntityIdIntValue = LinkageTableEntryObject.get("id");
+ if (!EntityIdIntValue) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityId", "id",
+ "number (unsigned 64-bit integer)")
+ .build();
+ }
+
+ const std::optional<uint64_t> OptEntityIdInt =
+ EntityIdIntValue->getAsUINT64();
+ if (!OptEntityIdInt) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityId", "id",
+ "number (unsigned 64-bit integer)")
+ .build();
+ }
+
+ EntityId EI = entityIdFromJSON(*OptEntityIdInt);
+
+ const Object *OptEntityLinkageObject =
+ LinkageTableEntryObject.getObject("linkage");
+ if (!OptEntityLinkageObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityLinkage", "linkage", "object")
+ .build();
+ }
+
+ auto ExpectedEntityLinkage = entityLinkageFromJSON(*OptEntityLinkageObject);
+ if (!ExpectedEntityLinkage) {
+ return ErrorBuilder::wrap(ExpectedEntityLinkage.takeError())
+ .context(ErrorMessages::ReadingFromField, "EntityLinkage", "linkage")
+ .build();
+ }
+
+ return std::make_pair(std::move(EI), std::move(*ExpectedEntityLinkage));
+}
+
+Object JSONFormat::linkageTableEntryToJSON(EntityId EI,
+ const EntityLinkage &EL) const {
+ Object Entry;
+ Entry["id"] = entityIdToJSON(EI);
+ Entry["linkage"] = entityLinkageToJSON(EL);
+ return Entry;
+}
+
+//----------------------------------------------------------------------------
+// LinkageTable
+//----------------------------------------------------------------------------
+
+// ExpectedIds is the set of EntityIds from the IdTable that must appear in the
+// linkage table—no more, no fewer. It is taken by value because it is consumed
+// during parsing: each successfully matched id is erased from the set, and any
+// ids remaining at the end are reported as missing.
+llvm::Expected<std::map<EntityId, EntityLinkage>>
+JSONFormat::linkageTableFromJSON(const Array &LinkageTableArray,
+ std::set<EntityId> ExpectedIds) const {
+ std::map<EntityId, EntityLinkage> LinkageTable;
+
+ for (const auto &[Index, LinkageTableEntryValue] :
+ llvm::enumerate(LinkageTableArray)) {
+ const Object *OptLinkageTableEntryObject =
+ LinkageTableEntryValue.getAsObject();
+ if (!OptLinkageTableEntryObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtIndex,
+ "LinkageTable entry", Index, "object")
+ .build();
+ }
+
+ auto ExpectedLinkageTableEntry =
+ linkageTableEntryFromJSON(*OptLinkageTableEntryObject);
+ if (!ExpectedLinkageTableEntry) {
+ return ErrorBuilder::wrap(ExpectedLinkageTableEntry.takeError())
+ .context(ErrorMessages::ReadingFromIndex, "LinkageTable entry", Index)
+ .build();
+ }
+
+ const EntityId EI = ExpectedLinkageTableEntry->first;
+
+ auto [It, Inserted] =
+ LinkageTable.insert(std::move(*ExpectedLinkageTableEntry));
+ if (!Inserted) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedInsertionOnDuplication,
+ "LinkageTable entry", Index, It->first)
+ .build();
+ }
+
+ if (ExpectedIds.erase(EI) == 0) {
+ return ErrorBuilder::create(
+ std::errc::invalid_argument,
+ ErrorMessages::FailedToDeserializeLinkageTableExtraId, EI)
+ .context(ErrorMessages::ReadingFromIndex, "LinkageTable entry", Index)
+ .build();
+ }
+ }
+
+ if (!ExpectedIds.empty()) {
+ return ErrorBuilder::create(
+ std::errc::invalid_argument,
+ ErrorMessages::FailedToDeserializeLinkageTableMissingId,
+ *ExpectedIds.begin())
+ .build();
+ }
+
+ return LinkageTable;
+}
+
+Array JSONFormat::linkageTableToJSON(
+ const std::map<EntityId, EntityLinkage> &LinkageTable) const {
+ Array Result;
+ Result.reserve(LinkageTable.size());
+
+ for (const auto &[EI, EL] : LinkageTable) {
+ Result.push_back(linkageTableEntryToJSON(EI, EL));
+ }
+
+ return Result;
+}
+
+//----------------------------------------------------------------------------
+// EntitySummary
+//----------------------------------------------------------------------------
+
+llvm::Expected<std::unique_ptr<EntitySummary>>
+JSONFormat::entitySummaryFromJSON(const SummaryName &SN,
+ const Object &EntitySummaryObject,
+ EntityIdTable &IdTable) const {
+ auto InfoIt = FormatInfos.find(SN);
+ if (InfoIt == FormatInfos.end()) {
+ return ErrorBuilder::create(
+ std::errc::invalid_argument,
+ ErrorMessages::FailedToDeserializeEntitySummaryNoFormatInfo, SN)
+ .build();
+ }
+
+ const auto &InfoEntry = InfoIt->second;
+ assert(InfoEntry.ForSummary == SN);
+
+ return InfoEntry.Deserialize(EntitySummaryObject, IdTable,
+ entityIdFromJSONObject);
+}
+
+llvm::Expected<Object>
+JSONFormat::entitySummaryToJSON(const SummaryName &SN,
+ const EntitySummary &ES) const {
+ auto InfoIt = FormatInfos.find(SN);
+ if (InfoIt == FormatInfos.end()) {
+ return ErrorBuilder::create(
+ std::errc::invalid_argument,
+ ErrorMessages::FailedToSerializeEntitySummaryNoFormatInfo, SN)
+ .build();
+ }
+
+ const auto &InfoEntry = InfoIt->second;
+ assert(InfoEntry.ForSummary == SN);
+
+ return InfoEntry.Serialize(ES, entityIdToJSONObject);
+}
+
+//----------------------------------------------------------------------------
+// EntityDataMapEntry
+//----------------------------------------------------------------------------
+
+llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummary>>>
+JSONFormat::entityDataMapEntryFromJSON(const Object &EntityDataMapEntryObject,
+ const SummaryName &SN,
+ EntityIdTable &IdTable) const {
+
+ const Value *EntityIdIntValue = EntityDataMapEntryObject.get("entity_id");
+ if (!EntityIdIntValue) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityId", "entity_id",
+ "number (unsigned 64-bit integer)")
+ .build();
+ }
+
+ const std::optional<uint64_t> OptEntityIdInt =
+ EntityIdIntValue->getAsUINT64();
+ if (!OptEntityIdInt) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityId", "entity_id",
+ "number (unsigned 64-bit integer)")
+ .build();
+ }
+
+ EntityId EI = entityIdFromJSON(*OptEntityIdInt);
+
+ const Object *OptEntitySummaryObject =
+ EntityDataMapEntryObject.getObject("entity_summary");
+ if (!OptEntitySummaryObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntitySummary", "entity_summary", "object")
+ .build();
+ }
+
+ auto ExpectedEntitySummary =
+ entitySummaryFromJSON(SN, *OptEntitySummaryObject, IdTable);
+ if (!ExpectedEntitySummary) {
+ return ErrorBuilder::wrap(ExpectedEntitySummary.takeError())
+ .context(ErrorMessages::ReadingFromField, "EntitySummary",
+ "entity_summary")
+ .build();
+ }
+
+ if (*ExpectedEntitySummary == nullptr) {
+ return ErrorBuilder::create(
+ std::errc::invalid_argument,
+ ErrorMessages::FailedToDeserializeEntitySummaryMissingData, SN)
+ .build();
+ }
+
+ auto ActualSN = (*ExpectedEntitySummary)->getSummaryName();
+ if (SN != ActualSN) {
+ return ErrorBuilder::create(
+ std::errc::invalid_argument,
+ ErrorMessages::
+ FailedToDeserializeEntitySummaryMismatchedSummaryName,
+ SN, ActualSN)
+ .build();
+ }
+
+ return std::make_pair(std::move(EI), std::move(*ExpectedEntitySummary));
+}
+
+llvm::Expected<Object> JSONFormat::entityDataMapEntryToJSON(
+ const EntityId EI, const std::unique_ptr<EntitySummary> &EntitySummary,
+ const SummaryName &SN) const {
+ Object Entry;
+
+ Entry["entity_id"] = entityIdToJSON(EI);
+
+ if (!EntitySummary) {
+ ErrorBuilder::fatal(
+ ErrorMessages::FailedToSerializeEntitySummaryMissingData, SN);
+ }
+
+ const auto ActualSN = EntitySummary->getSummaryName();
+ if (SN != ActualSN) {
+ ErrorBuilder::fatal(
+ ErrorMessages::FailedToSerializeEntitySummaryMismatchedSummaryName, SN,
+ ActualSN);
+ }
+
+ auto ExpectedEntitySummaryObject = entitySummaryToJSON(SN, *EntitySummary);
+ if (!ExpectedEntitySummaryObject) {
+ return ErrorBuilder::wrap(ExpectedEntitySummaryObject.takeError())
+ .context(ErrorMessages::WritingToField, "EntitySummary",
+ "entity_summary")
+ .build();
+ }
+
+ Entry["entity_summary"] = std::move(*ExpectedEntitySummaryObject);
+
+ return Entry;
+}
+
+//----------------------------------------------------------------------------
+// EntityDataMap
+//----------------------------------------------------------------------------
+
+llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummary>>>
+JSONFormat::entityDataMapFromJSON(const SummaryName &SN,
+ const Array &EntityDataArray,
+ EntityIdTable &IdTable) const {
+ std::map<EntityId, std::unique_ptr<EntitySummary>> EntityDataMap;
+
+ for (const auto &[Index, EntityDataMapEntryValue] :
+ llvm::enumerate(EntityDataArray)) {
+ const Object *OptEntityDataMapEntryObject =
+ EntityDataMapEntryValue.getAsObject();
+ if (!OptEntityDataMapEntryObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtIndex,
+ "EntitySummary entry", Index, "object")
+ .build();
+ }
+
+ auto ExpectedEntityDataMapEntry =
+ entityDataMapEntryFromJSON(*OptEntityDataMapEntryObject, SN, IdTable);
+ if (!ExpectedEntityDataMapEntry) {
+ return ErrorBuilder::wrap(ExpectedEntityDataMapEntry.takeError())
+ .context(ErrorMessages::ReadingFromIndex, "EntitySummary entry",
+ Index)
+ .build();
+ }
+
+ auto [DataIt, DataInserted] =
+ EntityDataMap.insert(std::move(*ExpectedEntityDataMapEntry));
+ if (!DataInserted) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedInsertionOnDuplication,
+ "EntitySummary entry", Index, DataIt->first)
+ .build();
+ }
+ }
+
+ return std::move(EntityDataMap);
+}
+
+llvm::Expected<Array> JSONFormat::entityDataMapToJSON(
+ const SummaryName &SN,
+ const std::map<EntityId, std::unique_ptr<EntitySummary>> &EntityDataMap)
+ const {
+ Array Result;
+ Result.reserve(EntityDataMap.size());
+
+ for (const auto &[Index, EntityDataMapEntry] :
+ llvm::enumerate(EntityDataMap)) {
+ const auto &[EntityId, EntitySummary] = EntityDataMapEntry;
+
+ auto ExpectedEntityDataMapEntryObject =
+ entityDataMapEntryToJSON(EntityId, EntitySummary, SN);
+
+ if (!ExpectedEntityDataMapEntryObject) {
+ return ErrorBuilder::wrap(ExpectedEntityDataMapEntryObject.takeError())
+ .context(ErrorMessages::WritingToIndex, "EntitySummary entry", Index)
+ .build();
+ }
+
+ Result.push_back(std::move(*ExpectedEntityDataMapEntryObject));
+ }
+
+ return Result;
+}
+
+//----------------------------------------------------------------------------
+// SummaryDataMapEntry
+//----------------------------------------------------------------------------
+
+llvm::Expected<
+ std::pair<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>>
+JSONFormat::summaryDataMapEntryFromJSON(const Object &SummaryDataMapEntryObject,
+ EntityIdTable &IdTable) const {
+
+ std::optional<llvm::StringRef> OptSummaryNameStr =
+ SummaryDataMapEntryObject.getString("summary_name");
+ if (!OptSummaryNameStr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "SummaryName", "summary_name", "string")
+ .build();
+ }
+
+ SummaryName SN = summaryNameFromJSON(*OptSummaryNameStr);
+
+ const Array *OptEntityDataArray =
+ SummaryDataMapEntryObject.getArray("summary_data");
+ if (!OptEntityDataArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntitySummary entries", "summary_data",
+ "array")
+ .build();
+ }
+
+ auto ExpectedEntityDataMap =
+ entityDataMapFromJSON(SN, *OptEntityDataArray, IdTable);
+ if (!ExpectedEntityDataMap) {
+ return ErrorBuilder::wrap(ExpectedEntityDataMap.takeError())
+ .context(ErrorMessages::ReadingFromField, "EntitySummary entries",
+ "summary_data")
+ .build();
+ }
+
+ return std::make_pair(std::move(SN), std::move(*ExpectedEntityDataMap));
+}
+
+llvm::Expected<Object> JSONFormat::summaryDataMapEntryToJSON(
+ const SummaryName &SN,
+ const std::map<EntityId, std::unique_ptr<EntitySummary>> &SD) const {
+ Object Result;
+
+ Result["summary_name"] = summaryNameToJSON(SN);
+
+ auto ExpectedSummaryDataArray = entityDataMapToJSON(SN, SD);
+ if (!ExpectedSummaryDataArray) {
+ return ErrorBuilder::wrap(ExpectedSummaryDataArray.takeError())
+ .context(ErrorMessages::WritingToField, "EntitySummary entries",
+ "summary_data")
+ .build();
+ }
+
+ Result["summary_data"] = std::move(*ExpectedSummaryDataArray);
+
+ return Result;
+}
+
+//----------------------------------------------------------------------------
+// SummaryDataMap
+//----------------------------------------------------------------------------
+
+llvm::Expected<
+ std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>>
+JSONFormat::summaryDataMapFromJSON(const Array &SummaryDataArray,
+ EntityIdTable &IdTable) const {
+ std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>
+ SummaryDataMap;
+
+ for (const auto &[Index, SummaryDataMapEntryValue] :
+ llvm::enumerate(SummaryDataArray)) {
+ const Object *OptSummaryDataMapEntryObject =
+ SummaryDataMapEntryValue.getAsObject();
+ if (!OptSummaryDataMapEntryObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtIndex,
+ "SummaryData entry", Index, "object")
+ .build();
+ }
+
+ auto ExpectedSummaryDataMapEntry =
+ summaryDataMapEntryFromJSON(*OptSummaryDataMapEntryObject, IdTable);
+ if (!ExpectedSummaryDataMapEntry) {
+ return ErrorBuilder::wrap(ExpectedSummaryDataMapEntry.takeError())
+ .context(ErrorMessages::ReadingFromIndex, "SummaryData entry", Index)
+ .build();
+ }
+
+ auto [SummaryIt, SummaryInserted] =
+ SummaryDataMap.emplace(std::move(*ExpectedSummaryDataMapEntry));
+ if (!SummaryInserted) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedInsertionOnDuplication,
+ "SummaryData entry", Index, SummaryIt->first)
+ .build();
+ }
+ }
+
+ return std::move(SummaryDataMap);
+}
+
+llvm::Expected<Array> JSONFormat::summaryDataMapToJSON(
+ const std::map<SummaryName,
+ std::map<EntityId, std::unique_ptr<EntitySummary>>>
+ &SummaryDataMap) const {
+ Array Result;
+ Result.reserve(SummaryDataMap.size());
+
+ for (const auto &[Index, SummaryDataMapEntry] :
+ llvm::enumerate(SummaryDataMap)) {
+ const auto &[SummaryName, DataMap] = SummaryDataMapEntry;
+
+ auto ExpectedSummaryDataMapObject =
+ summaryDataMapEntryToJSON(SummaryName, DataMap);
+ if (!ExpectedSummaryDataMapObject) {
+ return ErrorBuilder::wrap(ExpectedSummaryDataMapObject.takeError())
+ .context(ErrorMessages::WritingToIndex, "SummaryData entry", Index)
+ .build();
+ }
+
+ Result.push_back(std::move(*ExpectedSummaryDataMapObject));
+ }
+
+ return std::move(Result);
+}
+
+//----------------------------------------------------------------------------
+// EncodingDataMapEntry
+//----------------------------------------------------------------------------
+
+llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
+JSONFormat::encodingDataMapEntryFromJSON(
+ const Object &EntityDataMapEntryObject) const {
+ const Value *EntityIdIntValue = EntityDataMapEntryObject.get("entity_id");
+ if (!EntityIdIntValue) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityId", "entity_id",
+ "number (unsigned 64-bit integer)")
+ .build();
+ }
+
+ const std::optional<uint64_t> OptEntityIdInt =
+ EntityIdIntValue->getAsUINT64();
+ if (!OptEntityIdInt) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntityId", "entity_id",
+ "number (unsigned 64-bit integer)")
+ .build();
+ }
+
+ EntityId EI = entityIdFromJSON(*OptEntityIdInt);
+
+ const Object *OptEntitySummaryObject =
+ EntityDataMapEntryObject.getObject("entity_summary");
+ if (!OptEntitySummaryObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntitySummary", "entity_summary", "object")
+ .build();
+ }
+
+ std::unique_ptr<EntitySummaryEncoding> Encoding(
+ new JSONEntitySummaryEncoding(Value(Object(*OptEntitySummaryObject))));
+
+ return std::make_pair(std::move(EI), std::move(Encoding));
+}
+
+Object JSONFormat::encodingDataMapEntryToJSON(
+ EntityId EI, const std::unique_ptr<EntitySummaryEncoding> &Encoding) const {
+ Object Entry;
+ Entry["entity_id"] = entityIdToJSON(EI);
+
+ // All EntitySummaryEncoding objects stored in a TUSummaryEncoding or
+ // LUSummaryEncoding read by JSONFormat are JSONEntitySummaryEncoding
+ // instances, since encodingDataMapEntryFromJSON is the only place that
+ // creates them.
+ auto *JSONEncoding = static_cast<JSONEntitySummaryEncoding *>(Encoding.get());
+ Entry["entity_summary"] = JSONEncoding->Data;
+
+ return Entry;
+}
+
+//----------------------------------------------------------------------------
+// EncodingDataMap
+//----------------------------------------------------------------------------
+
+llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
+JSONFormat::encodingDataMapFromJSON(const Array &EntityDataArray) const {
+ std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>> EncodingDataMap;
+
+ for (const auto &[Index, EntityDataMapEntryValue] :
+ llvm::enumerate(EntityDataArray)) {
+ const Object *OptEntityDataMapEntryObject =
+ EntityDataMapEntryValue.getAsObject();
+ if (!OptEntityDataMapEntryObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtIndex,
+ "EntitySummary entry", Index, "object")
+ .build();
+ }
+
+ auto ExpectedEntry =
+ encodingDataMapEntryFromJSON(*OptEntityDataMapEntryObject);
+ if (!ExpectedEntry) {
+ return ErrorBuilder::wrap(ExpectedEntry.takeError())
+ .context(ErrorMessages::ReadingFromIndex, "EntitySummary entry",
+ Index)
+ .build();
+ }
+
+ auto [DataIt, DataInserted] =
+ EncodingDataMap.insert(std::move(*ExpectedEntry));
+ if (!DataInserted) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedInsertionOnDuplication,
+ "EntitySummary entry", Index, DataIt->first)
+ .build();
+ }
+ }
+
+ return std::move(EncodingDataMap);
+}
+
+Array JSONFormat::encodingDataMapToJSON(
+ const std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>
+ &EncodingDataMap) const {
+ Array Result;
+ Result.reserve(EncodingDataMap.size());
+
+ for (const auto &[EI, Encoding] : EncodingDataMap) {
+ Result.push_back(encodingDataMapEntryToJSON(EI, Encoding));
+ }
+
+ return Result;
+}
+
+//----------------------------------------------------------------------------
+// EncodingSummaryDataMapEntry
+//----------------------------------------------------------------------------
+
+llvm::Expected<std::pair<
+ SummaryName, std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>>
+JSONFormat::encodingSummaryDataMapEntryFromJSON(
+ const Object &SummaryDataMapEntryObject) const {
+ std::optional<llvm::StringRef> OptSummaryNameStr =
+ SummaryDataMapEntryObject.getString("summary_name");
+ if (!OptSummaryNameStr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "SummaryName", "summary_name", "string")
+ .build();
+ }
+
+ SummaryName SN = summaryNameFromJSON(*OptSummaryNameStr);
+
+ const Array *OptEntityDataArray =
+ SummaryDataMapEntryObject.getArray("summary_data");
+ if (!OptEntityDataArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "EntitySummary entries", "summary_data",
+ "array")
+ .build();
+ }
+
+ auto ExpectedEncodingDataMap = encodingDataMapFromJSON(*OptEntityDataArray);
+ if (!ExpectedEncodingDataMap) {
+ return ErrorBuilder::wrap(ExpectedEncodingDataMap.takeError())
+ .context(ErrorMessages::ReadingFromField, "EntitySummary entries",
+ "summary_data")
+ .build();
+ }
+
+ return std::make_pair(std::move(SN), std::move(*ExpectedEncodingDataMap));
+}
+
+Object JSONFormat::encodingSummaryDataMapEntryToJSON(
+ const SummaryName &SN,
+ const std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>
+ &EncodingMap) const {
+ Object Result;
+
+ Result["summary_name"] = summaryNameToJSON(SN);
+ Result["summary_data"] = encodingDataMapToJSON(EncodingMap);
+
+ return Result;
+}
+
+//----------------------------------------------------------------------------
+// EncodingSummaryDataMap
+//----------------------------------------------------------------------------
+
+llvm::Expected<std::map<
+ SummaryName, std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>>
+JSONFormat::encodingSummaryDataMapFromJSON(
+ const Array &SummaryDataArray) const {
+ std::map<SummaryName,
+ std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
+ EncodingSummaryDataMap;
+
+ for (const auto &[Index, SummaryDataMapEntryValue] :
+ llvm::enumerate(SummaryDataArray)) {
+ const Object *OptSummaryDataMapEntryObject =
+ SummaryDataMapEntryValue.getAsObject();
+ if (!OptSummaryDataMapEntryObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtIndex,
+ "SummaryData entry", Index, "object")
+ .build();
+ }
+
+ auto ExpectedEntry =
+ encodingSummaryDataMapEntryFromJSON(*OptSummaryDataMapEntryObject);
+ if (!ExpectedEntry) {
+ return ErrorBuilder::wrap(ExpectedEntry.takeError())
+ .context(ErrorMessages::ReadingFromIndex, "SummaryData entry", Index)
+ .build();
+ }
+
+ auto [SummaryIt, SummaryInserted] =
+ EncodingSummaryDataMap.emplace(std::move(*ExpectedEntry));
+ if (!SummaryInserted) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedInsertionOnDuplication,
+ "SummaryData entry", Index, SummaryIt->first)
+ .build();
+ }
+ }
+
+ return std::move(EncodingSummaryDataMap);
+}
+
+Array JSONFormat::encodingSummaryDataMapToJSON(
+ const std::map<SummaryName,
+ std::map<EntityId, std::unique_ptr<EntitySummaryEncoding>>>
+ &EncodingSummaryDataMap) const {
+ Array Result;
+ Result.reserve(EncodingSummaryDataMap.size());
+
+ for (const auto &[SN, EncodingMap] : EncodingSummaryDataMap) {
+ Result.push_back(encodingSummaryDataMapEntryToJSON(SN, EncodingMap));
+ }
+
+ return Result;
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.h b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.h
new file mode 100644
index 0000000000000..191be83ccb0e5
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/JSONFormatImpl.h
@@ -0,0 +1,219 @@
+//===- JSONFormatImpl.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Internal implementation header shared by all translation units in the
+// JSONFormat subdirectory. Not part of the public API.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_ScalableStaticAnalysis_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
+#define LLVM_CLANG_LIB_ScalableStaticAnalysis_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
+
+#include "../../ModelStringConversions.h"
+#include "JSONEntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Registry.h"
+
+namespace clang::ssaf {
+
+using Array = llvm::json::Array;
+using Object = llvm::json::Object;
+using Value = llvm::json::Value;
+
+//----------------------------------------------------------------------------
+// File Format Constant
+//----------------------------------------------------------------------------
+
+inline constexpr const char *JSONFormatFileExtension = ".json";
+
+//----------------------------------------------------------------------------
+// Error Message Constants
+//----------------------------------------------------------------------------
+
+namespace ErrorMessages {
+
+inline constexpr const char *FailedToReadFile =
+ "failed to read file '{0}': {1}";
+inline constexpr const char *FailedToWriteFile =
+ "failed to write file '{0}': {1}";
+inline constexpr const char *FileNotFound = "file does not exist";
+inline constexpr const char *FileIsDirectory =
+ "path is a directory, not a file";
+inline constexpr const char *FileIsNotJSON =
+ "file does not end with '{0}' extension";
+inline constexpr const char *FileExists = "file already exists";
+inline constexpr const char *ParentDirectoryNotFound =
+ "parent directory does not exist";
+
+inline constexpr const char *ReadingFromField = "reading {0} from field '{1}'";
+inline constexpr const char *WritingToField = "writing {0} to field '{1}'";
+inline constexpr const char *ReadingFromIndex = "reading {0} from index '{1}'";
+inline constexpr const char *WritingToIndex = "writing {0} to index '{1}'";
+inline constexpr const char *ReadingFromFile = "reading {0} from file '{1}'";
+inline constexpr const char *WritingToFile = "writing {0} to file '{1}'";
+
+inline constexpr const char *FailedInsertionOnDuplication =
+ "failed to insert {0} at index '{1}': encountered duplicate '{2}'";
+
+inline constexpr const char *FailedToReadObject =
+ "failed to read {0}: expected JSON {1}";
+inline constexpr const char *FailedToReadObjectAtField =
+ "failed to read {0} from field '{1}': expected JSON {2}";
+inline constexpr const char *FailedToReadObjectAtIndex =
+ "failed to read {0} from index '{1}': expected JSON {2}";
+
+inline constexpr const char *MismatchedSummaryType =
+ "expected '{0}' for field '{1}' but got '{2}'";
+inline constexpr const char *UnknownArtifactType =
+ "unknown value '{0}' for field '{1}': expected '{2}', '{3}', or '{4}'";
+inline constexpr const char *UnknownArtifactEncodingType =
+ "unknown value '{0}' for field '{1}': expected '{2}', or '{3}'";
+
+inline constexpr const char *FailedToDeserializeEntitySummaryNoFormatInfo =
+ "failed to deserialize EntitySummary: no FormatInfo registered for '{0}'";
+inline constexpr const char *FailedToSerializeEntitySummaryNoFormatInfo =
+ "failed to serialize EntitySummary: no FormatInfo registered for '{0}'";
+
+inline constexpr const char *FailedToDeserializeEntitySummaryMissingData =
+ "failed to deserialize EntitySummary: null EntitySummary data for '{0}'";
+inline constexpr const char *FailedToSerializeEntitySummaryMissingData =
+ "JSONFormat - null EntitySummary data for '{0}'";
+
+inline constexpr const char
+ *FailedToDeserializeEntitySummaryMismatchedSummaryName =
+ "failed to deserialize EntitySummary: EntitySummary data for '{0}' "
+ "reports mismatched '{1}'";
+inline constexpr const char
+ *FailedToSerializeEntitySummaryMismatchedSummaryName =
+ "JSONFormat - EntitySummary data for '{0}' reports mismatched '{1}'";
+
+inline constexpr const char *InvalidBuildNamespaceKind =
+ "invalid BuildNamespaceKind value '{0}' for field 'kind'";
+
+inline constexpr const char *InvalidEntityLinkageType =
+ "invalid EntityLinkageType value '{0}' for field 'type'";
+
+inline constexpr const char *FailedToDeserializeLinkageTableExtraId =
+ "failed to deserialize LinkageTable: extra '{0}' not present in IdTable";
+
+inline constexpr const char *FailedToDeserializeLinkageTableMissingId =
+ "failed to deserialize LinkageTable: missing '{0}' present in IdTable";
+
+inline constexpr const char *FailedToReadEntityIdObject =
+ "failed to read EntityId: expected JSON object with a single '{0}' key "
+ "mapped to a number (unsigned 64-bit integer)";
+
+inline constexpr const char *FailedToPatchEntityIdNotInTable =
+ "failed to patch EntityId: '{0}' not found in entity resolution table";
+
+inline constexpr const char *TargetTripleNotNormalized =
+ "target triple '{0}' is not in normalized form (expected '{1}')";
+
+} // namespace ErrorMessages
+
+//----------------------------------------------------------------------------
+// Entity Id JSON Representation
+//----------------------------------------------------------------------------
+
+/// An entity ID is encoded as the single-key object {"@": <index>}.
+inline constexpr const char *JSONEntityIdKey = "@";
+
+//----------------------------------------------------------------------------
+// Summary Type JSON Representation
+//----------------------------------------------------------------------------
+
+/// Root-object key naming the summary kind so files are self-describing.
+inline constexpr const char *JSONTypeKey = "type";
+
+/// Value written to \c JSONTypeKey for serialized \c TUSummary files.
+inline constexpr const char *JSONTypeValueTUSummary = "TUSummary";
+
+/// Value written to \c JSONTypeKey for serialized \c LUSummary files.
+inline constexpr const char *JSONTypeValueLUSummary = "LUSummary";
+
+/// Value written to \c JSONTypeKey for serialized \c WPASuite files.
+inline constexpr const char *JSONTypeValueWPASuite = "WPASuite";
+
+/// Reads the \c JSONTypeKey field from the root object and verifies it
+/// equals \p ExpectedType. Returns success or an error with the field
+/// missing/mismatch detail.
+llvm::Error checkSummaryType(const Object &RootObject,
+ llvm::StringRef ExpectedType);
+
+/// Reads the \c JSONTypeKey field from the root object as a string.
+/// Returns the string on success; on error, the message is suitable for
+/// callers that want to report the missing field themselves.
+llvm::Expected<llvm::StringRef> readSummaryType(const Object &RootObject);
+
+//----------------------------------------------------------------------------
+// JSON Reader and Writer
+//----------------------------------------------------------------------------
+
+llvm::Expected<Value> readJSON(llvm::StringRef Path);
+llvm::Error writeJSON(Value &&V, llvm::StringRef Path);
+
+//----------------------------------------------------------------------------
+// SummaryName helpers (free functions, anonymous-namespace in .cpp)
+//----------------------------------------------------------------------------
+
+SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr);
+llvm::StringRef summaryNameToJSON(const SummaryName &SN);
+
+//----------------------------------------------------------------------------
+// AnalysisName helpers
+//----------------------------------------------------------------------------
+
+AnalysisName analysisNameFromJSON(llvm::StringRef AnalysisNameStr);
+llvm::StringRef analysisNameToJSON(const AnalysisName &AN);
+
+//----------------------------------------------------------------------------
+// BuildNamespaceKind helpers
+//----------------------------------------------------------------------------
+
+llvm::Expected<BuildNamespaceKind>
+buildNamespaceKindFromJSON(llvm::StringRef BuildNamespaceKindStr);
+
+// Provided for consistency with respect to rest of the codebase.
+llvm::StringRef buildNamespaceKindToJSON(BuildNamespaceKind BNK);
+
+//----------------------------------------------------------------------------
+// EntityLinkageType helpers
+//----------------------------------------------------------------------------
+
+llvm::Expected<EntityLinkageType>
+entityLinkageTypeFromJSON(llvm::StringRef EntityLinkageTypeStr);
+
+// Provided for consistency with respect to rest of the codebase.
+llvm::StringRef entityLinkageTypeToJSON(EntityLinkageType LT);
+
+//----------------------------------------------------------------------------
+// TargetTriple helpers
+//----------------------------------------------------------------------------
+
+/// Validates that \p Triple is a target triple string in normalized form.
+/// Returns success if \p Triple equals \c llvm::Triple::normalize(Triple),
+/// otherwise returns an \c invalid_argument error describing the expected
+/// normalized form.
+llvm::Error validateNormalizedTargetTriple(llvm::StringRef Triple);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_LIB_ScalableStaticAnalysis_CORE_SERIALIZATION_JSONFORMAT_JSONFORMATIMPL_H
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummary.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummary.cpp
new file mode 100644
index 0000000000000..89405bc1ed774
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummary.cpp
@@ -0,0 +1,196 @@
+//===- LUSummary.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONFormatImpl.h"
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <set>
+
+namespace clang::ssaf {
+
+//----------------------------------------------------------------------------
+// LUSummary
+//----------------------------------------------------------------------------
+
+llvm::Expected<LUSummary> JSONFormat::readLUSummary(llvm::StringRef Path) {
+ auto ExpectedJSON = readJSON(Path);
+ if (!ExpectedJSON) {
+ return ErrorBuilder::wrap(ExpectedJSON.takeError())
+ .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
+ .build();
+ }
+
+ Object *RootObjectPtr = ExpectedJSON->getAsObject();
+ if (!RootObjectPtr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObject, "LUSummary",
+ "object")
+ .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
+ .build();
+ }
+
+ if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueLUSummary)) {
+ return ErrorBuilder::wrap(std::move(Err))
+ .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
+ .build();
+ }
+
+ auto ExpectedSummary = readLUSummaryFromObject(*RootObjectPtr);
+ if (!ExpectedSummary) {
+ return ErrorBuilder::wrap(ExpectedSummary.takeError())
+ .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
+ .build();
+ }
+
+ return std::move(*ExpectedSummary);
+}
+
+llvm::Expected<LUSummary>
+JSONFormat::readLUSummaryFromObject(const Object &RootObject) {
+ auto OptTargetTriple = RootObject.getString("target_triple");
+ if (!OptTargetTriple) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "TargetTriple", "target_triple", "string")
+ .build();
+ }
+
+ if (auto Err = validateNormalizedTargetTriple(*OptTargetTriple)) {
+ return ErrorBuilder::wrap(std::move(Err))
+ .context(ErrorMessages::ReadingFromField, "TargetTriple",
+ "target_triple")
+ .build();
+ }
+
+ llvm::Triple T(*OptTargetTriple);
+
+ const Array *LUNamespaceArray = RootObject.getArray("lu_namespace");
+ if (!LUNamespaceArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "NestedBuildNamespace", "lu_namespace", "array")
+ .build();
+ }
+
+ auto ExpectedLUNamespace = nestedBuildNamespaceFromJSON(*LUNamespaceArray);
+ if (!ExpectedLUNamespace) {
+ return ErrorBuilder::wrap(ExpectedLUNamespace.takeError())
+ .context(ErrorMessages::ReadingFromField, "NestedBuildNamespace",
+ "lu_namespace")
+ .build();
+ }
+
+ LUSummary Summary(std::move(T), std::move(*ExpectedLUNamespace));
+
+ {
+ const Array *IdTableArray = RootObject.getArray("id_table");
+ if (!IdTableArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "IdTable", "id_table", "array")
+ .build();
+ }
+
+ auto ExpectedIdTable = luEntityIdTableFromJSON(*IdTableArray);
+ if (!ExpectedIdTable) {
+ return ErrorBuilder::wrap(ExpectedIdTable.takeError())
+ .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
+ .build();
+ }
+
+ getIdTable(Summary) = std::move(*ExpectedIdTable);
+ }
+
+ {
+ const Array *LinkageTableArray = RootObject.getArray("linkage_table");
+ if (!LinkageTableArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "LinkageTable", "linkage_table", "array")
+ .build();
+ }
+
+ auto ExpectedIdRange =
+ llvm::make_second_range(getEntities(getIdTable(Summary)));
+ std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
+ ExpectedIdRange.end());
+
+ // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
+ // that the linkage table contains exactly the ids present in the IdTable.
+ auto ExpectedLinkageTable =
+ linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds));
+ if (!ExpectedLinkageTable) {
+ return ErrorBuilder::wrap(ExpectedLinkageTable.takeError())
+ .context(ErrorMessages::ReadingFromField, "LinkageTable",
+ "linkage_table")
+ .build();
+ }
+
+ getLinkageTable(Summary) = std::move(*ExpectedLinkageTable);
+ }
+
+ {
+ const Array *SummaryDataArray = RootObject.getArray("data");
+ if (!SummaryDataArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "SummaryData entries", "data", "array")
+ .build();
+ }
+
+ auto ExpectedSummaryDataMap =
+ summaryDataMapFromJSON(*SummaryDataArray, getIdTable(Summary));
+ if (!ExpectedSummaryDataMap) {
+ return ErrorBuilder::wrap(ExpectedSummaryDataMap.takeError())
+ .context(ErrorMessages::ReadingFromField, "SummaryData entries",
+ "data")
+ .build();
+ }
+
+ getData(Summary) = std::move(*ExpectedSummaryDataMap);
+ }
+
+ return std::move(Summary);
+}
+
+llvm::Error JSONFormat::writeLUSummary(const LUSummary &S,
+ llvm::StringRef Path) {
+ Object RootObject;
+
+ RootObject[JSONTypeKey] = JSONTypeValueLUSummary;
+
+ RootObject["target_triple"] =
+ llvm::Triple::normalize(getTargetTriple(S).str());
+
+ RootObject["lu_namespace"] = nestedBuildNamespaceToJSON(getLUNamespace(S));
+
+ RootObject["id_table"] = luEntityIdTableToJSON(getIdTable(S));
+
+ RootObject["linkage_table"] = linkageTableToJSON(getLinkageTable(S));
+
+ auto ExpectedDataObject = summaryDataMapToJSON(getData(S));
+ if (!ExpectedDataObject) {
+ return ErrorBuilder::wrap(ExpectedDataObject.takeError())
+ .context(ErrorMessages::WritingToFile, "LUSummary", Path)
+ .build();
+ }
+
+ RootObject["data"] = std::move(*ExpectedDataObject);
+
+ if (auto Error = writeJSON(std::move(RootObject), Path)) {
+ return ErrorBuilder::wrap(std::move(Error))
+ .context(ErrorMessages::WritingToFile, "LUSummary", Path)
+ .build();
+ }
+
+ return llvm::Error::success();
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
new file mode 100644
index 0000000000000..b1f78c5309dfb
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/LUSummaryEncoding.cpp
@@ -0,0 +1,193 @@
+//===- LUSummaryEncoding.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONFormatImpl.h"
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <set>
+
+namespace clang::ssaf {
+
+//----------------------------------------------------------------------------
+// LUSummaryEncoding
+//----------------------------------------------------------------------------
+
+llvm::Expected<LUSummaryEncoding>
+JSONFormat::readLUSummaryEncoding(llvm::StringRef Path) {
+ auto ExpectedJSON = readJSON(Path);
+ if (!ExpectedJSON) {
+ return ErrorBuilder::wrap(ExpectedJSON.takeError())
+ .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
+ .build();
+ }
+
+ Object *RootObjectPtr = ExpectedJSON->getAsObject();
+ if (!RootObjectPtr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObject, "LUSummary",
+ "object")
+ .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
+ .build();
+ }
+
+ if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueLUSummary)) {
+ return ErrorBuilder::wrap(std::move(Err))
+ .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
+ .build();
+ }
+
+ auto ExpectedEncoding = readLUSummaryEncodingFromObject(*RootObjectPtr);
+ if (!ExpectedEncoding) {
+ return ErrorBuilder::wrap(ExpectedEncoding.takeError())
+ .context(ErrorMessages::ReadingFromFile, "LUSummary", Path)
+ .build();
+ }
+
+ return std::move(*ExpectedEncoding);
+}
+
+llvm::Expected<LUSummaryEncoding>
+JSONFormat::readLUSummaryEncodingFromObject(const Object &RootObject) {
+ auto OptTargetTriple = RootObject.getString("target_triple");
+ if (!OptTargetTriple) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "TargetTriple", "target_triple", "string")
+ .build();
+ }
+
+ if (auto Err = validateNormalizedTargetTriple(*OptTargetTriple)) {
+ return ErrorBuilder::wrap(std::move(Err))
+ .context(ErrorMessages::ReadingFromField, "TargetTriple",
+ "target_triple")
+ .build();
+ }
+
+ llvm::Triple T(*OptTargetTriple);
+
+ const Array *LUNamespaceArray = RootObject.getArray("lu_namespace");
+ if (!LUNamespaceArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "NestedBuildNamespace", "lu_namespace", "array")
+ .build();
+ }
+
+ auto ExpectedLUNamespace = nestedBuildNamespaceFromJSON(*LUNamespaceArray);
+ if (!ExpectedLUNamespace) {
+ return ErrorBuilder::wrap(ExpectedLUNamespace.takeError())
+ .context(ErrorMessages::ReadingFromField, "NestedBuildNamespace",
+ "lu_namespace")
+ .build();
+ }
+
+ LUSummaryEncoding Encoding(std::move(T), std::move(*ExpectedLUNamespace));
+
+ {
+ const Array *IdTableArray = RootObject.getArray("id_table");
+ if (!IdTableArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "IdTable", "id_table", "array")
+ .build();
+ }
+
+ auto ExpectedIdTable = luEntityIdTableFromJSON(*IdTableArray);
+ if (!ExpectedIdTable) {
+ return ErrorBuilder::wrap(ExpectedIdTable.takeError())
+ .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
+ .build();
+ }
+
+ getIdTable(Encoding) = std::move(*ExpectedIdTable);
+ }
+
+ {
+ const Array *LinkageTableArray = RootObject.getArray("linkage_table");
+ if (!LinkageTableArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "LinkageTable", "linkage_table", "array")
+ .build();
+ }
+
+ auto ExpectedIdRange =
+ llvm::make_second_range(getEntities(getIdTable(Encoding)));
+ std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
+ ExpectedIdRange.end());
+
+ // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
+ // that the linkage table contains exactly the ids present in the IdTable.
+ auto ExpectedLinkageTable =
+ linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds));
+ if (!ExpectedLinkageTable) {
+ return ErrorBuilder::wrap(ExpectedLinkageTable.takeError())
+ .context(ErrorMessages::ReadingFromField, "LinkageTable",
+ "linkage_table")
+ .build();
+ }
+
+ getLinkageTable(Encoding) = std::move(*ExpectedLinkageTable);
+ }
+
+ {
+ const Array *SummaryDataArray = RootObject.getArray("data");
+ if (!SummaryDataArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "SummaryData entries", "data", "array")
+ .build();
+ }
+
+ auto ExpectedEncodingSummaryDataMap =
+ encodingSummaryDataMapFromJSON(*SummaryDataArray);
+ if (!ExpectedEncodingSummaryDataMap) {
+ return ErrorBuilder::wrap(ExpectedEncodingSummaryDataMap.takeError())
+ .context(ErrorMessages::ReadingFromField, "SummaryData entries",
+ "data")
+ .build();
+ }
+
+ getData(Encoding) = std::move(*ExpectedEncodingSummaryDataMap);
+ }
+
+ return std::move(Encoding);
+}
+
+llvm::Error
+JSONFormat::writeLUSummaryEncoding(const LUSummaryEncoding &SummaryEncoding,
+ llvm::StringRef Path) {
+ Object RootObject;
+
+ RootObject[JSONTypeKey] = JSONTypeValueLUSummary;
+
+ RootObject["target_triple"] =
+ llvm::Triple::normalize(getTargetTriple(SummaryEncoding).str());
+
+ RootObject["lu_namespace"] =
+ nestedBuildNamespaceToJSON(getLUNamespace(SummaryEncoding));
+
+ RootObject["id_table"] = luEntityIdTableToJSON(getIdTable(SummaryEncoding));
+
+ RootObject["linkage_table"] =
+ linkageTableToJSON(getLinkageTable(SummaryEncoding));
+
+ RootObject["data"] = encodingSummaryDataMapToJSON(getData(SummaryEncoding));
+
+ if (auto Error = writeJSON(std::move(RootObject), Path)) {
+ return ErrorBuilder::wrap(std::move(Error))
+ .context(ErrorMessages::WritingToFile, "LUSummary", Path)
+ .build();
+ }
+
+ return llvm::Error::success();
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummary.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummary.cpp
new file mode 100644
index 0000000000000..a77a5952ddb91
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummary.cpp
@@ -0,0 +1,196 @@
+//===- TUSummary.cpp ------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONFormatImpl.h"
+
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <set>
+
+namespace clang::ssaf {
+
+//----------------------------------------------------------------------------
+// TUSummary
+//----------------------------------------------------------------------------
+
+llvm::Expected<TUSummary> JSONFormat::readTUSummary(llvm::StringRef Path) {
+ auto ExpectedJSON = readJSON(Path);
+ if (!ExpectedJSON) {
+ return ErrorBuilder::wrap(ExpectedJSON.takeError())
+ .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
+ .build();
+ }
+
+ Object *RootObjectPtr = ExpectedJSON->getAsObject();
+ if (!RootObjectPtr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObject, "TUSummary",
+ "object")
+ .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
+ .build();
+ }
+
+ if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueTUSummary)) {
+ return ErrorBuilder::wrap(std::move(Err))
+ .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
+ .build();
+ }
+
+ auto ExpectedSummary = readTUSummaryFromObject(*RootObjectPtr);
+ if (!ExpectedSummary) {
+ return ErrorBuilder::wrap(ExpectedSummary.takeError())
+ .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
+ .build();
+ }
+
+ return std::move(*ExpectedSummary);
+}
+
+llvm::Expected<TUSummary>
+JSONFormat::readTUSummaryFromObject(const Object &RootObject) {
+ auto OptTargetTriple = RootObject.getString("target_triple");
+ if (!OptTargetTriple) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "TargetTriple", "target_triple", "string")
+ .build();
+ }
+
+ if (auto Err = validateNormalizedTargetTriple(*OptTargetTriple)) {
+ return ErrorBuilder::wrap(std::move(Err))
+ .context(ErrorMessages::ReadingFromField, "TargetTriple",
+ "target_triple")
+ .build();
+ }
+
+ llvm::Triple T(*OptTargetTriple);
+
+ const Object *TUNamespaceObject = RootObject.getObject("tu_namespace");
+ if (!TUNamespaceObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "BuildNamespace", "tu_namespace", "object")
+ .build();
+ }
+
+ auto ExpectedTUNamespace = buildNamespaceFromJSON(*TUNamespaceObject);
+ if (!ExpectedTUNamespace) {
+ return ErrorBuilder::wrap(ExpectedTUNamespace.takeError())
+ .context(ErrorMessages::ReadingFromField, "BuildNamespace",
+ "tu_namespace")
+ .build();
+ }
+
+ TUSummary Summary(std::move(T), std::move(*ExpectedTUNamespace));
+
+ {
+ const Array *IdTableArray = RootObject.getArray("id_table");
+ if (!IdTableArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "IdTable", "id_table", "array")
+ .build();
+ }
+
+ auto ExpectedIdTable = tuEntityIdTableFromJSON(*IdTableArray);
+ if (!ExpectedIdTable) {
+ return ErrorBuilder::wrap(ExpectedIdTable.takeError())
+ .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
+ .build();
+ }
+
+ getIdTable(Summary) = std::move(*ExpectedIdTable);
+ }
+
+ {
+ const Array *LinkageTableArray = RootObject.getArray("linkage_table");
+ if (!LinkageTableArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "LinkageTable", "linkage_table", "array")
+ .build();
+ }
+
+ auto ExpectedIdRange =
+ llvm::make_second_range(getEntities(getIdTable(Summary)));
+ std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
+ ExpectedIdRange.end());
+
+ // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
+ // that the linkage table contains exactly the ids present in the IdTable.
+ auto ExpectedLinkageTable =
+ linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds));
+ if (!ExpectedLinkageTable) {
+ return ErrorBuilder::wrap(ExpectedLinkageTable.takeError())
+ .context(ErrorMessages::ReadingFromField, "LinkageTable",
+ "linkage_table")
+ .build();
+ }
+
+ getLinkageTable(Summary) = std::move(*ExpectedLinkageTable);
+ }
+
+ {
+ const Array *SummaryDataArray = RootObject.getArray("data");
+ if (!SummaryDataArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "SummaryData entries", "data", "array")
+ .build();
+ }
+
+ auto ExpectedSummaryDataMap =
+ summaryDataMapFromJSON(*SummaryDataArray, getIdTable(Summary));
+ if (!ExpectedSummaryDataMap) {
+ return ErrorBuilder::wrap(ExpectedSummaryDataMap.takeError())
+ .context(ErrorMessages::ReadingFromField, "SummaryData entries",
+ "data")
+ .build();
+ }
+
+ getData(Summary) = std::move(*ExpectedSummaryDataMap);
+ }
+
+ return std::move(Summary);
+}
+
+llvm::Error JSONFormat::writeTUSummary(const TUSummary &S,
+ llvm::StringRef Path) {
+ Object RootObject;
+
+ RootObject[JSONTypeKey] = JSONTypeValueTUSummary;
+
+ RootObject["target_triple"] =
+ llvm::Triple::normalize(getTargetTriple(S).str());
+
+ RootObject["tu_namespace"] = buildNamespaceToJSON(getTUNamespace(S));
+
+ RootObject["id_table"] = tuEntityIdTableToJSON(getIdTable(S));
+
+ RootObject["linkage_table"] = linkageTableToJSON(getLinkageTable(S));
+
+ auto ExpectedDataObject = summaryDataMapToJSON(getData(S));
+ if (!ExpectedDataObject) {
+ return ErrorBuilder::wrap(ExpectedDataObject.takeError())
+ .context(ErrorMessages::WritingToFile, "TUSummary", Path)
+ .build();
+ }
+
+ RootObject["data"] = std::move(*ExpectedDataObject);
+
+ if (auto Error = writeJSON(std::move(RootObject), Path)) {
+ return ErrorBuilder::wrap(std::move(Error))
+ .context(ErrorMessages::WritingToFile, "TUSummary", Path)
+ .build();
+ }
+
+ return llvm::Error::success();
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
new file mode 100644
index 0000000000000..5a5ab98731c47
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/TUSummaryEncoding.cpp
@@ -0,0 +1,193 @@
+//===- TUSummaryEncoding.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONFormatImpl.h"
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "llvm/TargetParser/Triple.h"
+
+#include <set>
+
+namespace clang::ssaf {
+
+//----------------------------------------------------------------------------
+// TUSummaryEncoding
+//----------------------------------------------------------------------------
+
+llvm::Expected<TUSummaryEncoding>
+JSONFormat::readTUSummaryEncoding(llvm::StringRef Path) {
+ auto ExpectedJSON = readJSON(Path);
+ if (!ExpectedJSON) {
+ return ErrorBuilder::wrap(ExpectedJSON.takeError())
+ .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
+ .build();
+ }
+
+ Object *RootObjectPtr = ExpectedJSON->getAsObject();
+ if (!RootObjectPtr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObject, "TUSummary",
+ "object")
+ .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
+ .build();
+ }
+
+ if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueTUSummary)) {
+ return ErrorBuilder::wrap(std::move(Err))
+ .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
+ .build();
+ }
+
+ auto ExpectedEncoding = readTUSummaryEncodingFromObject(*RootObjectPtr);
+ if (!ExpectedEncoding) {
+ return ErrorBuilder::wrap(ExpectedEncoding.takeError())
+ .context(ErrorMessages::ReadingFromFile, "TUSummary", Path)
+ .build();
+ }
+
+ return std::move(*ExpectedEncoding);
+}
+
+llvm::Expected<TUSummaryEncoding>
+JSONFormat::readTUSummaryEncodingFromObject(const Object &RootObject) {
+ auto OptTargetTriple = RootObject.getString("target_triple");
+ if (!OptTargetTriple) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "TargetTriple", "target_triple", "string")
+ .build();
+ }
+
+ if (auto Err = validateNormalizedTargetTriple(*OptTargetTriple)) {
+ return ErrorBuilder::wrap(std::move(Err))
+ .context(ErrorMessages::ReadingFromField, "TargetTriple",
+ "target_triple")
+ .build();
+ }
+
+ llvm::Triple T(*OptTargetTriple);
+
+ const Object *TUNamespaceObject = RootObject.getObject("tu_namespace");
+ if (!TUNamespaceObject) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "BuildNamespace", "tu_namespace", "object")
+ .build();
+ }
+
+ auto ExpectedTUNamespace = buildNamespaceFromJSON(*TUNamespaceObject);
+ if (!ExpectedTUNamespace) {
+ return ErrorBuilder::wrap(ExpectedTUNamespace.takeError())
+ .context(ErrorMessages::ReadingFromField, "BuildNamespace",
+ "tu_namespace")
+ .build();
+ }
+
+ TUSummaryEncoding Encoding(std::move(T), std::move(*ExpectedTUNamespace));
+
+ {
+ const Array *IdTableArray = RootObject.getArray("id_table");
+ if (!IdTableArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "IdTable", "id_table", "array")
+ .build();
+ }
+
+ auto ExpectedIdTable = tuEntityIdTableFromJSON(*IdTableArray);
+ if (!ExpectedIdTable) {
+ return ErrorBuilder::wrap(ExpectedIdTable.takeError())
+ .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
+ .build();
+ }
+
+ getIdTable(Encoding) = std::move(*ExpectedIdTable);
+ }
+
+ {
+ const Array *LinkageTableArray = RootObject.getArray("linkage_table");
+ if (!LinkageTableArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "LinkageTable", "linkage_table", "array")
+ .build();
+ }
+
+ auto ExpectedIdRange =
+ llvm::make_second_range(getEntities(getIdTable(Encoding)));
+ std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
+ ExpectedIdRange.end());
+
+ // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
+ // that the linkage table contains exactly the ids present in the IdTable.
+ auto ExpectedLinkageTable =
+ linkageTableFromJSON(*LinkageTableArray, std::move(ExpectedIds));
+ if (!ExpectedLinkageTable) {
+ return ErrorBuilder::wrap(ExpectedLinkageTable.takeError())
+ .context(ErrorMessages::ReadingFromField, "LinkageTable",
+ "linkage_table")
+ .build();
+ }
+
+ getLinkageTable(Encoding) = std::move(*ExpectedLinkageTable);
+ }
+
+ {
+ const Array *SummaryDataArray = RootObject.getArray("data");
+ if (!SummaryDataArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "SummaryData entries", "data", "array")
+ .build();
+ }
+
+ auto ExpectedEncodingSummaryDataMap =
+ encodingSummaryDataMapFromJSON(*SummaryDataArray);
+ if (!ExpectedEncodingSummaryDataMap) {
+ return ErrorBuilder::wrap(ExpectedEncodingSummaryDataMap.takeError())
+ .context(ErrorMessages::ReadingFromField, "SummaryData entries",
+ "data")
+ .build();
+ }
+
+ getData(Encoding) = std::move(*ExpectedEncodingSummaryDataMap);
+ }
+
+ return std::move(Encoding);
+}
+
+llvm::Error
+JSONFormat::writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding,
+ llvm::StringRef Path) {
+ Object RootObject;
+
+ RootObject[JSONTypeKey] = JSONTypeValueTUSummary;
+
+ RootObject["target_triple"] =
+ llvm::Triple::normalize(getTargetTriple(SummaryEncoding).str());
+
+ RootObject["tu_namespace"] =
+ buildNamespaceToJSON(getTUNamespace(SummaryEncoding));
+
+ RootObject["id_table"] = tuEntityIdTableToJSON(getIdTable(SummaryEncoding));
+
+ RootObject["linkage_table"] =
+ linkageTableToJSON(getLinkageTable(SummaryEncoding));
+
+ RootObject["data"] = encodingSummaryDataMapToJSON(getData(SummaryEncoding));
+
+ if (auto Error = writeJSON(std::move(RootObject), Path)) {
+ return ErrorBuilder::wrap(std::move(Error))
+ .context(ErrorMessages::WritingToFile, "TUSummary", Path)
+ .build();
+ }
+
+ return llvm::Error::success();
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/WPASuite.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/WPASuite.cpp
new file mode 100644
index 0000000000000..523e12a7f60c8
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/JSONFormat/WPASuite.cpp
@@ -0,0 +1,226 @@
+//===- WPASuite.cpp -------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONFormatImpl.h"
+
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+
+namespace clang::ssaf {
+
+//----------------------------------------------------------------------------
+// AnalysisResultMapEntry
+//----------------------------------------------------------------------------
+
+llvm::Expected<std::pair<AnalysisName, std::unique_ptr<AnalysisResult>>>
+JSONFormat::analysisResultMapEntryFromJSON(const Object &Entry) const {
+ auto OptName = Entry.getString("analysis_name");
+ if (!OptName) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "AnalysisName", "analysis_name", "string")
+ .build();
+ }
+
+ AnalysisName Name = analysisNameFromJSON(*OptName);
+
+ auto ExpectedCodec = AnalysisResultRegistry::instantiate(Name);
+ if (!ExpectedCodec) {
+ return ExpectedCodec.takeError();
+ }
+
+ const Object *ResultObj = Entry.getObject("result");
+ if (!ResultObj) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "AnalysisResult", "result", "object")
+ .build();
+ }
+
+ auto ExpectedResult =
+ (*ExpectedCodec)->deserialize(*ResultObj, &entityIdFromJSONObject);
+ if (!ExpectedResult) {
+ return ExpectedResult.takeError();
+ }
+
+ return std::make_pair(std::move(Name), std::move(*ExpectedResult));
+}
+
+llvm::Expected<Object> JSONFormat::analysisResultMapEntryToJSON(
+ const AnalysisName &Name,
+ const std::unique_ptr<AnalysisResult> &Result) const {
+ auto ExpectedCodec = AnalysisResultRegistry::instantiate(Name);
+ if (!ExpectedCodec) {
+ return ExpectedCodec.takeError();
+ }
+
+ Object Entry;
+ Entry["analysis_name"] = analysisNameToJSON(Name);
+ Entry["result"] = (*ExpectedCodec)->serialize(*Result, &entityIdToJSONObject);
+ return Entry;
+}
+
+//----------------------------------------------------------------------------
+// AnalysisResultMap
+//----------------------------------------------------------------------------
+
+llvm::Expected<std::map<AnalysisName, std::unique_ptr<AnalysisResult>>>
+JSONFormat::analysisResultMapFromJSON(const Array &ResultsArray) const {
+ std::map<AnalysisName, std::unique_ptr<AnalysisResult>> Results;
+
+ auto AsObject = [](const Value &V) { return V.getAsObject(); };
+ auto ObjectsRange = llvm::map_range(ResultsArray, AsObject);
+
+ for (auto [I, Entry] : enumerate(ObjectsRange)) {
+ if (!Entry) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtIndex,
+ "WPA result entry", I, "object")
+ .build();
+ }
+
+ auto ExpectedPair = analysisResultMapEntryFromJSON(*Entry);
+ if (!ExpectedPair) {
+ return ErrorBuilder::wrap(ExpectedPair.takeError())
+ .context(ErrorMessages::ReadingFromIndex, "WPA result entry", I)
+ .build();
+ }
+
+ auto [Name, Result] = std::move(*ExpectedPair);
+ bool Inserted = Results.try_emplace(Name, std::move(Result)).second;
+ if (!Inserted) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedInsertionOnDuplication,
+ "WPA result", I, Name)
+ .build();
+ }
+ }
+ return std::move(Results);
+}
+
+llvm::Expected<Array> JSONFormat::analysisResultMapToJSON(
+ const std::map<AnalysisName, std::unique_ptr<AnalysisResult>> &Data) const {
+ Array Results;
+ for (const auto &[Name, Result] : Data) {
+ auto ExpectedEntry = analysisResultMapEntryToJSON(Name, Result);
+ if (!ExpectedEntry) {
+ return ExpectedEntry.takeError();
+ }
+ Results.push_back(std::move(*ExpectedEntry));
+ }
+ return Results;
+}
+
+//----------------------------------------------------------------------------
+// WPASuite
+//----------------------------------------------------------------------------
+
+llvm::Expected<WPASuite> JSONFormat::readWPASuite(llvm::StringRef Path) {
+ auto ExpectedJSON = readJSON(Path);
+ if (!ExpectedJSON) {
+ return ErrorBuilder::wrap(ExpectedJSON.takeError())
+ .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
+ .build();
+ }
+
+ Object *RootObjectPtr = ExpectedJSON->getAsObject();
+ if (!RootObjectPtr) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObject, "WPASuite",
+ "object")
+ .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
+ .build();
+ }
+
+ if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueWPASuite)) {
+ return ErrorBuilder::wrap(std::move(Err))
+ .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
+ .build();
+ }
+
+ auto ExpectedSuite = readWPASuiteFromObject(*RootObjectPtr);
+ if (!ExpectedSuite) {
+ return ErrorBuilder::wrap(ExpectedSuite.takeError())
+ .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
+ .build();
+ }
+
+ return std::move(*ExpectedSuite);
+}
+
+llvm::Expected<WPASuite>
+JSONFormat::readWPASuiteFromObject(const Object &RootObject) {
+ WPASuite Suite = makeWPASuite();
+
+ {
+ const Array *IdTableArray = RootObject.getArray("id_table");
+ if (!IdTableArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "IdTable", "id_table", "array")
+ .build();
+ }
+
+ auto ExpectedIdTable = luEntityIdTableFromJSON(*IdTableArray);
+ if (!ExpectedIdTable) {
+ return ErrorBuilder::wrap(ExpectedIdTable.takeError())
+ .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
+ .build();
+ }
+
+ getIdTable(Suite) = std::move(*ExpectedIdTable);
+ }
+
+ {
+ const Array *ResultsArray = RootObject.getArray("results");
+ if (!ResultsArray) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ ErrorMessages::FailedToReadObjectAtField,
+ "WPA results", "results", "array")
+ .build();
+ }
+
+ auto ExpectedResultsMap = analysisResultMapFromJSON(*ResultsArray);
+ if (!ExpectedResultsMap) {
+ return ErrorBuilder::wrap(ExpectedResultsMap.takeError())
+ .context(ErrorMessages::ReadingFromField, "WPA results", "results")
+ .build();
+ }
+
+ getData(Suite) = std::move(*ExpectedResultsMap);
+ }
+
+ return std::move(Suite);
+}
+
+llvm::Error JSONFormat::writeWPASuite(const WPASuite &Suite,
+ llvm::StringRef Path) {
+ Object RootObject;
+
+ RootObject[JSONTypeKey] = JSONTypeValueWPASuite;
+
+ RootObject["id_table"] = luEntityIdTableToJSON(getIdTable(Suite));
+
+ auto ExpectedResults = analysisResultMapToJSON(getData(Suite));
+ if (!ExpectedResults) {
+ return ErrorBuilder::wrap(ExpectedResults.takeError())
+ .context(ErrorMessages::WritingToFile, "WPASuite", Path)
+ .build();
+ }
+
+ RootObject["results"] = std::move(*ExpectedResults);
+
+ if (auto Error = writeJSON(std::move(RootObject), Path)) {
+ return ErrorBuilder::wrap(std::move(Error))
+ .context(ErrorMessages::WritingToFile, "WPASuite", Path)
+ .build();
+ }
+
+ return llvm::Error::success();
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.cpp b/clang/lib/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.cpp
new file mode 100644
index 0000000000000..7f7791922bbee
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.cpp
@@ -0,0 +1,37 @@
+//===- SerializationFormatRegistry.cpp ------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include <memory>
+
+using namespace clang;
+using namespace ssaf;
+
+LLVM_DEFINE_REGISTRY(SerializationFormatRegistry)
+
+bool ssaf::isFormatRegistered(llvm::StringRef FormatName) {
+ for (const auto &Entry : SerializationFormatRegistry::entries())
+ if (Entry.getName() == FormatName)
+ return true;
+ return false;
+}
+
+std::unique_ptr<SerializationFormat>
+ssaf::makeFormat(llvm::StringRef FormatName) {
+ for (const auto &Entry : SerializationFormatRegistry::entries())
+ if (Entry.getName() == FormatName)
+ return Entry.instantiate();
+ assert(false && "Unknown SerializationFormat name");
+ return nullptr;
+}
+
+void ssaf::printAvailableFormats(llvm::raw_ostream &OS) {
+ OS << "OVERVIEW: Available SSAF serialization formats:\n\n";
+ for (const auto &Entry : SerializationFormatRegistry::entries())
+ OS << " " << Entry.getName() << " - " << Entry.getDesc() << "\n";
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.cpp b/clang/lib/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.cpp
new file mode 100644
index 0000000000000..fb630e8117f59
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.cpp
@@ -0,0 +1,78 @@
+//===- LUSummaryConsumer.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+
+using namespace clang;
+using namespace ssaf;
+
+llvm::Expected<std::unique_ptr<SummaryData>>
+LUSummaryConsumer::build(LUDataIterator LUIt) {
+ const SummaryName SN = LUIt->first;
+ auto Builder = SummaryDataBuilderRegistry::instantiate(SN.str());
+ if (!Builder) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ "no builder registered for analysis '{0}'",
+ SN.str())
+ .build();
+ }
+
+ for (auto &[Id, Summary] : LUIt->second) {
+ Builder->addSummary(Id, std::move(Summary));
+ }
+ Builder->finalize();
+ LU->Data.erase(LUIt);
+
+ return std::move(*Builder).takeData();
+}
+
+llvm::Expected<std::unique_ptr<SummaryData>>
+LUSummaryConsumer::build(const SummaryName &SN) {
+ auto LUIt = LU->Data.find(SN);
+ if (LUIt == LU->Data.end()) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ "no data for analysis '{0}' in LUSummary",
+ SN.str())
+ .build();
+ }
+ return build(LUIt);
+}
+
+llvm::Expected<SummaryDataStore>
+LUSummaryConsumer::run(llvm::ArrayRef<SummaryName> Names) {
+ SummaryDataStore Store;
+ for (const auto &SN : Names) {
+ auto Result = build(SN);
+ if (!Result) {
+ return Result.takeError();
+ }
+ Store.Data.emplace(SN, std::move(*Result));
+ }
+ return std::move(Store);
+}
+
+SummaryDataStore LUSummaryConsumer::run() && {
+ SummaryDataStore Store;
+ // Advance the iterator before calling build(): build() erases the current
+ // element on success, but std::map only invalidates iterators to the erased
+ // element, so the pre-advanced iterator remains valid in all cases.
+ auto It = LU->Data.begin();
+ while (It != LU->Data.end()) {
+ auto Current = It++; // Read the comment above!
+ SummaryName SN = Current->first; // copy before build() potentially erases
+ auto Result = build(Current);
+ if (!Result) {
+ llvm::consumeError(Result.takeError());
+ continue;
+ }
+ Store.Data.emplace(std::move(SN), std::move(*Result));
+ }
+ return Store;
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.cpp b/clang/lib/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.cpp
new file mode 100644
index 0000000000000..98624bb9e2a08
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.cpp
@@ -0,0 +1,36 @@
+//===- SummaryDataBuilderRegistry.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h"
+
+using namespace clang;
+using namespace ssaf;
+
+using RegistryT = llvm::Registry<SummaryDataBuilderBase>;
+LLVM_DEFINE_REGISTRY(RegistryT)
+
+namespace {
+const RegistryT::entry *findEntry(llvm::StringRef Name) {
+ for (const auto &Entry : RegistryT::entries()) {
+ if (Entry.getName() == Name) {
+ return &Entry;
+ }
+ }
+ return nullptr;
+}
+} // namespace
+
+bool SummaryDataBuilderRegistry::contains(llvm::StringRef Name) {
+ return findEntry(Name) != nullptr;
+}
+
+std::unique_ptr<SummaryDataBuilderBase>
+SummaryDataBuilderRegistry::instantiate(llvm::StringRef Name) {
+ const auto *Entry = findEntry(Name);
+ return Entry ? Entry->instantiate() : nullptr;
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Core/Support/ErrorBuilder.cpp b/clang/lib/ScalableStaticAnalysis/Core/Support/ErrorBuilder.cpp
new file mode 100644
index 0000000000000..99610725a6d23
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/Support/ErrorBuilder.cpp
@@ -0,0 +1,63 @@
+//===- ErrorBuilder.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include <cassert>
+
+namespace clang::ssaf {
+
+static constexpr llvm::StringLiteral ErrorSeparator = " + ";
+static constexpr llvm::StringLiteral ContextSeparator = "\n";
+
+ErrorBuilder ErrorBuilder::wrap(llvm::Error E) {
+ assert(
+ E &&
+ "Cannot wrap a success error - check for success before calling wrap()");
+
+ std::optional<std::error_code> EC;
+ std::vector<std::string> Messages;
+
+ llvm::handleAllErrors(std::move(E), [&](const llvm::ErrorInfoBase &EI) {
+ // Capture error code from the first error only.
+ if (!EC)
+ EC = EI.convertToErrorCode();
+
+ // Collect messages from all errors.
+ std::string ErrorMsg = EI.message();
+ if (!ErrorMsg.empty())
+ Messages.push_back(std::move(ErrorMsg));
+ });
+
+ assert(EC && "wrap() called with a non-success error but no handler fired - "
+ "indicates a bug in handleAllErrors");
+
+ ErrorBuilder Builder(*EC);
+
+ // Combine all messages with " + " and push as a single context entry.
+ Builder.pushContext(llvm::join(Messages, ErrorSeparator));
+
+ return Builder;
+}
+
+ErrorBuilder &ErrorBuilder::context(const char *Msg) {
+ pushContext(std::string(Msg));
+ return *this;
+}
+
+llvm::Error ErrorBuilder::build() const {
+ // Reverse the context stack so that the most recent context appears first
+ // and the wrapped error (if any) appears last.
+ // Note: Even if ContextStack is empty, we create an error with the stored
+ // error code and an empty message (this is valid in LLVM).
+ return llvm::createStringError(
+ llvm::join(llvm::reverse(ContextStack), ContextSeparator), Code);
+}
+
+} // namespace clang::ssaf
diff --git a/clang/lib/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.cpp b/clang/lib/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.cpp
new file mode 100644
index 0000000000000..1456d363625ad
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.cpp
@@ -0,0 +1,39 @@
+//===- ExtractorRegistry.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include <memory>
+
+using namespace clang;
+using namespace ssaf;
+
+LLVM_DEFINE_REGISTRY(clang::ssaf::TUSummaryExtractorRegistry)
+
+bool ssaf::isTUSummaryExtractorRegistered(llvm::StringRef SummaryName) {
+ for (const auto &Entry : TUSummaryExtractorRegistry::entries())
+ if (Entry.getName() == SummaryName)
+ return true;
+ return false;
+}
+
+std::unique_ptr<TUSummaryExtractor>
+ssaf::makeTUSummaryExtractor(llvm::StringRef SummaryName,
+ TUSummaryBuilder &Builder) {
+ for (const auto &Entry : TUSummaryExtractorRegistry::entries())
+ if (Entry.getName() == SummaryName)
+ return Entry.instantiate(Builder);
+ assert(false && "Unknown SummaryExtractor name");
+ return nullptr;
+}
+
+void ssaf::printAvailableTUSummaryExtractors(llvm::raw_ostream &OS) {
+ OS << "OVERVIEW: Available SSAF summary extractors:\n\n";
+ for (const auto &Entry : TUSummaryExtractorRegistry::entries())
+ OS << " " << Entry.getName() << " - " << Entry.getDesc() << "\n";
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.cpp b/clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.cpp
new file mode 100644
index 0000000000000..ba2def365dddc
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.cpp
@@ -0,0 +1,36 @@
+//===- TUSummaryBuilder.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include <memory>
+#include <utility>
+
+using namespace clang;
+using namespace ssaf;
+
+EntityId TUSummaryBuilder::addEntity(const EntityName &EN,
+ EntityLinkageType Linkage) {
+ EntityId Id = Summary.IdTable.getId(EN);
+ [[maybe_unused]] EntityLinkageType Link =
+ Summary.LinkageTable.try_emplace(Id, Linkage).first->second.getLinkage();
+ // Even if we had in the past a linkage, that must bee the same as we set now.
+ assert(Link == Linkage);
+ return Id;
+}
+
+std::pair<EntitySummary *, bool>
+TUSummaryBuilder::addSummaryImpl(EntityId Entity,
+ std::unique_ptr<EntitySummary> &&Data) {
+ auto &EntitySummaries = Summary.Data[Data->getSummaryName()];
+ auto [It, Inserted] = EntitySummaries.try_emplace(Entity, std::move(Data));
+ return {It->second.get(), Inserted};
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.cpp b/clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.cpp
new file mode 100644
index 0000000000000..40205b90a4eb6
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.cpp
@@ -0,0 +1,80 @@
+//===- TUSummaryExtractor.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "llvm/Support/Casting.h"
+#include <optional>
+
+using namespace clang;
+using namespace ssaf;
+
+static EntityLinkageType getLinkageForDecl(const Decl *D) {
+ const auto *ND = dyn_cast<NamedDecl>(D);
+ if (!ND)
+ return EntityLinkageType::None;
+
+ // Parameters have no linkage in C++, but SSAF needs them to inherit
+ // the external linkage from their parent functions.
+ // Here is why:
+ // SSAF treats parameters as entities and may not always associate them back
+ // to their parent functions. Therefore, it needs to identify parameters of
+ // functions with external linkage across different TUs. Treating them as
+ // having no linkage (as in C++) causes the same parameter in different TUs
+ // to be assigned different EntityIDs. As a result, the behavior of the
+ // parameter across multiple TUs cannot be correlated.
+ if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
+ if (const auto *FD = llvm::dyn_cast_or_null<FunctionDecl>(
+ PVD->getParentFunctionOrMethod())) {
+ return getLinkageForDecl(FD);
+ }
+ }
+
+ switch (ND->getFormalLinkage()) {
+ case Linkage::Invalid: {
+ llvm_unreachable("Shouldn't be invalid");
+ }
+ case Linkage::None:
+ return EntityLinkageType::None;
+ case Linkage::Internal:
+ return EntityLinkageType::Internal;
+ case Linkage::UniqueExternal:
+ return EntityLinkageType::Internal;
+ case Linkage::VisibleNone:
+ return EntityLinkageType::Internal;
+ case Linkage::Module:
+ return EntityLinkageType::External;
+ case Linkage::External:
+ return EntityLinkageType::External;
+ }
+ llvm_unreachable("Unhandled clang::Linkage kind");
+}
+
+std::optional<EntityId> TUSummaryExtractor::addEntity(const NamedDecl *D) {
+ auto Name = getEntityName(D);
+ if (!Name)
+ return std::nullopt;
+ return SummaryBuilder.addEntity(*Name, getLinkageForDecl(D));
+}
+
+std::optional<EntityId>
+TUSummaryExtractor::addEntityForReturn(const FunctionDecl *FD) {
+ auto Name = getEntityNameForReturn(FD);
+ if (!Name)
+ return std::nullopt;
+ return SummaryBuilder.addEntity(*Name, getLinkageForDecl(FD));
+}
+
+const SSAFOptions &TUSummaryExtractor::getOptions() const {
+ return SummaryBuilder.getOptions();
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.cpp b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.cpp
new file mode 100644
index 0000000000000..f60c916e10b67
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.cpp
@@ -0,0 +1,212 @@
+//===- AnalysisDriver.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <map>
+#include <vector>
+
+using namespace clang;
+using namespace ssaf;
+
+AnalysisDriver::AnalysisDriver(std::unique_ptr<LUSummary> LU)
+ : LU(std::move(LU)) {}
+
+llvm::Expected<std::vector<std::unique_ptr<AnalysisBase>>>
+AnalysisDriver::toposort(llvm::ArrayRef<AnalysisName> Roots) {
+ struct Visitor {
+ enum class State { Unvisited, Visiting, Visited };
+
+ std::map<AnalysisName, State> Marks;
+ std::vector<AnalysisName> Path;
+ std::vector<std::unique_ptr<AnalysisBase>> Result;
+
+ explicit Visitor(size_t N) {
+ Path.reserve(N);
+ Result.reserve(N);
+ }
+
+ std::string formatCycle(const AnalysisName &CycleEntry) const {
+ auto CycleBegin = llvm::find(Path, CycleEntry);
+ std::string Cycle;
+ llvm::raw_string_ostream OS(Cycle);
+ llvm::interleave(llvm::make_range(CycleBegin, Path.end()), OS, " -> ");
+ OS << " -> " << CycleEntry;
+ return Cycle;
+ }
+
+ llvm::Error visit(const AnalysisName &Name) {
+ auto [It, _] = Marks.emplace(Name, State::Unvisited);
+
+ switch (It->second) {
+ case State::Visited:
+ return llvm::Error::success();
+
+ case State::Visiting:
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ "cycle detected: {0}", formatCycle(Name))
+ .build();
+
+ case State::Unvisited: {
+ It->second = State::Visiting;
+ Path.push_back(Name);
+
+ llvm::Expected<std::unique_ptr<AnalysisBase>> V =
+ AnalysisRegistry::instantiate(Name);
+ if (!V) {
+ return V.takeError();
+ }
+
+ // Unwrap for convenience to avoid the noise of dereferencing an
+ // Expected on every subsequent access.
+ std::unique_ptr<AnalysisBase> Analysis = std::move(*V);
+
+ for (const auto &Dep : Analysis->getDependencyNames()) {
+ if (auto Err = visit(Dep)) {
+ return Err;
+ }
+ }
+
+ // std::map iterators are not invalidated by insertions, so It remains
+ // valid after recursive visit() calls that insert new entries.
+ It->second = State::Visited;
+ Path.pop_back();
+ Result.push_back(std::move(Analysis));
+
+ return llvm::Error::success();
+ }
+ }
+ llvm_unreachable("unhandled State");
+ }
+ };
+
+ Visitor V(Roots.size());
+ for (const auto &Root : Roots) {
+ if (auto Err = V.visit(Root)) {
+ return std::move(Err);
+ }
+ }
+ return std::move(V.Result);
+}
+
+llvm::Error AnalysisDriver::executeSummaryAnalysis(SummaryAnalysisBase &Summary,
+ WPASuite &Suite) const {
+ SummaryName SN = Summary.getSummaryName();
+ auto DataIt = LU->Data.find(SN);
+ if (DataIt == LU->Data.end()) {
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ "no data for analysis '{0}' in LUSummary",
+ Summary.getAnalysisName())
+ .build();
+ }
+
+ if (auto Err = Summary.initialize()) {
+ return Err;
+ }
+
+ for (auto &[Id, EntitySummary] : DataIt->second) {
+ if (auto Err = Summary.add(Id, *EntitySummary)) {
+ return Err;
+ }
+ }
+
+ if (auto Err = Summary.finalize()) {
+ return Err;
+ }
+
+ return llvm::Error::success();
+}
+
+llvm::Error AnalysisDriver::executeDerivedAnalysis(DerivedAnalysisBase &Derived,
+ WPASuite &Suite) const {
+ std::map<AnalysisName, const AnalysisResult *> DepMap;
+
+ for (const auto &DepName : Derived.getDependencyNames()) {
+ auto It = Suite.Data.find(DepName);
+ if (It == Suite.Data.end()) {
+ ErrorBuilder::fatal("missing dependency '{0}' for analysis '{1}': "
+ "dependency graph is not topologically sorted",
+ DepName, Derived.getAnalysisName());
+ }
+ DepMap[DepName] = It->second.get();
+ }
+
+ if (auto Err = Derived.initialize(DepMap)) {
+ return Err;
+ }
+
+ while (true) {
+ auto StepOrErr = Derived.step();
+ if (!StepOrErr) {
+ return StepOrErr.takeError();
+ }
+ if (!*StepOrErr) {
+ break;
+ }
+ }
+
+ if (auto Err = Derived.finalize()) {
+ return Err;
+ }
+
+ return llvm::Error::success();
+}
+
+llvm::Expected<WPASuite> AnalysisDriver::execute(
+ EntityIdTable IdTable,
+ llvm::ArrayRef<std::unique_ptr<AnalysisBase>> Sorted) const {
+ WPASuite Suite;
+ Suite.IdTable = std::move(IdTable);
+
+ for (auto &Analysis : Sorted) {
+ switch (Analysis->TheKind) {
+ case AnalysisBase::Kind::Summary: {
+ SummaryAnalysisBase &SA = static_cast<SummaryAnalysisBase &>(*Analysis);
+ if (auto Err = executeSummaryAnalysis(SA, Suite)) {
+ return std::move(Err);
+ }
+ break;
+ }
+ case AnalysisBase::Kind::Derived: {
+ DerivedAnalysisBase &DA = static_cast<DerivedAnalysisBase &>(*Analysis);
+ if (auto Err = executeDerivedAnalysis(DA, Suite)) {
+ return std::move(Err);
+ }
+ break;
+ }
+ }
+ AnalysisName Name = Analysis->getAnalysisName();
+ Suite.Data.emplace(std::move(Name), std::move(*Analysis).takeResult());
+ }
+
+ return std::move(Suite);
+}
+
+llvm::Expected<WPASuite> AnalysisDriver::run() && {
+ auto ExpectedSorted = toposort(AnalysisRegistry::names());
+ if (!ExpectedSorted) {
+ return ExpectedSorted.takeError();
+ }
+ return execute(std::move(LU->IdTable), *ExpectedSorted);
+}
+
+llvm::Expected<WPASuite>
+AnalysisDriver::run(llvm::ArrayRef<AnalysisName> Names) const {
+ auto ExpectedSorted = toposort(Names);
+ if (!ExpectedSorted) {
+ return ExpectedSorted.takeError();
+ }
+
+ return execute(LU->IdTable, *ExpectedSorted);
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.cpp b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.cpp
new file mode 100644
index 0000000000000..011b816ae03dc
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.cpp
@@ -0,0 +1,16 @@
+//===- AnalysisName.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+
+using namespace clang::ssaf;
+
+llvm::raw_ostream &clang::ssaf::operator<<(llvm::raw_ostream &OS,
+ const AnalysisName &AN) {
+ return OS << "AnalysisName(" << AN.str() << ")";
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.cpp b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
new file mode 100644
index 0000000000000..71779e800f612
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.cpp
@@ -0,0 +1,46 @@
+//===- AnalysisRegistry.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace clang;
+using namespace ssaf;
+
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int AnalysisRegistryAnchorSource = 0;
+} // namespace clang::ssaf
+
+LLVM_DEFINE_REGISTRY(llvm::Registry<AnalysisBase>)
+
+std::vector<AnalysisName> &AnalysisRegistry::getAnalysisNames() {
+ static std::vector<AnalysisName> Names;
+ return Names;
+}
+
+bool AnalysisRegistry::contains(const AnalysisName &Name) {
+ return llvm::is_contained(getAnalysisNames(), Name);
+}
+
+const std::vector<AnalysisName> &AnalysisRegistry::names() {
+ return getAnalysisNames();
+}
+
+llvm::Expected<std::unique_ptr<AnalysisBase>>
+AnalysisRegistry::instantiate(const AnalysisName &Name) {
+ for (const auto &Entry : llvm::Registry<AnalysisBase>::entries()) {
+ if (Entry.getName() == Name.str()) {
+ return std::unique_ptr<AnalysisBase>(Entry.instantiate());
+ }
+ }
+ return ErrorBuilder::create(std::errc::invalid_argument,
+ "no analysis registered for '{0}'", Name)
+ .build();
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Frontend/#%2Aediff-merge%2A#zEv5rY# b/clang/lib/ScalableStaticAnalysis/Frontend/#%2Aediff-merge%2A#zEv5rY#
new file mode 100644
index 0000000000000..aa3351738c268
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Frontend/#%2Aediff-merge%2A#zEv5rY#
@@ -0,0 +1,198 @@
+//===- TUSummaryExtractorFrontendAction.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/IOSandbox.h"
+#include "llvm/Support/Path.h"
+#include "llvm/TargetParser/Triple.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+using namespace clang;
+using namespace ssaf;
+
+static std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
+parseOutputFileFormatAndPathOrReportError(DiagnosticsEngine &Diags,
+ StringRef SSAFTUSummaryFile) {
+
+ StringRef Ext = llvm::sys::path::extension(SSAFTUSummaryFile);
+ StringRef FilePath = SSAFTUSummaryFile.drop_back(Ext.size());
+
+ if (!Ext.consume_front(".") || FilePath.empty()) {
+ Diags.Report(diag::warn_ssaf_extract_tu_summary_file_unknown_format)
+ << SSAFTUSummaryFile;
+ return std::nullopt;
+ }
+
+ if (!isFormatRegistered(Ext)) {
+ Diags.Report(diag::warn_ssaf_extract_tu_summary_file_unknown_output_format)
+ << Ext << SSAFTUSummaryFile;
+ return std::nullopt;
+ }
+
+ return std::pair{Ext, FilePath};
+}
+
+/// Return \c true if reported unrecognized extractors.
+static bool
+reportUnrecognizedExtractorNames(DiagnosticsEngine &Diags,
+ ArrayRef<std::string> SSAFExtractSummaries) {
+ if (SSAFExtractSummaries.empty()) {
+ Diags.Report(diag::warn_ssaf_must_enable_summary_extractors);
+ return true;
+ }
+
+ std::vector<StringRef> UnrecognizedExtractorNames;
+ for (StringRef Name : SSAFExtractSummaries)
+ if (!isTUSummaryExtractorRegistered(Name))
+ UnrecognizedExtractorNames.push_back(Name);
+
+ if (!UnrecognizedExtractorNames.empty()) {
+ Diags.Report(diag::warn_ssaf_extract_summary_unknown_extractor_name)
+ << UnrecognizedExtractorNames.size()
+ << llvm::join(UnrecognizedExtractorNames, ", ");
+ return true;
+ }
+
+ return false;
+}
+
+static std::vector<std::unique_ptr<ASTConsumer>>
+makeTUSummaryExtractors(TUSummaryBuilder &Builder,
+ ArrayRef<std::string> SSAFExtractSummaries) {
+ std::vector<std::unique_ptr<ASTConsumer>> Extractors;
+ Extractors.reserve(SSAFExtractSummaries.size());
+ for (StringRef Name : SSAFExtractSummaries) {
+ assert(isTUSummaryExtractorRegistered(Name));
+ Extractors.push_back(makeTUSummaryExtractor(Name, Builder));
+ }
+ return Extractors;
+}
+
+namespace {
+
+/// Drives all extractor \c ASTConsumers and serializes the completed
+/// \c TUSummary.
+///
+/// Derives from \c MultiplexConsumer so every \c ASTConsumer virtual method is
+/// automatically forwarded to each extractor.
+class TUSummaryRunner final : public MultiplexConsumer {
+public:
+ static std::unique_ptr<TUSummaryRunner> create(CompilerInstance &CI);
+
+private:
+ TUSummaryRunner(llvm::Triple TargetTriple,
+ std::unique_ptr<SerializationFormat> Format,
+ const FrontendOptions &Opts);
+
+ void HandleTranslationUnit(ASTContext &Ctx) override;
+
+ TUSummary Summary;
+ TUSummaryBuilder Builder = TUSummaryBuilder(Summary);
+ std::unique_ptr<SerializationFormat> Format;
+ const FrontendOptions &Opts;
+};
+} // namespace
+
+std::unique_ptr<TUSummaryRunner> TUSummaryRunner::create(CompilerInstance &CI) {
+ const FrontendOptions &Opts = CI.getFrontendOpts();
+ DiagnosticsEngine &Diags = CI.getDiagnostics();
+
+ if (Opts.SSAFCompilationUnitId.empty()) {
+ Diags.Report(diag::warn_ssaf_tu_summary_requires_compilation_unit_id);
+ return nullptr;
+ }
+
+ auto MaybePair =
+ parseOutputFileFormatAndPathOrReportError(Diags, Opts.SSAFTUSummaryFile);
+ if (!MaybePair.has_value())
+ return nullptr;
+ auto [FormatName, OutputPath] = MaybePair.value();
+
+ if (reportUnrecognizedExtractorNames(Diags, Opts.SSAFExtractSummaries))
+ return nullptr;
+
+ return std::unique_ptr<TUSummaryRunner>{
+ new TUSummaryRunner{CI.getTarget().getTriple(), makeFormat(FormatName), Opts}};
+}
+
+TUSummaryRunner::TUSummaryRunner(llvm::Triple TargetTriple, std::unique_ptr<SerializationFormat> Format,
+ const FrontendOptions &Opts)
+ : MultiplexConsumer(std::vector<std::unique_ptr<ASTConsumer>>{}),
+<<<<<<< variant A
+ Summary(std::move(TargetTriple),
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, InFile)),
+>>>>>>> variant B
+ Summary(BuildNamespace(BuildNamespaceKind::CompilationUnit,
+ Opts.SSAFCompilationUnitId)),
+======= end
+ Format(std::move(Format)), Opts(Opts) {
+ assert(this->Format);
+ assert(!Opts.SSAFCompilationUnitId.empty());
+
+ // Now the Summary and the builders are constructed, we can also construct the
+ // extractors.
+ auto Extractors = makeTUSummaryExtractors(Builder, Opts.SSAFExtractSummaries);
+ assert(!Extractors.empty());
+
+ // We must initialize the Consumers here because our extractors need a
+ // Builder that holds a reference to the TUSummary, which would be only
+ // initialized after the MultiplexConsumer ctor. This is the only way we can
+ // avoid the use of the TUSummary before it starts its lifetime.
+ MultiplexConsumer::Consumers = std::move(Extractors);
+}
+
+void TUSummaryRunner::HandleTranslationUnit(ASTContext &Ctx) {
+ // First, invoke the Summary Extractors.
+ MultiplexConsumer::HandleTranslationUnit(Ctx);
+
+ // FIXME(sandboxing): Remove this by adopting `llvm::vfs::OutputBackend`.
+ llvm::sys::sandbox::ScopedSetting Guard = llvm::sys::sandbox::scopedDisable();
+
+ // Then serialize the result.
+ if (auto Err = Format->writeTUSummary(Summary, Opts.SSAFTUSummaryFile)) {
+ Ctx.getDiagnostics().Report(diag::warn_ssaf_write_tu_summary_failed)
+ << Opts.SSAFTUSummaryFile << llvm::toString(std::move(Err));
+ }
+}
+
+TUSummaryExtractorFrontendAction::~TUSummaryExtractorFrontendAction() = default;
+
+TUSummaryExtractorFrontendAction::TUSummaryExtractorFrontendAction(
+ std::unique_ptr<FrontendAction> WrappedAction)
+ : WrapperFrontendAction(std::move(WrappedAction)) {}
+
+std::unique_ptr<ASTConsumer>
+TUSummaryExtractorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+ auto WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
+ if (!WrappedConsumer)
+ return nullptr;
+
+ if (auto Runner = TUSummaryRunner::create(CI)) {
+ CI.getCodeGenOpts().ClearASTBeforeBackend = false;
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+ Consumers.reserve(2);
+ Consumers.push_back(std::move(WrappedConsumer));
+ Consumers.push_back(std::move(Runner));
+ return std::make_unique<MultiplexConsumer>(std::move(Consumers));
+ }
+ return WrappedConsumer;
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
new file mode 100644
index 0000000000000..74e1d0cbe1ed0
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Frontend/CMakeLists.txt
@@ -0,0 +1,16 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ TargetParser
+ )
+
+add_clang_library(clangScalableStaticAnalysisFrontend
+ TUSummaryExtractorFrontendAction.cpp
+
+ LINK_LIBS
+ clangAST
+ clangBasic
+ clangFrontend
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangSema
+ )
diff --git a/clang/lib/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.cpp b/clang/lib/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.cpp
new file mode 100644
index 0000000000000..bb4caef8f99ab
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.cpp
@@ -0,0 +1,199 @@
+//===- TUSummaryExtractorFrontendAction.cpp -------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
+#include "clang/AST/ASTConsumer.h"
+#include "clang/Basic/DiagnosticFrontend.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Frontend/SSAFOptions.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/IOSandbox.h"
+#include "llvm/Support/Path.h"
+#include "llvm/TargetParser/Triple.h"
+#include <memory>
+#include <string>
+#include <vector>
+
+using namespace clang;
+using namespace ssaf;
+
+static std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
+parseOutputFileFormatAndPathOrReportError(DiagnosticsEngine &Diags,
+ StringRef SSAFTUSummaryFile) {
+
+ StringRef Ext = llvm::sys::path::extension(SSAFTUSummaryFile);
+ StringRef FilePath = SSAFTUSummaryFile.drop_back(Ext.size());
+
+ if (!Ext.consume_front(".") || FilePath.empty()) {
+ Diags.Report(diag::warn_ssaf_extract_tu_summary_file_unknown_format)
+ << SSAFTUSummaryFile;
+ return std::nullopt;
+ }
+
+ if (!isFormatRegistered(Ext)) {
+ Diags.Report(diag::warn_ssaf_extract_tu_summary_file_unknown_output_format)
+ << Ext << SSAFTUSummaryFile;
+ return std::nullopt;
+ }
+
+ return std::pair{Ext, FilePath};
+}
+
+/// Return \c true if reported unrecognized extractors.
+static bool
+reportUnrecognizedExtractorNames(DiagnosticsEngine &Diags,
+ ArrayRef<std::string> SSAFExtractSummaries) {
+ if (SSAFExtractSummaries.empty()) {
+ Diags.Report(diag::warn_ssaf_must_enable_summary_extractors);
+ return true;
+ }
+
+ std::vector<StringRef> UnrecognizedExtractorNames;
+ for (StringRef Name : SSAFExtractSummaries)
+ if (!isTUSummaryExtractorRegistered(Name))
+ UnrecognizedExtractorNames.push_back(Name);
+
+ if (!UnrecognizedExtractorNames.empty()) {
+ Diags.Report(diag::warn_ssaf_extract_summary_unknown_extractor_name)
+ << UnrecognizedExtractorNames.size()
+ << llvm::join(UnrecognizedExtractorNames, ", ");
+ return true;
+ }
+
+ return false;
+}
+
+static std::vector<std::unique_ptr<ASTConsumer>>
+makeTUSummaryExtractors(TUSummaryBuilder &Builder,
+ ArrayRef<std::string> SSAFExtractSummaries) {
+ std::vector<std::unique_ptr<ASTConsumer>> Extractors;
+ Extractors.reserve(SSAFExtractSummaries.size());
+ for (StringRef Name : SSAFExtractSummaries) {
+ assert(isTUSummaryExtractorRegistered(Name));
+ Extractors.push_back(makeTUSummaryExtractor(Name, Builder));
+ }
+ return Extractors;
+}
+
+namespace {
+
+/// Drives all extractor \c ASTConsumers and serializes the completed
+/// \c TUSummary.
+///
+/// Derives from \c MultiplexConsumer so every \c ASTConsumer virtual method is
+/// automatically forwarded to each extractor.
+class TUSummaryRunner final : public MultiplexConsumer {
+public:
+ static std::unique_ptr<TUSummaryRunner> create(CompilerInstance &CI);
+
+private:
+ TUSummaryRunner(llvm::Triple TargetTriple,
+ std::unique_ptr<SerializationFormat> Format,
+ const SSAFOptions &Opts);
+
+ void HandleTranslationUnit(ASTContext &Ctx) override;
+
+ TUSummary Summary;
+
+ /// Owned by the \c CompilerInstance.
+ const SSAFOptions &Opts;
+
+ TUSummaryBuilder Builder = TUSummaryBuilder(Summary, Opts);
+ std::unique_ptr<SerializationFormat> Format;
+};
+} // namespace
+
+std::unique_ptr<TUSummaryRunner> TUSummaryRunner::create(CompilerInstance &CI) {
+ const SSAFOptions &Opts = CI.getSSAFOpts();
+ DiagnosticsEngine &Diags = CI.getDiagnostics();
+
+ if (Opts.CompilationUnitId.empty()) {
+ Diags.Report(diag::warn_ssaf_tu_summary_requires_compilation_unit_id);
+ return nullptr;
+ }
+
+ auto MaybePair =
+ parseOutputFileFormatAndPathOrReportError(Diags, Opts.TUSummaryFile);
+ if (!MaybePair.has_value())
+ return nullptr;
+ auto [FormatName, OutputPath] = MaybePair.value();
+
+ if (reportUnrecognizedExtractorNames(Diags, Opts.ExtractSummaries))
+ return nullptr;
+
+ return std::unique_ptr<TUSummaryRunner>{new TUSummaryRunner{
+ CI.getTarget().getTriple(), makeFormat(FormatName), Opts}};
+}
+
+TUSummaryRunner::TUSummaryRunner(llvm::Triple TargetTriple,
+ std::unique_ptr<SerializationFormat> Format,
+ const SSAFOptions &Opts)
+ : MultiplexConsumer(std::vector<std::unique_ptr<ASTConsumer>>{}),
+ Summary(std::move(TargetTriple),
+ BuildNamespace(BuildNamespaceKind::CompilationUnit,
+ Opts.CompilationUnitId)),
+ Opts(Opts), Format(std::move(Format)) {
+ assert(this->Format);
+ assert(!Opts.CompilationUnitId.empty());
+
+ // Now the Summary and the builders are constructed, we can also construct the
+ // extractors.
+ auto Extractors = makeTUSummaryExtractors(Builder, Opts.ExtractSummaries);
+ assert(!Extractors.empty());
+
+ // We must initialize the Consumers here because our extractors need a
+ // Builder that holds a reference to the TUSummary, which would be only
+ // initialized after the MultiplexConsumer ctor. This is the only way we can
+ // avoid the use of the TUSummary before it starts its lifetime.
+ MultiplexConsumer::Consumers = std::move(Extractors);
+}
+
+void TUSummaryRunner::HandleTranslationUnit(ASTContext &Ctx) {
+ // First, invoke the Summary Extractors.
+ MultiplexConsumer::HandleTranslationUnit(Ctx);
+
+ // FIXME(sandboxing): Remove this by adopting `llvm::vfs::OutputBackend`.
+ llvm::sys::sandbox::ScopedSetting Guard = llvm::sys::sandbox::scopedDisable();
+
+ // Then serialize the result.
+ if (auto Err = Format->writeTUSummary(Summary, Opts.TUSummaryFile)) {
+ Ctx.getDiagnostics().Report(diag::warn_ssaf_write_tu_summary_failed)
+ << Opts.TUSummaryFile << llvm::toString(std::move(Err));
+ }
+}
+
+TUSummaryExtractorFrontendAction::~TUSummaryExtractorFrontendAction() = default;
+
+TUSummaryExtractorFrontendAction::TUSummaryExtractorFrontendAction(
+ std::unique_ptr<FrontendAction> WrappedAction)
+ : WrapperFrontendAction(std::move(WrappedAction)) {}
+
+std::unique_ptr<ASTConsumer>
+TUSummaryExtractorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
+ StringRef InFile) {
+ auto WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
+ if (!WrappedConsumer)
+ return nullptr;
+
+ if (auto Runner = TUSummaryRunner::create(CI)) {
+ CI.getCodeGenOpts().ClearASTBeforeBackend = false;
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+ Consumers.reserve(2);
+ Consumers.push_back(std::move(WrappedConsumer));
+ Consumers.push_back(std::move(Runner));
+ return std::make_unique<MultiplexConsumer>(std::move(Consumers));
+ }
+ return WrappedConsumer;
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Plugins/CMakeLists.txt
new file mode 100644
index 0000000000000..a6af1e64e0ac3
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/CMakeLists.txt
@@ -0,0 +1,15 @@
+if(CLANG_PLUGIN_SUPPORT AND LLVM_ENABLE_PLUGINS AND NOT WIN32)
+ # Plugins must never bring LLVM or Clang libraries in statically.
+ # clang-ssaf-analyzer already loads clangScalableStaticAnalysisCore
+ # and LLVM into the process; a second static copy would produce duplicate
+ # llvm::Registry instances with separate global state, breaking registration.
+ #
+ # Instead: build each plugin as a MODULE with PLUGIN_TOOL pointing to the
+ # tool that will load it, and pull only include paths (not link deps) from
+ # the libraries whose headers are needed. All symbols are resolved from the
+ # tool's address space when the plugin is loaded via --load.
+ #
+ # This plugin is intended to be linked with undefined references; this isn't
+ # supported on PE-COFF.
+ add_subdirectory(ExamplePlugin)
+endif()
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/AnalysisResults.h b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/AnalysisResults.h
new file mode 100644
index 0000000000000..f5072dce74e23
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/AnalysisResults.h
@@ -0,0 +1,39 @@
+//===- AnalysisResults.h - Shared analysis result types ---------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef EXAMPLE_PLUGIN_ANALYSIS_RESULTS_H
+#define EXAMPLE_PLUGIN_ANALYSIS_RESULTS_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include <string>
+#include <utility>
+#include <vector>
+
+namespace example_plugin {
+
+struct TagsAnalysisResult final : clang::ssaf::AnalysisResult {
+ static clang::ssaf::AnalysisName analysisName() {
+ return clang::ssaf::AnalysisName("TagsAnalysisResult");
+ }
+
+ std::vector<std::string> Tags;
+};
+
+struct PairsAnalysisResult final : clang::ssaf::AnalysisResult {
+ static clang::ssaf::AnalysisName analysisName() {
+ return clang::ssaf::AnalysisName("PairsAnalysisResult");
+ }
+
+ std::vector<std::pair<clang::ssaf::EntityId, int>> PairCounts;
+};
+
+} // namespace example_plugin
+
+#endif // EXAMPLE_PLUGIN_ANALYSIS_RESULTS_H
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/CMakeLists.txt
new file mode 100644
index 0000000000000..b4eea284636bf
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/CMakeLists.txt
@@ -0,0 +1,18 @@
+# Do NOT set LLVM_LINK_COMPONENTS and clang_target_link_libraries here.
+#
+# Setting them would cause LLVM libraries to be linked statically into this
+# MODULE, producing a second copy of LLVM in the process alongside the copy
+# already loaded by the host tool. Let the dynamic loader resolve every SSAF and
+# LLVM symbol from the tool's address space at load time.
+
+add_llvm_library(SSAFExamplePlugin MODULE BUILDTREE_ONLY
+ TagsAnalysis.cpp
+ PairsAnalysis.cpp
+ TagsPairsAnalysis.cpp
+ PLUGIN_TOOL clang-ssaf-format
+ )
+
+# Pull in SSAF and LLVM include paths without any static link dependency.
+target_include_directories(SSAFExamplePlugin PRIVATE
+ $<TARGET_PROPERTY:clangScalableStaticAnalysisCore,INTERFACE_INCLUDE_DIRECTORIES>
+ )
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/PairsAnalysis.cpp b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/PairsAnalysis.cpp
new file mode 100644
index 0000000000000..94f08d7e9fb73
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/PairsAnalysis.cpp
@@ -0,0 +1,197 @@
+//===- PairsAnalysis.cpp - Pairs analysis for ExamplePlugin ---------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "AnalysisResults.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/Registry.h"
+#include <memory>
+#include <utility>
+#include <vector>
+
+using namespace clang::ssaf;
+using namespace llvm;
+using example_plugin::PairsAnalysisResult;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+// PairsEntitySummary
+//
+// Per-entity data: a list of (EntityId, EntityId) pairs. Stored in the LU
+// data section under summary_name "PairsEntitySummary". Serialized as:
+// { "pairs": [{"first": {...}, "second": {...}}, ...] }
+//===----------------------------------------------------------------------===//
+
+struct PairsEntitySummary final : EntitySummary {
+ static SummaryName summaryName() { return SummaryName("PairsEntitySummary"); }
+
+ SummaryName getSummaryName() const override {
+ return SummaryName("PairsEntitySummary");
+ }
+
+ std::vector<std::pair<EntityId, EntityId>> Pairs;
+};
+
+json::Object serializePairsEntitySummary(const EntitySummary &ES,
+ JSONFormat::EntityIdToJSONFn ToJSON) {
+ const auto &S = static_cast<const PairsEntitySummary &>(ES);
+ json::Array PairsArray;
+ for (const auto &[First, Second] : S.Pairs) {
+ PairsArray.push_back(json::Object{
+ {"first", ToJSON(First)},
+ {"second", ToJSON(Second)},
+ });
+ }
+ return json::Object{{"pairs", std::move(PairsArray)}};
+}
+
+Expected<std::unique_ptr<EntitySummary>>
+deserializePairsEntitySummary(const json::Object &Obj, EntityIdTable &,
+ JSONFormat::EntityIdFromJSONFn FromJSON) {
+ auto Result = std::make_unique<PairsEntitySummary>();
+ const json::Array *PairsArray = Obj.getArray("pairs");
+ if (!PairsArray) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid field 'pairs'");
+ }
+ for (const auto &[Index, Value] : llvm::enumerate(*PairsArray)) {
+ const json::Object *Pair = Value.getAsObject();
+ if (!Pair) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "pairs element at index %zu is not a JSON object", Index);
+ }
+ const json::Object *FirstObj = Pair->getObject("first");
+ if (!FirstObj) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "missing or invalid 'first' field at index '%zu'", Index);
+ }
+ const json::Object *SecondObj = Pair->getObject("second");
+ if (!SecondObj) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "missing or invalid 'second' field at index '%zu'", Index);
+ }
+ auto ExpectedFirst = FromJSON(*FirstObj);
+ if (!ExpectedFirst) {
+ return createStringError(inconvertibleErrorCode(),
+ "invalid 'first' entity id at index '%zu': %s",
+ Index,
+ toString(ExpectedFirst.takeError()).c_str());
+ }
+ auto ExpectedSecond = FromJSON(*SecondObj);
+ if (!ExpectedSecond) {
+ return createStringError(inconvertibleErrorCode(),
+ "invalid 'second' entity id at index '%zu': %s",
+ Index,
+ toString(ExpectedSecond.takeError()).c_str());
+ }
+ Result->Pairs.emplace_back(*ExpectedFirst, *ExpectedSecond);
+ }
+ return std::move(Result);
+}
+
+struct PairsEntitySummaryFormatInfo final : JSONFormat::FormatInfo {
+ PairsEntitySummaryFormatInfo()
+ : JSONFormat::FormatInfo(SummaryName("PairsEntitySummary"),
+ serializePairsEntitySummary,
+ deserializePairsEntitySummary) {}
+};
+
+llvm::Registry<JSONFormat::FormatInfo>::Add<PairsEntitySummaryFormatInfo>
+ RegisterPairsEntitySummaryForJSON(
+ "PairsEntitySummary", "JSON format info for PairsEntitySummary");
+
+//===----------------------------------------------------------------------===//
+// PairsAnalysisResult serialization
+//
+// Per-entity pair count. Serialized as:
+// { "pair_counts": [{"entity_id": {...}, "count": N}, ...] }
+//===----------------------------------------------------------------------===//
+
+json::Object serializePairsAnalysisResult(const PairsAnalysisResult &R,
+ JSONFormat::EntityIdToJSONFn ToJSON) {
+ json::Array Arr;
+ for (const auto &[EI, Count] : R.PairCounts) {
+ Arr.push_back(json::Object{{"entity_id", ToJSON(EI)}, {"count", Count}});
+ }
+ return json::Object{{"pair_counts", std::move(Arr)}};
+}
+
+Expected<std::unique_ptr<AnalysisResult>>
+deserializePairsAnalysisResult(const json::Object &Obj,
+ JSONFormat::EntityIdFromJSONFn FromJSON) {
+ const json::Array *Arr = Obj.getArray("pair_counts");
+ if (!Arr) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid field 'pair_counts'");
+ }
+
+ auto R = std::make_unique<PairsAnalysisResult>();
+ for (const auto &[Index, Val] : llvm::enumerate(*Arr)) {
+ const json::Object *Entry = Val.getAsObject();
+ if (!Entry) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "pair_counts element at index %zu is not an object", Index);
+ }
+ const json::Object *EIObj = Entry->getObject("entity_id");
+ if (!EIObj) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "missing or invalid 'entity_id' field at index %zu", Index);
+ }
+ auto ExpectedEI = FromJSON(*EIObj);
+ if (!ExpectedEI) {
+ return ExpectedEI.takeError();
+ }
+
+ auto CountVal = Entry->getInteger("count");
+ if (!CountVal) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid 'count' field at index %zu",
+ Index);
+ }
+ R->PairCounts.emplace_back(*ExpectedEI, static_cast<int>(*CountVal));
+ }
+ return std::move(R);
+}
+
+JSONFormat::AnalysisResultRegistry::Add<PairsAnalysisResult>
+ RegisterPairsResultForJSON(serializePairsAnalysisResult,
+ deserializePairsAnalysisResult);
+
+//===----------------------------------------------------------------------===//
+// PairsAnalysis
+//
+// SummaryAnalysis that reads per-entity PairsEntitySummary data and counts
+// the number of pairs per entity, producing (EntityId, count) pairs.
+//===----------------------------------------------------------------------===//
+
+class PairsAnalysis final
+ : public SummaryAnalysis<PairsAnalysisResult, PairsEntitySummary> {
+public:
+ using ResultType = PairsAnalysisResult;
+
+ llvm::Error add(EntityId Id, const PairsEntitySummary &S) override {
+ getResult().PairCounts.emplace_back(Id, static_cast<int>(S.Pairs.size()));
+ return llvm::Error::success();
+ }
+};
+
+AnalysisRegistry::Add<PairsAnalysis>
+ RegisterPairsAnalysis("Counts pairs per entity");
+
+} // namespace
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsAnalysis.cpp b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsAnalysis.cpp
new file mode 100644
index 0000000000000..9d74b7b30d9bf
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsAnalysis.cpp
@@ -0,0 +1,160 @@
+//===- TagsAnalysis.cpp - Tags analysis for ExamplePlugin -----------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "AnalysisResults.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/Registry.h"
+#include <algorithm>
+#include <memory>
+#include <string>
+#include <vector>
+
+using namespace clang::ssaf;
+using namespace llvm;
+using example_plugin::TagsAnalysisResult;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+// TagsEntitySummary
+//
+// Per-entity data: a list of string tags. Stored in the LU data section
+// under summary_name "TagsEntitySummary". Serialized as:
+// { "tags": ["tag1", "tag2", ...] }
+//===----------------------------------------------------------------------===//
+
+struct TagsEntitySummary final : EntitySummary {
+ static SummaryName summaryName() { return SummaryName("TagsEntitySummary"); }
+
+ SummaryName getSummaryName() const override {
+ return SummaryName("TagsEntitySummary");
+ }
+
+ std::vector<std::string> Tags;
+};
+
+json::Object serializeTagsEntitySummary(const EntitySummary &ES,
+ JSONFormat::EntityIdToJSONFn) {
+ const auto &S = static_cast<const TagsEntitySummary &>(ES);
+ json::Array TagsArray;
+ TagsArray.reserve(S.Tags.size());
+ llvm::append_range(TagsArray, S.Tags);
+ return json::Object{{"tags", std::move(TagsArray)}};
+}
+
+Expected<std::unique_ptr<EntitySummary>>
+deserializeTagsEntitySummary(const json::Object &Obj, EntityIdTable &,
+ JSONFormat::EntityIdFromJSONFn) {
+ const json::Array *TagsArray = Obj.getArray("tags");
+ if (!TagsArray) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid field 'tags'");
+ }
+
+ auto S = std::make_unique<TagsEntitySummary>();
+ for (const auto &[Index, Val] : llvm::enumerate(*TagsArray)) {
+ auto Str = Val.getAsString();
+ if (!Str) {
+ return createStringError(inconvertibleErrorCode(),
+ "tags element at index %zu is not a string",
+ Index);
+ }
+ S->Tags.push_back(Str->str());
+ }
+ return std::move(S);
+}
+
+struct TagsEntitySummaryFormatInfo final : JSONFormat::FormatInfo {
+ TagsEntitySummaryFormatInfo()
+ : JSONFormat::FormatInfo(SummaryName("TagsEntitySummary"),
+ serializeTagsEntitySummary,
+ deserializeTagsEntitySummary) {}
+};
+
+llvm::Registry<JSONFormat::FormatInfo>::Add<TagsEntitySummaryFormatInfo>
+ RegisterTagsEntitySummaryForJSON("TagsEntitySummary",
+ "JSON format info for TagsEntitySummary");
+
+//===----------------------------------------------------------------------===//
+// TagsAnalysisResult serialization
+//
+// Sorted, deduplicated list of all tags seen across entities. Serialized as:
+// { "tags": ["tag1", "tag2", ...] }
+//===----------------------------------------------------------------------===//
+
+json::Object serializeTagsAnalysisResult(const TagsAnalysisResult &R,
+ JSONFormat::EntityIdToJSONFn) {
+ json::Array TagsArray;
+ TagsArray.reserve(R.Tags.size());
+ llvm::append_range(TagsArray, R.Tags);
+ return json::Object{{"tags", std::move(TagsArray)}};
+}
+
+Expected<std::unique_ptr<AnalysisResult>>
+deserializeTagsAnalysisResult(const json::Object &Obj,
+ JSONFormat::EntityIdFromJSONFn) {
+ const json::Array *TagsArray = Obj.getArray("tags");
+ if (!TagsArray) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid field 'tags'");
+ }
+
+ auto R = std::make_unique<TagsAnalysisResult>();
+ for (const auto &[Index, Val] : llvm::enumerate(*TagsArray)) {
+ auto S = Val.getAsString();
+ if (!S) {
+ return createStringError(inconvertibleErrorCode(),
+ "tags element at index %zu is not a string",
+ Index);
+ }
+ R->Tags.push_back(S->str());
+ }
+ return std::move(R);
+}
+
+JSONFormat::AnalysisResultRegistry::Add<TagsAnalysisResult>
+ RegisterTagsResultForJSON(serializeTagsAnalysisResult,
+ deserializeTagsAnalysisResult);
+
+//===----------------------------------------------------------------------===//
+// TagsAnalysis
+//
+// SummaryAnalysis that reads per-entity TagsEntitySummary data and collects
+// all unique tags into a sorted, deduplicated flat list.
+//===----------------------------------------------------------------------===//
+
+class TagsAnalysis final
+ : public SummaryAnalysis<TagsAnalysisResult, TagsEntitySummary> {
+public:
+ using ResultType = TagsAnalysisResult;
+
+ llvm::Error add(EntityId, const TagsEntitySummary &S) override {
+ for (const auto &Tag : S.Tags) {
+ getResult().Tags.push_back(Tag);
+ }
+ return llvm::Error::success();
+ }
+
+ llvm::Error finalize() override {
+ auto &Tags = getResult().Tags;
+ std::sort(Tags.begin(), Tags.end());
+ Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
+ return llvm::Error::success();
+ }
+};
+
+AnalysisRegistry::Add<TagsAnalysis>
+ RegisterTagsAnalysis("Collects unique tags across entities");
+
+} // namespace
diff --git a/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
new file mode 100644
index 0000000000000..5ceb0eb971673
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Plugins/ExamplePlugin/TagsPairsAnalysis.cpp
@@ -0,0 +1,136 @@
+//===- TagsPairsAnalysis.cpp - Derived analysis for ExamplePlugin ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "AnalysisResults.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/Registry.h"
+#include <memory>
+
+using namespace clang::ssaf;
+using namespace llvm;
+using example_plugin::PairsAnalysisResult;
+using example_plugin::TagsAnalysisResult;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+// TagsPairsAnalysisResult
+//
+// Aggregate statistics derived from TagsAnalysisResult and
+// PairsAnalysisResult. Serialized as:
+// { "unique_tag_count": N, "entity_count": N,
+// "total_pair_count": N, "max_pairs_per_entity": N }
+//===----------------------------------------------------------------------===//
+
+struct TagsPairsAnalysisResult final : AnalysisResult {
+ static AnalysisName analysisName() {
+ return AnalysisName("TagsPairsAnalysisResult");
+ }
+
+ int UniqueTagCount = 0;
+ int EntityCount = 0;
+ int TotalPairCount = 0;
+ int MaxPairsPerEntity = 0;
+};
+
+json::Object serializeTagsPairsAnalysisResult(const TagsPairsAnalysisResult &R,
+ JSONFormat::EntityIdToJSONFn) {
+ return json::Object{{"unique_tag_count", R.UniqueTagCount},
+ {"entity_count", R.EntityCount},
+ {"total_pair_count", R.TotalPairCount},
+ {"max_pairs_per_entity", R.MaxPairsPerEntity}};
+}
+
+Expected<std::unique_ptr<AnalysisResult>>
+deserializeTagsPairsAnalysisResult(const json::Object &Obj,
+ JSONFormat::EntityIdFromJSONFn) {
+ auto R = std::make_unique<TagsPairsAnalysisResult>();
+
+ auto UTC = Obj.getInteger("unique_tag_count");
+ if (!UTC) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid 'unique_tag_count'");
+ }
+ R->UniqueTagCount = static_cast<int>(*UTC);
+
+ auto EC = Obj.getInteger("entity_count");
+ if (!EC) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid 'entity_count'");
+ }
+ R->EntityCount = static_cast<int>(*EC);
+
+ auto TPC = Obj.getInteger("total_pair_count");
+ if (!TPC) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid 'total_pair_count'");
+ }
+ R->TotalPairCount = static_cast<int>(*TPC);
+
+ auto MPE = Obj.getInteger("max_pairs_per_entity");
+ if (!MPE) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid 'max_pairs_per_entity'");
+ }
+ R->MaxPairsPerEntity = static_cast<int>(*MPE);
+
+ return std::move(R);
+}
+
+JSONFormat::AnalysisResultRegistry::Add<TagsPairsAnalysisResult>
+ RegisterSummaryResultForJSON(serializeTagsPairsAnalysisResult,
+ deserializeTagsPairsAnalysisResult);
+
+//===----------------------------------------------------------------------===//
+// TagsPairsAnalysis
+//
+// DerivedAnalysis that depends on TagsAnalysisResult and PairsAnalysisResult.
+// Computes aggregate statistics:
+// - unique_tag_count: number of distinct tags
+// - entity_count: number of entities with pair data
+// - total_pair_count: sum of all per-entity pair counts
+// - max_pairs_per_entity: maximum pairs on any single entity
+//===----------------------------------------------------------------------===//
+
+class TagsPairsAnalysis final
+ : public DerivedAnalysis<TagsPairsAnalysisResult, TagsAnalysisResult,
+ PairsAnalysisResult> {
+public:
+ using ResultType = TagsPairsAnalysisResult;
+
+ llvm::Error initialize(const TagsAnalysisResult &Tags,
+ const PairsAnalysisResult &Pairs) override {
+ getResult().UniqueTagCount = static_cast<int>(Tags.Tags.size());
+ getResult().EntityCount = static_cast<int>(Pairs.PairCounts.size());
+
+ int Total = 0;
+ int Max = 0;
+ for (const auto &[Id, Count] : Pairs.PairCounts) {
+ Total += Count;
+ if (Count > Max)
+ Max = Count;
+ }
+ getResult().TotalPairCount = Total;
+ getResult().MaxPairsPerEntity = Max;
+
+ return llvm::Error::success();
+ }
+
+ llvm::Expected<bool> step() override {
+ return false; // converged in initialize
+ }
+};
+
+AnalysisRegistry::Add<TagsPairsAnalysis>
+ RegisterTagsPairsAnalysis("Aggregate tag and pair statistics");
+
+} // namespace
diff --git a/clang/lib/ScalableStaticAnalysis/SourceTransformation/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/SourceTransformation/CMakeLists.txt
new file mode 100644
index 0000000000000..3761ee7463f86
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/SourceTransformation/CMakeLists.txt
@@ -0,0 +1,13 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+add_clang_library(clangScalableStaticAnalysisSourceTransformation
+ TransformationRegistry.cpp
+
+ LINK_LIBS
+ clangAST
+ clangBasic
+ clangScalableStaticAnalysisCore
+ clangToolingCore
+ )
diff --git a/clang/lib/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.cpp b/clang/lib/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.cpp
new file mode 100644
index 0000000000000..505b0ee4f9e51
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.cpp
@@ -0,0 +1,44 @@
+//===- TransformationRegistry.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.h"
+#include <memory>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace clang::ssaf {
+// NOLINTNEXTLINE(misc-use-internal-linkage)
+volatile int SSAFSourceTransformationAnchorSource = 0;
+} // namespace clang::ssaf
+
+LLVM_DEFINE_REGISTRY(clang::ssaf::TransformationRegistry)
+
+bool ssaf::isTransformationRegistered(llvm::StringRef Name) {
+ for (const auto &Entry : TransformationRegistry::entries())
+ if (Entry.getName() == Name)
+ return true;
+ return false;
+}
+
+std::unique_ptr<Transformation>
+ssaf::makeTransformation(llvm::StringRef Name, const WPASuite &Suite,
+ SourceEditEmitter &Edits,
+ TransformationReportEmitter &Report) {
+ for (const auto &Entry : TransformationRegistry::entries())
+ if (Entry.getName() == Name)
+ return Entry.instantiate(Suite, Edits, Report);
+ assert(false && "Unknown Transformation name");
+ return nullptr;
+}
+
+void ssaf::printAvailableTransformations(llvm::raw_ostream &OS) {
+ OS << "OVERVIEW: Available SSAF source transformations:\n\n";
+ for (const auto &Entry : TransformationRegistry::entries())
+ OS << " " << Entry.getName() << " - " << Entry.getDesc() << "\n";
+}
diff --git a/clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt b/clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt
new file mode 100644
index 0000000000000..2ca9a8d9b84d0
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Tool/CMakeLists.txt
@@ -0,0 +1,12 @@
+set(LLVM_LINK_COMPONENTS
+ Support
+ TargetParser
+ )
+
+add_clang_library(clangScalableStaticAnalysisTool
+ Utils.cpp
+
+ LINK_LIBS
+ clangBasic
+ clangScalableStaticAnalysisCore
+ )
diff --git a/clang/lib/ScalableStaticAnalysis/Tool/Utils.cpp b/clang/lib/ScalableStaticAnalysis/Tool/Utils.cpp
new file mode 100644
index 0000000000000..6a740f57741d7
--- /dev/null
+++ b/clang/lib/ScalableStaticAnalysis/Tool/Utils.cpp
@@ -0,0 +1,207 @@
+//===- Utils.cpp - Shared utilities for SSAF tools ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Tool/Utils.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/WithColor.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <memory>
+#include <string>
+
+using namespace clang::ssaf;
+
+namespace fs = llvm::sys::fs;
+namespace path = llvm::sys::path;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+// Error Messages
+//===----------------------------------------------------------------------===//
+
+namespace ErrorMessages {
+
+constexpr const char *CannotValidatePath = "failed to validate path '{0}': {1}";
+
+constexpr const char *ExtensionNotSupplied = "Extension not supplied";
+
+constexpr const char *NoFormatForExtension =
+ "No format registered for extension '{0}'";
+
+constexpr const char *PathDoesNotExist = "Path does not exist";
+
+constexpr const char *PathIsNotAFile = "Path is not a file";
+
+constexpr const char *OutputDirectoryMissing =
+ "Parent directory does not exist";
+
+constexpr const char *OutputDirectoryNotWritable =
+ "Parent directory is not writable";
+
+constexpr const char *FileAlreadyExists = "File already exists";
+
+constexpr const char *FailedToLoadPlugin = "failed to load plugin '{0}': {1}";
+
+} // namespace ErrorMessages
+
+llvm::StringRef ToolName;
+llvm::StringRef ToolVersion;
+
+void printVersion(llvm::raw_ostream &OS) {
+ OS << ToolName << " " << ToolVersion << "\n";
+}
+
+// Returns the SerializationFormat registered for \p Extension, or nullptr if
+// none is registered. Results are cached for the lifetime of the process.
+// FIXME: This will be revisited after we add support for registering formats
+// with extensions.
+SerializationFormat *getFormatForExtension(llvm::StringRef Extension) {
+ // This cache is not thread-safe. SSAF tools are single-threaded CLIs, so
+ // concurrent calls to this function are not expected.
+
+ // Realistically, we don't expect to encounter more than four registered
+ // formats.
+ static llvm::SmallVector<
+ std::pair<std::string, std::unique_ptr<SerializationFormat>>, 4>
+ ExtensionFormatList;
+
+ // Most recently used format is most likely to be reused again.
+ auto ReversedList = llvm::reverse(ExtensionFormatList);
+ auto It = llvm::find_if(ReversedList, [&](const auto &Entry) {
+ return Entry.first == Extension;
+ });
+ if (It != ReversedList.end()) {
+ return It->second.get();
+ }
+
+ if (!isFormatRegistered(Extension)) {
+ return nullptr;
+ }
+
+ auto Format = makeFormat(Extension);
+ SerializationFormat *Result = Format.get();
+ assert(Result &&
+ "makeFormat must return non-null for a registered extension");
+
+ ExtensionFormatList.emplace_back(Extension, std::move(Format));
+
+ return Result;
+}
+
+FormatFile fromPath(llvm::StringRef Path) {
+ llvm::StringRef Extension = path::extension(Path);
+ if (Extension.empty()) {
+ fail(ErrorMessages::CannotValidatePath, Path,
+ ErrorMessages::ExtensionNotSupplied);
+ }
+
+ Extension = Extension.drop_front();
+ SerializationFormat *Format = getFormatForExtension(Extension);
+ if (!Format) {
+ std::string BadExtension =
+ llvm::formatv(ErrorMessages::NoFormatForExtension, Extension);
+ fail(ErrorMessages::CannotValidatePath, Path, BadExtension);
+ }
+
+ return {Path.str(), Format};
+}
+
+} // namespace
+
+llvm::StringRef clang::ssaf::getToolName() { return ToolName; }
+
+[[noreturn]] void clang::ssaf::fail(const char *Msg) {
+ llvm::WithColor::error(llvm::errs(), ToolName) << Msg << "\n";
+ llvm::sys::Process::Exit(1);
+}
+
+[[noreturn]] void clang::ssaf::fail(llvm::Error Err) {
+ std::string Message = llvm::toString(std::move(Err));
+ clang::ssaf::fail(Message.data());
+}
+
+void clang::ssaf::loadPlugins(llvm::ArrayRef<std::string> Paths) {
+ for (const std::string &PluginPath : Paths) {
+ if (!fs::exists(PluginPath)) {
+ fail(ErrorMessages::FailedToLoadPlugin, PluginPath,
+ ErrorMessages::PathDoesNotExist);
+ }
+ std::string ErrMsg;
+ if (llvm::sys::DynamicLibrary::LoadLibraryPermanently(PluginPath.c_str(),
+ &ErrMsg)) {
+ fail(ErrorMessages::FailedToLoadPlugin, PluginPath, ErrMsg);
+ }
+ }
+}
+
+void clang::ssaf::initTool(int argc, const char **argv, llvm::StringRef Version,
+ llvm::cl::OptionCategory &Category,
+ llvm::StringRef ToolHeading) {
+ // path::stem strips the .exe extension on Windows so ToolName is consistent.
+ ToolName = path::stem(argv[0]);
+
+ // Set tool version for the version printer.
+ ToolVersion = Version;
+
+ // Hide options unrelated to the tool from --help output.
+ llvm::cl::HideUnrelatedOptions(Category);
+
+ // Register a custom version printer for the --version flag.
+ llvm::cl::SetVersionPrinter(printVersion);
+
+ // Parse command-line arguments and exit with an error if they are invalid.
+ std::string Overview = (ToolHeading + "\n").str();
+ llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
+}
+
+clang::ssaf::FormatFile
+clang::ssaf::FormatFile::fromInputPath(llvm::StringRef Path) {
+ if (!fs::exists(Path)) {
+ fail(ErrorMessages::CannotValidatePath, Path,
+ ErrorMessages::PathDoesNotExist);
+ }
+
+ if (!fs::is_regular_file(Path)) {
+ fail(ErrorMessages::CannotValidatePath, Path,
+ ErrorMessages::PathIsNotAFile);
+ }
+
+ return fromPath(Path);
+}
+
+clang::ssaf::FormatFile
+clang::ssaf::FormatFile::fromOutputPath(llvm::StringRef Path) {
+ if (fs::exists(Path)) {
+ fail(ErrorMessages::CannotValidatePath, Path,
+ ErrorMessages::FileAlreadyExists);
+ }
+
+ llvm::StringRef ParentDir = path::parent_path(Path);
+ llvm::StringRef DirToCheck = ParentDir.empty() ? "." : ParentDir;
+
+ if (!fs::exists(DirToCheck)) {
+ fail(ErrorMessages::CannotValidatePath, Path,
+ ErrorMessages::OutputDirectoryMissing);
+ }
+
+ if (fs::access(DirToCheck, fs::AccessMode::Write)) {
+ fail(ErrorMessages::CannotValidatePath, Path,
+ ErrorMessages::OutputDirectoryNotWritable);
+ }
+
+ return fromPath(Path);
+}
diff --git a/clang/unittests/ScalableStaticAnalysis/ASTEntityMappingTest.cpp b/clang/unittests/ScalableStaticAnalysis/ASTEntityMappingTest.cpp
new file mode 100644
index 0000000000000..c34e92cb9fa5d
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/ASTEntityMappingTest.cpp
@@ -0,0 +1,341 @@
+//===- ASTEntityMappingTest.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "FindDecl.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::ssaf {
+namespace {
+
+TEST(ASTEntityMappingTest, FunctionDecl) {
+ auto AST = tooling::buildASTFromCode(R"cpp(void foo() {})cpp");
+ auto &Ctx = AST->getASTContext();
+
+ const auto *FD = findFnByName("foo", Ctx);
+ ASSERT_NE(FD, nullptr);
+
+ auto EntityName = getEntityName(FD);
+ EXPECT_TRUE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, VarDecl) {
+ auto AST = tooling::buildASTFromCode(R"cpp(int x = 42;)cpp");
+ auto &Ctx = AST->getASTContext();
+
+ const auto *VD = findDeclByName<VarDecl>("x", Ctx);
+ ASSERT_NE(VD, nullptr);
+
+ auto EntityName = getEntityName(VD);
+ EXPECT_TRUE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, ParmVarDecl) {
+ auto AST = tooling::buildASTFromCode(R"cpp(void foo(int x) {})cpp");
+ auto &Ctx = AST->getASTContext();
+
+ const auto *FD = findFnByName("foo", Ctx);
+ ASSERT_NE(FD, nullptr);
+ ASSERT_EQ(FD->param_size(), 1u);
+
+ const auto *PVD = FD->getParamDecl(0);
+ ASSERT_NE(PVD, nullptr);
+
+ auto EntityName = getEntityName(PVD);
+ EXPECT_TRUE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, RecordDecl) {
+ auto AST = tooling::buildASTFromCode(R"cpp(struct S {};)cpp");
+ auto &Ctx = AST->getASTContext();
+
+ const auto *RD = findDeclByName<RecordDecl>("S", Ctx);
+ ASSERT_NE(RD, nullptr);
+
+ auto EntityName = getEntityName(RD);
+ EXPECT_TRUE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, FieldDecl) {
+ auto AST = tooling::buildASTFromCode(R"cpp(struct S { int field; };)cpp");
+ auto &Ctx = AST->getASTContext();
+
+ const auto *FD = findDeclByName<FieldDecl>("field", Ctx);
+ ASSERT_NE(FD, nullptr);
+
+ auto EntityName = getEntityName(FD);
+ EXPECT_TRUE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, NullDecl) {
+ auto EntityName = getEntityName(nullptr);
+ EXPECT_FALSE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, ImplicitDeclLambda) {
+ auto AST = tooling::buildASTFromCode(
+ R"cpp(
+ auto L = [](){};
+ )cpp",
+ "test.cpp", std::make_shared<PCHContainerOperations>());
+ auto &Ctx = AST->getASTContext();
+
+ auto Matcher = cxxRecordDecl(isImplicit()).bind("decl");
+ auto Matches = match(Matcher, Ctx);
+ ASSERT_GT(Matches.size(), 0u);
+
+ const auto *ImplCXXRD = Matches[0].getNodeAs<CXXRecordDecl>("decl");
+ ASSERT_NE(ImplCXXRD, nullptr);
+
+ auto EntityName = getEntityName(ImplCXXRD);
+ EXPECT_FALSE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, BuiltinFunction) {
+ auto AST = tooling::buildASTFromCode(R"cpp(
+ void test() {
+ __builtin_memcpy(0, 0, 0);
+ }
+ )cpp");
+ auto &Ctx = AST->getASTContext();
+
+ // Find the builtin call
+ auto Matcher = callExpr().bind("call");
+ auto Matches = match(Matcher, Ctx);
+ ASSERT_EQ(Matches.size(), 1ul);
+
+ const auto *CE = Matches[0].getNodeAs<CallExpr>("call");
+ ASSERT_NE(CE, nullptr);
+
+ const auto *Callee = CE->getDirectCallee();
+ ASSERT_NE(Callee, nullptr);
+ ASSERT_NE(Callee->getBuiltinID(), 0u /* not a built-in */);
+
+ auto EntityName = getEntityName(Callee);
+ EXPECT_FALSE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, UnsupportedDecl) {
+ auto AST = tooling::buildASTFromCode(R"cpp(namespace N {})cpp");
+ auto &Ctx = AST->getASTContext();
+
+ const auto *ND = findDeclByName<NamespaceDecl>("N", Ctx);
+ ASSERT_NE(ND, nullptr);
+
+ auto EntityName = getEntityName(ND);
+ EXPECT_FALSE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, FunctionReturn) {
+ auto AST = tooling::buildASTFromCode(R"cpp(int foo() { return 42; })cpp");
+ auto &Ctx = AST->getASTContext();
+
+ const auto *FD = findFnByName("foo", Ctx);
+ ASSERT_NE(FD, nullptr);
+
+ auto EntityName = getEntityNameForReturn(FD);
+ EXPECT_TRUE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, FunctionReturnNull) {
+ auto EntityName = getEntityNameForReturn(nullptr);
+ EXPECT_FALSE(EntityName.has_value());
+}
+
+TEST(ASTEntityMappingTest, FunctionReturnBuiltin) {
+ auto AST = tooling::buildASTFromCode(R"cpp(
+ void test() {
+ __builtin_memcpy(0, 0, 0);
+ }
+ )cpp");
+ auto &Ctx = AST->getASTContext();
+
+ // Find the builtin call
+ auto Matcher = callExpr().bind("call");
+ auto Matches = match(Matcher, Ctx);
+ ASSERT_FALSE(Matches.empty());
+
+ const auto *CE = Matches[0].getNodeAs<CallExpr>("call");
+ ASSERT_NE(CE, nullptr);
+
+ const auto *Callee = CE->getDirectCallee();
+ if (Callee && Callee->getBuiltinID()) {
+ auto EntityName = getEntityNameForReturn(Callee);
+ EXPECT_FALSE(EntityName.has_value());
+ }
+}
+
+TEST(ASTEntityMappingTest, DifferentFunctionsDifferentNames) {
+ auto AST = tooling::buildASTFromCode(R"cpp(
+ void foo() {}
+ void bar() {}
+ )cpp");
+ auto &Ctx = AST->getASTContext();
+
+ const auto *Foo = findFnByName("foo", Ctx);
+ const auto *Bar = findFnByName("bar", Ctx);
+ ASSERT_NE(Foo, nullptr);
+ ASSERT_NE(Bar, nullptr);
+
+ auto FooName = getEntityName(Foo);
+ auto BarName = getEntityName(Bar);
+ ASSERT_TRUE(FooName.has_value());
+ ASSERT_TRUE(BarName.has_value());
+
+ EXPECT_NE(*FooName, *BarName);
+}
+
+// Redeclaration tests
+
+TEST(ASTEntityMappingTest, FunctionRedeclaration) {
+ auto AST = tooling::buildASTFromCode(R"cpp(
+ void foo();
+ void foo() {}
+ )cpp");
+ auto &Ctx = AST->getASTContext();
+
+ auto Matcher = functionDecl(hasName("foo")).bind("decl");
+ auto Matches = match(Matcher, Ctx);
+ ASSERT_GE(Matches.size(), 2u);
+
+ const auto *FirstDecl = Matches[0].getNodeAs<FunctionDecl>("decl");
+ ASSERT_NE(FirstDecl, nullptr);
+
+ auto FirstName = getEntityName(FirstDecl);
+ ASSERT_TRUE(FirstName.has_value());
+
+ for (size_t I = 1; I < Matches.size(); ++I) {
+ const auto *Decl = Matches[I].getNodeAs<FunctionDecl>("decl");
+ ASSERT_NE(Decl, nullptr);
+
+ auto Name = getEntityName(Decl);
+ ASSERT_TRUE(Name.has_value());
+ EXPECT_EQ(*FirstName, *Name);
+ }
+}
+
+TEST(ASTEntityMappingTest, VarRedeclaration) {
+ auto AST = tooling::buildASTFromCode(R"cpp(
+ extern int x;
+ int x = 42;
+ )cpp");
+ auto &Ctx = AST->getASTContext();
+
+ auto Matcher = varDecl(hasName("x")).bind("decl");
+ auto Matches = match(Matcher, Ctx);
+ ASSERT_EQ(Matches.size(), 2u);
+
+ const auto *FirstDecl = Matches[0].getNodeAs<VarDecl>("decl");
+ ASSERT_NE(FirstDecl, nullptr);
+
+ auto FirstName = getEntityName(FirstDecl);
+ ASSERT_TRUE(FirstName.has_value());
+
+ for (size_t I = 1; I < Matches.size(); ++I) {
+ const auto *Decl = Matches[I].getNodeAs<VarDecl>("decl");
+ ASSERT_NE(Decl, nullptr);
+
+ auto Name = getEntityName(Decl);
+ ASSERT_TRUE(Name.has_value());
+ EXPECT_EQ(*FirstName, *Name);
+ }
+}
+
+TEST(ASTEntityMappingTest, RecordRedeclaration) {
+ auto AST = tooling::buildASTFromCode(R"cpp(
+ struct S;
+ struct S {};
+ )cpp");
+ auto &Ctx = AST->getASTContext();
+
+ auto Matcher = recordDecl(hasName("S"), unless(isImplicit())).bind("decl");
+ auto Matches = match(Matcher, Ctx);
+ ASSERT_GE(Matches.size(), 2u);
+
+ const auto *FirstDecl = Matches[0].getNodeAs<RecordDecl>("decl");
+ ASSERT_NE(FirstDecl, nullptr);
+
+ auto FirstName = getEntityName(FirstDecl);
+ ASSERT_TRUE(FirstName.has_value());
+
+ for (size_t I = 1; I < Matches.size(); ++I) {
+ const auto *Decl = Matches[I].getNodeAs<RecordDecl>("decl");
+ ASSERT_NE(Decl, nullptr);
+
+ auto Name = getEntityName(Decl);
+ ASSERT_TRUE(Name.has_value());
+ EXPECT_EQ(*FirstName, *Name);
+ }
+}
+
+TEST(ASTEntityMappingTest, ParmVarDeclRedeclaration) {
+ auto AST = tooling::buildASTFromCode(R"cpp(
+ void foo(int);
+ void foo(int x);
+ void foo(int y);
+ void foo(int x) {}
+ )cpp");
+ auto &Ctx = AST->getASTContext();
+
+ auto Matcher = functionDecl(hasName("foo")).bind("decl");
+ auto Matches = match(Matcher, Ctx);
+ ASSERT_GE(Matches.size(), 2u);
+
+ const auto *FirstFuncDecl = Matches[0].getNodeAs<FunctionDecl>("decl");
+ ASSERT_NE(FirstFuncDecl, nullptr);
+ ASSERT_GT(FirstFuncDecl->param_size(), 0u);
+
+ auto ParamEName = getEntityName(FirstFuncDecl->getParamDecl(0));
+ ASSERT_TRUE(ParamEName.has_value());
+
+ for (size_t I = 1; I < Matches.size(); ++I) {
+ const auto *FDecl = Matches[I].getNodeAs<FunctionDecl>("decl");
+ ASSERT_NE(FDecl, nullptr);
+ ASSERT_GT(FDecl->param_size(), 0u);
+
+ auto ParamRedeclEName = getEntityName(FDecl->getParamDecl(0));
+ EXPECT_EQ(*ParamEName, *ParamRedeclEName);
+ }
+}
+
+TEST(ASTEntityMappingTest, FunctionReturnRedeclaration) {
+ auto AST = tooling::buildASTFromCode(R"cpp(
+ int foo();
+ int foo() { return 42; }
+ )cpp");
+ auto &Ctx = AST->getASTContext();
+
+ auto Matcher = functionDecl(hasName("foo")).bind("decl");
+ auto Matches = match(Matcher, Ctx);
+ ASSERT_EQ(Matches.size(), 2u);
+
+ const auto *Decl1 = Matches[0].getNodeAs<FunctionDecl>("decl");
+ ASSERT_NE(Decl1, nullptr);
+ auto Name1 = getEntityNameForReturn(Decl1);
+ ASSERT_TRUE(Name1.has_value());
+
+ for (size_t I = 1; I < Matches.size(); ++I) {
+ const auto *FDecl = Matches[I].getNodeAs<FunctionDecl>("decl");
+ ASSERT_NE(FDecl, nullptr);
+
+ auto Name = getEntityNameForReturn(Decl1);
+ ASSERT_TRUE(Name.has_value());
+ EXPECT_EQ(*Name1, *Name);
+ }
+}
+
+} // namespace
+} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractorTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractorTest.cpp
new file mode 100644
index 0000000000000..f8769f3a9ce4d
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphExtractorTest.cpp
@@ -0,0 +1,517 @@
+//===- CallGraphExtractorTest.cpp -----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestFixture.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Frontend/SSAFOptions.h"
+#include "clang/ScalableStaticAnalysis/Analyses/CallGraph/CallGraphSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/ASTEntityMapping.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <cassert>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+AST_MATCHER(FunctionDecl, isPrimaryTemplate) {
+ return Node.getDescribedFunctionTemplate() != nullptr;
+}
+} // namespace
+
+static llvm::Expected<const NamedDecl *> findDecl(ASTContext &Ctx,
+ StringRef FnName) {
+ using namespace ast_matchers;
+ auto Matcher =
+ functionDecl(hasName(FnName), unless(isPrimaryTemplate())).bind("decl");
+ auto Matches = match(Matcher, Ctx);
+ if (Matches.empty())
+ return llvm::createStringError("No definition was found with name '" +
+ FnName + "'");
+ auto *ND = Matches[0].template getNodeAs<NamedDecl>("decl");
+ assert(ND);
+ return cast<NamedDecl>(ND->getCanonicalDecl());
+}
+
+// ============================================================================
+// PrintTo overload for readable failure messages.
+// Must live in the same namespace as Location (clang::ssaf) for ADL.
+// ============================================================================
+
+namespace clang::ssaf {
+void PrintTo(const CallGraphSummary::Location &Loc, std::ostream *OS) {
+ *OS << Loc.File << ":" << Loc.Line << ":" << Loc.Column;
+}
+void PrintTo(const CallGraphSummary &S, std::ostream *OS) {
+ *OS << "CallGraphSummary { PrettyName: '" << S.PrettyName << "'"
+ << ", Definition: ";
+ PrintTo(S.Definition, OS);
+ *OS << ", DirectCallees: " << S.DirectCallees.size()
+ << ", VirtualCallees: " << S.VirtualCallees.size() << " }";
+}
+} // namespace clang::ssaf
+
+namespace {
+
+MATCHER_P3(DefinedAt, File, Line, Column,
+ std::string(negation ? "is not" : "is") + " defined at " +
+ std::string(File) + ":" + testing::PrintToString(Line) + ":" +
+ testing::PrintToString(Column)) {
+ const auto &D = arg.Definition;
+ if (D.File != File || D.Line != Line || D.Column != Column) {
+ *result_listener << "defined at " << D.File << ":" << D.Line << ":"
+ << D.Column;
+ return false;
+ }
+ return true;
+}
+
+MATCHER_P(HasPrettyName, Name,
+ std::string(negation ? "doesn't have" : "has") + " pretty name '" +
+ testing::PrintToString(Name) + "'") {
+ if (arg.PrettyName != std::string(Name)) {
+ *result_listener << "has pretty name '" << arg.PrettyName << "'";
+ return false;
+ }
+ return true;
+}
+
+MATCHER(HasNoDirectCallees,
+ std::string(negation ? "has" : "has no") + " direct callees") {
+ if (!arg.DirectCallees.empty()) {
+ *result_listener << "has " << arg.DirectCallees.size()
+ << " direct callee(s)";
+ return false;
+ }
+ return true;
+}
+
+MATCHER(HasNoVirtualCallees,
+ std::string(negation ? "has" : "has no") + " virtual callees") {
+ if (!arg.VirtualCallees.empty()) {
+ *result_listener << "has " << arg.VirtualCallees.size()
+ << " virtual callee(s)";
+ return false;
+ }
+ return true;
+}
+
+template <typename... Matchers> auto hasSummaryThat(const Matchers &...Ms) {
+ using namespace testing;
+ return llvm::HasValue(Pointee(AllOf(std::move(Ms)...)));
+}
+
+// ============================================================================
+// Test fixture
+// ============================================================================
+
+static const SummaryName CallGraphName{CallGraphSummary::Name.str()};
+
+struct CallGraphExtractorTest : ssaf::TestFixture {
+ SSAFOptions Opts;
+ TUSummary Summary{
+ llvm::Triple("arm64-apple-macosx"),
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")};
+ TUSummaryBuilder Builder = TUSummaryBuilder(Summary, Opts);
+
+ /// Creates the AST and extractor, then extracts the summaries from the AST.
+ /// This will update the \c AST \c Builder and \c Summary data members.
+ void runExtractor(StringRef Code, ArrayRef<std::string> Args = {}) {
+ AST = tooling::buildASTFromCodeWithArgs(Code, Args);
+ auto Consumer = makeTUSummaryExtractor(CallGraphName.str(), Builder);
+ Consumer->HandleTranslationUnit(AST->getASTContext());
+ }
+
+ /// Tries to find the \c CallGraphSummary for the \p FnName function.
+ llvm::Expected<const CallGraphSummary *>
+ findSummary(llvm::StringRef FnName) const;
+
+ /// Matcher factory: matches a summary whose direct callees are exactly the
+ /// given set of function names (resolved to USRs via the entity table).
+ /// Uses \c testing::ResultOf to transform the summary's EntityId set into
+ /// USR strings before comparing with \c testing::ContainerEq.
+ auto hasDirectCallees(llvm::ArrayRef<StringRef> Names)
+ -> testing::Matcher<const CallGraphSummary &> {
+ auto MaybeUSRs = asUSRs(Names);
+ if (!MaybeUSRs) {
+ ADD_FAILURE() << "Failed to resolve callee names to USRs: "
+ << llvm::toString(MaybeUSRs.takeError());
+ return testing::An<const CallGraphSummary &>();
+ }
+ std::set<std::string> ExpectedUSRs = std::move(*MaybeUSRs);
+ return testing::ResultOf(
+ "direct callees",
+ [this](const CallGraphSummary &S) {
+ return getUSRsForCallees(S.DirectCallees);
+ },
+ testing::ContainerEq(ExpectedUSRs));
+ }
+
+ /// Matcher factory: same as \c hasDirectCallees but for virtual callees.
+ auto hasVirtualCallees(llvm::ArrayRef<StringRef> Names)
+ -> testing::Matcher<const CallGraphSummary &> {
+ auto MaybeUSRs = asUSRs(Names);
+ if (!MaybeUSRs) {
+ ADD_FAILURE() << "Failed to resolve callee names to USRs: "
+ << llvm::toString(MaybeUSRs.takeError());
+ return testing::A<const CallGraphSummary &>();
+ }
+ std::set<std::string> ExpectedUSRs = std::move(*MaybeUSRs);
+ return testing::ResultOf(
+ "virtual callees",
+ [this](const CallGraphSummary &S) {
+ return getUSRsForCallees(S.VirtualCallees);
+ },
+ testing::ContainerEq(ExpectedUSRs));
+ }
+
+private:
+ std::unique_ptr<ASTUnit> AST;
+
+ std::set<std::string>
+ getUSRsForCallees(const std::set<EntityId> &Callees) const;
+
+ /// Looks up the Decls for \p FnNames, and then transforms those into USRs.
+ llvm::Expected<std::set<std::string>>
+ asUSRs(llvm::ArrayRef<StringRef> FnNames);
+};
+
+llvm::Expected<const CallGraphSummary *>
+CallGraphExtractorTest::findSummary(llvm::StringRef FnName) const {
+ auto MaybeDecl = findDecl(AST->getASTContext(), FnName);
+ if (!MaybeDecl)
+ return MaybeDecl.takeError();
+
+ std::optional<EntityName> EntName = getEntityName(*MaybeDecl);
+ if (!EntName.has_value()) {
+ return llvm::createStringError("Failed to create an entity name for '" +
+ FnName + "'");
+ }
+
+ const auto &EntitiesTable = getEntities(getIdTable(Summary));
+ auto It = EntitiesTable.find(EntName.value());
+ if (It == EntitiesTable.end()) {
+ return llvm::createStringError(
+ "No entity ID was present in the entity table for '" + FnName + "'");
+ }
+ EntityId ID = It->second;
+ auto &Data = getData(Summary);
+ auto SummaryIt = Data.find(CallGraphName);
+ if (SummaryIt == Data.end())
+ return llvm::createStringError("There is no 'CallGraph' summary");
+ auto EntityIt = SummaryIt->second.find(ID);
+ if (EntityIt == SummaryIt->second.end()) {
+ return llvm::createStringError(
+ "There is no 'CallGraph' summary for entity ID " +
+ std::to_string(getIndex(ID)) + " aka. '" + FnName + "'");
+ }
+ return static_cast<const CallGraphSummary *>(EntityIt->second.get());
+}
+
+std::set<std::string> CallGraphExtractorTest::getUSRsForCallees(
+ const std::set<EntityId> &Callees) const {
+ std::set<std::string> USRs;
+
+ auto GatherCalleeUSRs = [&](const EntityName &Name, EntityId Id) {
+ if (llvm::is_contained(Callees, Id))
+ USRs.insert(TestFixture::getUSR(Name));
+ };
+ TestFixture::getIdTable(Summary).forEach(GatherCalleeUSRs);
+ assert(Callees.size() == USRs.size());
+ return USRs;
+}
+
+llvm::Expected<std::set<std::string>>
+CallGraphExtractorTest::asUSRs(llvm::ArrayRef<StringRef> FnNames) {
+ std::set<std::string> USRs;
+ ASTContext &Ctx = AST->getASTContext();
+ for (StringRef FnName : FnNames) {
+ auto MaybeDecl = findDecl(Ctx, FnName);
+ if (!MaybeDecl)
+ return MaybeDecl.takeError();
+ std::optional<EntityName> Name = getEntityName(MaybeDecl.get());
+ if (!Name.has_value()) {
+ return llvm::createStringError("Failed to get the USR of '" + FnName +
+ "'");
+ }
+ USRs.insert(getUSR(Name.value()));
+ }
+ assert(USRs.size() == FnNames.size());
+ return USRs;
+}
+
+// ============================================================================
+// Tests
+// ============================================================================
+
+TEST_F(CallGraphExtractorTest, SimpleFunctionCalls) {
+ runExtractor(R"cpp(
+ void a();
+ void b();
+ void calls_a_and_b(bool coin) {
+ if (coin)
+ a();
+ else
+ b();
+ }
+ )cpp");
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("calls_a_and_b"),
+ hasSummaryThat(hasDirectCallees({"a", "b"}), HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, NoCallees) {
+ runExtractor(R"cpp(
+ void leaf() {}
+ )cpp");
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("leaf"),
+ hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, TransitiveCalls) {
+ runExtractor(R"cpp(
+ void c() { /*empty*/ }
+ void b() { c(); }
+ void a() { b(); }
+ )cpp");
+
+ // a calls b (not c — we only record direct callees).
+ ASSERT_THAT_EXPECTED(findSummary("a"), hasSummaryThat(hasDirectCallees({"b"}),
+ HasNoVirtualCallees()));
+
+ // b calls c.
+ ASSERT_THAT_EXPECTED(findSummary("b"), hasSummaryThat(hasDirectCallees({"c"}),
+ HasNoVirtualCallees()));
+
+ // c calls nothing.
+ ASSERT_THAT_EXPECTED(findSummary("c"), hasSummaryThat(HasNoDirectCallees(),
+ HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, VirtualCallsAreImprecise) {
+ runExtractor(R"cpp(
+ struct Base {
+ virtual void virt();
+ };
+ struct Derived : Base {
+ void virt() override;
+ };
+ void caller(Base &Obj) {
+ Obj.virt();
+ }
+ )cpp");
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("caller"),
+ hasSummaryThat(HasNoDirectCallees(), hasVirtualCallees({"Base::virt"})));
+}
+
+TEST_F(CallGraphExtractorTest, MixedDirectAndVirtualCalls) {
+ runExtractor(R"cpp(
+ void direct_target();
+ struct Base {
+ virtual void virt();
+ };
+ void caller(Base &Obj) {
+ direct_target();
+ Obj.virt();
+ }
+ )cpp");
+
+ ASSERT_THAT_EXPECTED(findSummary("caller"),
+ hasSummaryThat(hasDirectCallees({"direct_target"}),
+ hasVirtualCallees({"Base::virt"})));
+}
+
+TEST_F(CallGraphExtractorTest, DeclarationsOnlyNoSummary) {
+ runExtractor(R"cpp(
+ void declared_only();
+ )cpp");
+
+ // No summary for functions without definitions.
+ EXPECT_FALSE(llvm::is_contained(getData(Summary), CallGraphName));
+}
+
+TEST_F(CallGraphExtractorTest, DuplicateCallees) {
+ runExtractor(R"cpp(
+ void target();
+ void caller() {
+ target();
+ target();
+ target();
+ }
+ )cpp");
+
+ // Despite three calls, there's only one unique callee.
+ ASSERT_THAT_EXPECTED(
+ findSummary("caller"),
+ hasSummaryThat(hasDirectCallees({"target"}), HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, NonVirtualMethodCalls) {
+ runExtractor(R"cpp(
+ struct S {
+ void method();
+ };
+ void caller() {
+ S s;
+ s.method();
+ }
+ )cpp");
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("caller"),
+ hasSummaryThat(hasDirectCallees({"method"}), HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, StaticMethodCalls) {
+ runExtractor(R"cpp(
+ struct S {
+ static void staticMethod();
+ };
+ void caller() {
+ S::staticMethod();
+ }
+ )cpp");
+
+ ASSERT_THAT_EXPECTED(findSummary("caller"),
+ hasSummaryThat(hasDirectCallees({"staticMethod"}),
+ HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, FunctionPtrCall) {
+ runExtractor(R"cpp(
+ void caller(int (&fptr)()) {
+ fptr();
+ }
+ )cpp");
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("caller"),
+ hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, ObjCMessageExprs) {
+ runExtractor(R"cpp(
+ @interface NSString
+ - (id)stringByAppendingString:(id)str;
+ @end
+
+ void caller(void) {
+ id msg = [@"Hello" stringByAppendingString:@", World!"];
+ }
+ )cpp",
+ {"-x", "objective-c"});
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("caller"),
+ hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, ObjCMessageToLocallyImplementedMethod) {
+ // When the receiver class is implemented in the same TU, `clang::CallGraph`
+ // resolves the ObjCMessageExpr (via `lookupPrivateMethod`) to an
+ // ObjCMethodDecl and adds it as a callee. The extractor must not abort on
+ // these — ObjC dispatch is dynamic and we don't model it as a direct callee.
+ runExtractor(R"cpp(
+ @interface NSObject @end
+ @interface Inner : NSObject
+ - (int) val;
+ @end
+ @implementation Inner
+ - (int) val { return 42; }
+ @end
+ int caller(Inner *x) { return [x val]; }
+ )cpp",
+ {"-x", "objective-c"});
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("caller"),
+ hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, ObjCPropertyDotSyntax) {
+ // Property dot-syntax (`x.val`) desugars to an ObjCMessageExpr to the
+ // synthesized getter; same dynamic dispatch as bracket syntax. Cover it
+ // explicitly because real-world hits often come through dot-syntax.
+ runExtractor(R"cpp(
+ @interface NSObject @end
+ @interface Inner : NSObject
+ @property (readonly) int val;
+ @end
+ @implementation Inner
+ @end
+ int caller(Inner *x) { return x.val; }
+ )cpp",
+ {"-x", "objective-c"});
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("caller"),
+ hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees()));
+}
+
+TEST_F(CallGraphExtractorTest, DefinitionLocation) {
+ runExtractor(R"cpp(
+ void callee_with_def() {}
+ void callee_without_def();
+ void caller(int n) {
+ if (n == 0) return;
+ callee_with_def();
+ callee_without_def();
+ caller(n - 1);
+ }
+ )cpp");
+
+ ASSERT_THAT_EXPECTED(
+ findSummary("caller"),
+ hasSummaryThat(
+ hasDirectCallees({"caller", "callee_with_def", "callee_without_def"}),
+ HasNoVirtualCallees(), DefinedAt("input.cc", 4U, 10U)));
+
+ ASSERT_THAT_EXPECTED(findSummary("callee_with_def"),
+ hasSummaryThat(HasNoDirectCallees(),
+ HasNoVirtualCallees(),
+ DefinedAt("input.cc", 2U, 10U)));
+}
+
+TEST_F(CallGraphExtractorTest, PrettyName) {
+ runExtractor(R"cpp(
+ template <class T, int N>
+ void templated_function(int *) {}
+ void caller(int n) {
+ templated_function<struct TypeTag, 404>(&n);
+ }
+ )cpp");
+
+ ASSERT_THAT_EXPECTED(findSummary("caller"),
+ hasSummaryThat(hasDirectCallees({"templated_function"}),
+ HasNoVirtualCallees(),
+ HasPrettyName("caller(int)")));
+
+ // FIXME: The template arguments are not spelled here.
+ ASSERT_THAT_EXPECTED(
+ findSummary("templated_function"),
+ hasSummaryThat(HasNoDirectCallees(), HasNoVirtualCallees(),
+ HasPrettyName("templated_function(int *)")));
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp
new file mode 100644
index 0000000000000..1c42ca0afe222
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowTest.cpp
@@ -0,0 +1,1443 @@
+//===- PointerFlowTest.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h"
+#include "TestFixture.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/SSAFOptions.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <memory>
+#include <type_traits>
+#include <variant>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+// Use FindEntityByName to identify entities in unit tests.
+// Unit tests are simple enough to meet the following assumptions:
+// - Named declarations should have unique names, they can be found by comparing
+// names with strings;
+// - Lambdas should initialize a variable named "X", they can be found using
+// "LambdaOfVar("X")";
+// - CXX Ctors should have unique combination of names and number of parameters,
+// they can be found using "CXXCtorOfNumParms(name, numParms)".
+struct LambdaOfVar {
+ StringRef VarName;
+};
+
+struct CXXCtorOfNumParms {
+ StringRef CXXCtorName;
+ unsigned NumParms;
+};
+
+using FindEntityByName =
+ std::variant<StringRef, CXXCtorOfNumParms, LambdaOfVar>;
+
+template <typename... Ts> struct Overloaded : Ts... {
+ using Ts::operator()...;
+};
+template <typename... Ts> Overloaded(Ts...) -> Overloaded<Ts...>;
+
+StringRef toStringRef(const FindEntityByName &N) {
+ return std::visit(
+ Overloaded{
+ [](StringRef S) -> StringRef { return S; },
+ [](const CXXCtorOfNumParms &L) -> StringRef { return L.CXXCtorName; },
+ [](const LambdaOfVar &L) -> StringRef { return L.VarName; },
+ },
+ N);
+}
+
+const NamedDecl *matchNamedDeclByFindEntityByName(const FindEntityByName &N,
+ const NamedDecl *D) {
+ return std::visit(
+ Overloaded{
+ [&D](StringRef S) -> const NamedDecl * {
+ if (D->getNameAsString() == S)
+ return D;
+ return nullptr;
+ },
+ [&D](const CXXCtorOfNumParms &L) -> const NamedDecl * {
+ if (auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
+ if (CD->getNameAsString() == L.CXXCtorName &&
+ CD->getNumParams() == L.NumParms)
+ return D;
+ }
+ return nullptr;
+ },
+ [&D](const LambdaOfVar &L) -> const NamedDecl * {
+ if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->getInit()) {
+ const Expr *Init = VD->getInit()->IgnoreUnlessSpelledInSource();
+ if (isa<LambdaExpr>(Init) && VD->getNameAsString() == L.VarName)
+ return cast<LambdaExpr>(Init)->getCallOperator();
+ }
+ return nullptr;
+ },
+ },
+ N);
+}
+
+template <typename SomeDecl = NamedDecl,
+ typename = std::enable_if_t<std::is_base_of_v<NamedDecl, SomeDecl>>>
+const SomeDecl *findEntityByName(FindEntityByName Name, ASTContext &Ctx) {
+ class NamedDeclFinder : public DynamicRecursiveASTVisitor {
+ public:
+ FindEntityByName SearchingName;
+ const SomeDecl *FoundDecl = nullptr;
+
+ NamedDeclFinder(FindEntityByName SearchingName)
+ : SearchingName(SearchingName) {
+ ShouldVisitTemplateInstantiations = true;
+ }
+
+ bool VisitDecl(Decl *D) override {
+ if (D->isTemplated())
+ return true;
+ if (auto *ND = dyn_cast<NamedDecl>(D)) {
+ FoundDecl = llvm::dyn_cast_or_null<SomeDecl>(
+ matchNamedDeclByFindEntityByName(SearchingName, ND));
+ if (FoundDecl)
+ return false;
+ }
+ return true;
+ }
+ };
+
+ NamedDeclFinder Finder(Name);
+
+ Finder.TraverseDecl(Ctx.getTranslationUnitDecl());
+ return dyn_cast_or_null<SomeDecl>(Finder.FoundDecl);
+}
+
+const FunctionDecl *findFnByName(FindEntityByName Name, ASTContext &Ctx) {
+ return findEntityByName<FunctionDecl>(Name, Ctx);
+}
+
+// Same as `std::pair<StringName, unsigned>` for a pair of entity declaration
+// name and a pointer level with an extra optional flag for whether the entity
+// represents a function return value. This structure is used to explicitly
+// spell out components of an EPL such as "{"p", 1}" or "{"foo_fn", 2, true}".
+struct EPLPair {
+ EPLPair(FindEntityByName Name, unsigned Lv, bool isFunRet = false)
+ : Name(Name), Lv(Lv), isFunRet(isFunRet) {}
+
+ FindEntityByName Name;
+ unsigned Lv;
+ bool isFunRet;
+};
+
+class PointerFlowTest : public TestFixture {
+protected:
+ SSAFOptions Opts;
+ TUSummary TUSum;
+ TUSummaryBuilder Builder;
+ std::unique_ptr<TUSummaryExtractor> Extractor;
+ std::unique_ptr<ASTUnit> AST;
+
+ PointerFlowTest()
+ : TUSum(llvm::Triple("arm64-apple-macosx"),
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")),
+ Builder(TUSum, Opts), Extractor(nullptr) {}
+
+ template <typename ContributorDecl = NamedDecl,
+ typename =
+ std::enable_if_t<std::is_base_of_v<NamedDecl, ContributorDecl>>>
+ bool setUpTest(StringRef Code) {
+ AST = tooling::buildASTFromCodeWithArgs(
+ Code, {"-Wno-unused-value", "-Wno-int-to-pointer-cast"});
+
+ 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 =
+ findEntityByName<ContributorDecl>(Name, AST->getASTContext());
+
+ if (!ContributorDefn) {
+ ADD_FAILURE() << "failed to find Decl of \"" << toStringRef(Name) << "\"";
+ return nullptr;
+ }
+
+ std::optional<EntityId> ContributorEntityId =
+ Extractor->addEntity(ContributorDefn);
+
+ if (!ContributorEntityId) {
+ ADD_FAILURE() << "failed to get EntityName for contributor \""
+ << toStringRef(Name) << "\"";
+ return nullptr;
+ }
+
+ auto &TUSumData = getData(TUSum);
+ auto EntitiesSumIter =
+ TUSumData.find(PointerFlowEntitySummary::summaryName());
+
+ // If none entity summary was collected, it may not be an entry in
+ // `TUSumData`:
+ if (EntitiesSumIter == TUSumData.end())
+ return nullptr;
+
+ auto EntitySumIter = EntitiesSumIter->second.find(*ContributorEntityId);
+
+ // If entity summary is empty, it may not exist:
+ if (EntitySumIter == EntitiesSumIter->second.end())
+ return nullptr;
+ return static_cast<const PointerFlowEntitySummary *>(
+ EntitySumIter->second.get());
+ }
+
+public:
+ std::optional<EntityId> getEntityId(FindEntityByName Name) {
+ if (const auto *D = findEntityByName(Name, AST->getASTContext())) {
+ return Extractor->addEntity(D);
+ }
+ return std::nullopt;
+ }
+
+ std::optional<EntityId> getEntityIdForReturn(FindEntityByName FunName) {
+ if (const auto *D = findFnByName(FunName, AST->getASTContext())) {
+ return Extractor->addEntityForReturn(D);
+ }
+ return std::nullopt;
+ }
+
+ EdgeSet makeEdges(unsigned Line, ArrayRef<std::pair<EPLPair, EPLPair>> Edges);
+};
+
+// 'ToEPL(Test, Line)' is a lambda that converts a 'EPLPair' to a
+// 'EntityPointerLevel':
+static constexpr auto ToEPL =
+ [](PointerFlowTest *Test,
+ unsigned Line) -> std::function<EntityPointerLevel(const EPLPair &)> {
+ return [Test, Line](const EPLPair &Pair) -> EntityPointerLevel {
+ std::optional<EntityId> Entity = Pair.isFunRet
+ ? Test->getEntityIdForReturn(Pair.Name)
+ : Test->getEntityId(Pair.Name);
+ if (!Entity) {
+ ADD_FAILURE_AT(__FILE__, Line)
+ << "Entity not found: " << toStringRef(Pair.Name);
+ }
+ return buildEntityPointerLevel(*Entity, Pair.Lv);
+ };
+};
+
+EdgeSet
+PointerFlowTest::makeEdges(unsigned Line,
+ ArrayRef<std::pair<EPLPair, EPLPair>> Edges) {
+ EdgeSet Result;
+ for (auto Edge : Edges)
+ Result[ToEPL(this, Line)(Edge.first)].insert(
+ ToEPL(this, Line)(Edge.second));
+ return Result;
+}
+
+TEST_F(PointerFlowTest, IsExtractorRegisteredTest) {
+ EXPECT_TRUE(isTUSummaryExtractorRegistered("PointerFlow"));
+}
+
+//////////////////////////////////////////////////////////////
+// Simple Assign Tests //
+//////////////////////////////////////////////////////////////
+TEST_F(PointerFlowTest, SimpleAssign) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p, int *q) {
+ q = p;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, AssignWithSubscriptLHS) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int **q, int *p, int x) {
+ q[x] = p;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 2U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, AssignWithPtrArithRHS) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p, int *q) {
+ q = p + 5;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, AssignInSubscript) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p, int *q) {
+ (q = p)[5];
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, MultipleAssign) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p, int *q, int *r) {
+ q = p;
+ r = q;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"q", 1U}, {"p", 1U}},
+ {{"r", 1U}, {"q", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, ChainedAssign) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p, int *q, int *r) {
+ r = q = p;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"q", 1U}, {"p", 1U}},
+ {{"r", 1U}, {"q", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, CastToRValue) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p, int *q) {
+ q = static_cast<int *&&>(p);
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, AssignToMember) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S { int *field; };
+ void foo(S s, int *p) {
+ s.field = p;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"field", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, AssignToMember2) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S { int *field; };
+ void foo(S *s, int *p) {
+ s->field = p;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"field", 1U}, {"p", 1U}}}));
+}
+
+//////////////////////////////////////////////////////////////
+// Call Expr Tests. //
+//////////////////////////////////////////////////////////////
+TEST_F(PointerFlowTest, CallArg) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void bar(int *param);
+ void foo(int *p) {
+ bar(p);
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"param", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, CallMultiArgs) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void bar(int *param1, int y, int *param2);
+ void foo(int *p, int x, int *q) {
+ bar(p, x, q);
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"param1", 1U}, {"p", 1U}},
+ {{"param2", 1U}, {"q", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, CallAsCallArg) {
+ ASSERT_EQ(setUpTest(R"cpp(
+
+ int *bar(int * w);
+ void foo(int * p) {
+ foo(bar(p));
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"w", 1U}, {"p", 1U}},
+ {{"p", 1U}, {"bar", 1U, true}}}));
+}
+
+TEST_F(PointerFlowTest, CXXOperatorCallMultiArgs) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S {
+ int* operator()(int *a, int *b);
+ };
+ void foo(S obj, int *p, int *q) {
+ foo(obj, obj(p, q), obj(p, q));
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"q", 1U}},
+ {{"p", 1U}, {"operator()", 1U, true}},
+ {{"q", 1U}, {"operator()", 1U, true}},
+ }));
+}
+
+TEST_F(PointerFlowTest, CXXMemberCall) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S {
+ int* method(int *a, int *b);
+ };
+ void foo(S obj, int *p, int *q) {
+ foo(obj, obj.method(p, q), obj.method(p, q));
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"q", 1U}},
+ {{"p", 1U}, {"method", 1U, true}},
+ {{"q", 1U}, {"method", 1U, true}}}));
+}
+
+TEST_F(PointerFlowTest, VirtualMethodCall) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct Base {
+ virtual void method(int *a);
+ };
+ void foo(Base &obj, int *p) {
+ obj.method(p);
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"a", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, StaticMethodCall) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S {
+ static void method(int *a, int *b);
+ };
+ void foo(int *p, int *q) {
+ S::method(p, q);
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"q", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, DefaultArg) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ int *g;
+ void bar(int *a, int *b = g);
+ void foo(int *p) {
+ bar(p);
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__,
+ {{{"a", 1U}, {"p", 1U}}, {{"b", 1U}, {"g", 1U}}}));
+}
+
+// Counter-example for the concern that matchArgsWithParams could go OOB
+// when fewer explicit args are provided than params (due to default args).
+// In Clang's AST, CallExpr::getNumArgs() always includes CXXDefaultArgExpr
+// nodes for defaulted parameters, so getNumArgs() >= getNumParams() holds.
+TEST_F(PointerFlowTest, AllArgsDefaulted) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ int *g1, *g2;
+ void bar(int *a = g1, int *b = g2);
+ void foo() {
+ bar();
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"g1", 1U}},
+ {{"b", 1U}, {"g2", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, DefaultArg2) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ int *g;
+ void bar(int *a, int *b = g);
+ void foo(int *p) {
+ bar(p, p);
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"p", 1U}},
+ }));
+}
+
+//////////////////////////////////////////////////////////////
+// CXX Ctor Tests. //
+//////////////////////////////////////////////////////////////
+TEST_F(PointerFlowTest, CXXCtorCallMultiArgs) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S {
+ S(int *a, int *b) {}
+ };
+ void foo(int *p, int *q) {
+ S s{p, q};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"q", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, CXXCtorCallMultiArgs2) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S {
+ S(int *a, int x, int *b) {}
+ };
+ void foo(int *p, int x, int *q) {
+ S s{p, x, q};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"q", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, CXXCtorCallAsCallArg) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct Wrapper {
+ Wrapper(int *q) {}
+ };
+ void bar(Wrapper w);
+ void foo(int *p) {
+ bar(Wrapper{p});
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, DelegatingCXXCtorCall) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S {
+ S(int *a, int *b) {}
+ S(int *p) : S(p, p) {}
+ };
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary<CXXConstructorDecl>(CXXCtorOfNumParms{"S", 1});
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"p", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, CXXCtorBaseInit) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct Base {
+ Base(int *a) {}
+ };
+ struct Derived : Base {
+ Derived(int *p) : Base(p) {}
+ };
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary<CXXConstructorDecl>("Derived");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"a", 1U}, {"p", 1U}}}));
+}
+
+//////////////////////////////////////////////////////////////
+// Initializers Tests. //
+//////////////////////////////////////////////////////////////
+TEST_F(PointerFlowTest, LocalVarDeclInit) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p) {
+ int *q = p;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, LocalVarDeclInit2) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int (*arr)[10]) {
+ int (*p)[10] = arr;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"p", 1U}, {"arr", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, FieldInit) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p) {
+ struct Bar {
+ int *field = p;
+ };
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("Bar");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"field", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, CXXCtorMemberInit) {
+ StringRef Code = R"cpp(
+ void foo(int *p) {
+ struct Bar {
+ int *member;
+ Bar(int *q) : member(q) {}
+ };
+ Bar B{p};
+ }
+ )cpp";
+
+ ASSERT_EQ(setUpTest(Code), true);
+ auto *Sum = getEntitySummary<CXXConstructorDecl>("Bar");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"member", 1U}, {"q", 1U}}}));
+
+ Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, GlobalVarInit) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ int *q;
+ int *g = q;
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary<VarDecl>("g");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"g", 1U}, {"q", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, StaticLocalInit) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p) {
+ static int *s = p;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"s", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, StaticMemberInit) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ int *g;
+ struct S { static int *member; };
+ int *S::member = g;
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary<VarDecl>("member");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"member", 1U}, {"g", 1U}}}));
+}
+
+//////////////////////////////////////////////////////////////
+// InitList Tests. //
+//////////////////////////////////////////////////////////////
+
+TEST_F(PointerFlowTest, ArrayInitList) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p, int *q) {
+ int *arr[] = {p, q};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"arr", 2U}, {"p", 1U}},
+ {{"arr", 2U}, {"q", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, StructInitList) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S { int *a; int *b; };
+ void foo(int *p, int *q) {
+ S s = {p, q};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"q", 1U}},
+ }));
+}
+
+// A union initialized with a brace-enclosed initializer:
+TEST_F(PointerFlowTest, UnionInitList) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ union U { int *x; int y; };
+ void foo(int *p) {
+ U u = {p};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"x", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, NestedInitList) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct Inner { int * a; int * b; };
+ struct S { Inner c; int * d; };
+ void foo(int *p, int *q, int *r) {
+ S s = {{p, q}, r};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"q", 1U}},
+ {{"d", 1U}, {"r", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, NestedInitList2) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ union Inner { int * a; int b; };
+ struct S { Inner c; int * d; };
+ void foo(int *p, int *q) {
+ S s = {{p}, q};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"d", 1U}, {"q", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, NestedInitList3) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct Inner { int * a; int * b; };
+ union S { Inner c; int * d; };
+ void foo(int *p, int *q) {
+ S s = {{p, q}};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"q", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, NestedArrayInitList) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p, int *q, int *r, int *s) {
+ int *arr[][2] = {{p, q}, {r, s}};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"arr", 3U}, {"p", 1U}},
+ {{"arr", 3U}, {"q", 1U}},
+ {{"arr", 3U}, {"r", 1U}},
+ {{"arr", 3U}, {"s", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, MixedNestedArrayStructInitList) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct T { int *arr[2]; };
+ void foo(int *p, int *q, int *r, int *s) {
+ T t[2] = {{p, q}, {r, s}};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"arr", 2U}, {"p", 1U}},
+ {{"arr", 2U}, {"q", 1U}},
+ {{"arr", 2U}, {"r", 1U}},
+ {{"arr", 2U}, {"s", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, ArrayOfStructInitList) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S { int *a; int *b; };
+ void foo(int *p, int *q, int *r, int *s) {
+ S arr[] = {{p, q}, {r, s}};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"a", 1U}, {"p", 1U}},
+ {{"b", 1U}, {"q", 1U}},
+ {{"a", 1U}, {"r", 1U}},
+ {{"b", 1U}, {"s", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, ScalarPointerBraceInit) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ int *q;
+ void foo() {
+ int *p{q};
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"p", 1U}, {"q", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, EmptyInitsScalarInt) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo() {
+ int x{};
+ int y = {};
+ int *p{};
+ int *q = {};
+ }
+ )cpp"));
+
+ // No pointer-flow edge for 0-initialized scalar.
+ ASSERT_FALSE(getEntitySummary("foo"));
+}
+
+TEST_F(PointerFlowTest, EmptyInitsUnion) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ union U { int x; int *p; };
+ void foo() {
+ U u{};
+ U uu = {};
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_EQ(Sum, nullptr);
+}
+
+TEST_F(PointerFlowTest, EmptyInitsStruct) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ struct S { int x; int *p; };
+ void foo() {
+ S s{};
+ S ss = {};
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_EQ(Sum, nullptr);
+}
+
+TEST_F(PointerFlowTest, EmptyInitsClass) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ class C { public: int x; int *p; };
+ void foo() {
+ C c{};
+ C cc = {};
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_EQ(Sum, nullptr);
+}
+
+//////////////////////////////////////////////////////////////
+// Return Tests. //
+//////////////////////////////////////////////////////////////
+
+TEST_F(PointerFlowTest, ReturnEdge) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ int *foo(int *p) {
+ return p;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"foo", 1U, true}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, MultipleReturnEdges) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ int *foo(int *p, int *q, bool cond) {
+ if (cond)
+ return p;
+ return q;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {
+ {{"foo", 1U, true}, {"p", 1U}},
+ {{"foo", 1U, true}, {"q", 1U}},
+ }));
+}
+
+TEST_F(PointerFlowTest, NoReturnEdgeForNonPointerReturnType) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ int foo(int *p, int x) {
+ return x;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ EXPECT_THAT(Sum, testing::AnyOf(testing::IsNull(),
+ testing::Pointee(makeEdges(__LINE__, {}))));
+}
+
+TEST_F(PointerFlowTest, ReturnEdgeNotFromNestedFunction) {
+ StringRef Code = R"cpp(
+ int *foo(int *p) {
+ struct Inner {
+ int *bar(int *q) { return q; }
+ };
+ return p;
+ }
+ )cpp";
+
+ ASSERT_EQ(setUpTest(Code), true);
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"foo", 1U, true}, {"p", 1U}}}));
+
+ Sum = getEntitySummary("bar");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"bar", 1U, true}, {"q", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, ReturnEdgeInClassMethod) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo() {
+ struct S {
+ int *method(int *p, int *q) { return p; }
+ };
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("method");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"method", 1U, true}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, NoEdgeFromIndirectCall) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void bar(int *param1);
+ void baz(int *param2);
+
+ void foo(int *p, void (*fp)(int *)) {
+ fp(p);
+ }
+
+ int main() {
+ int *q;
+ foo(q, bar);
+ foo(q, baz);
+ return 0;
+ }
+ )cpp"),
+ true);
+
+ /* FIXME or TBD: Currently indirect calls produce no edge: */
+ auto *Sum = getEntitySummary("foo");
+
+ EXPECT_THAT(Sum, testing::AnyOf(testing::IsNull(),
+ testing::Pointee(makeEdges(__LINE__, {}))));
+}
+
+//////////////////////////////////////////////////////////////
+// Lambda Tests. //
+//////////////////////////////////////////////////////////////
+
+TEST_F(PointerFlowTest, ReturnInLambda) {
+ StringRef Code = R"cpp(
+ int* foo(int *p) {
+ auto local = [](int *r) { return r; };
+ return local(p);
+ }
+ )cpp";
+
+ ASSERT_EQ(setUpTest(Code), true);
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"r", 1U}, {"p", 1U}},
+ {{"foo", 1U, true},
+ {LambdaOfVar{"local"}, 1U, true}}}));
+
+ Sum = getEntitySummary(LambdaOfVar{"local"});
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__,
+ {{{LambdaOfVar{"local"}, 1U, true}, {"r", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, NestedLambdaAssign) {
+ StringRef Code = R"cpp(
+ void foo() {
+ auto outer_lambda = [](int *r, int *s) {
+ s = r;
+ auto inner_lambda = [](int *x, int *y) { y = x; };
+ };
+ }
+ )cpp";
+
+ ASSERT_EQ(setUpTest(Code), true);
+ auto *Sum = getEntitySummary(LambdaOfVar{"outer_lambda"});
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"s", 1U}, {"r", 1U}}}));
+
+ Sum = getEntitySummary(LambdaOfVar{"inner_lambda"});
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"y", 1U}, {"x", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, ImplicitValueInit) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S { int *a; int *b; };
+ void foo(int *p) {
+ S s = {p}; // ImplicitValueInit inits 'b'
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"a", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, InitListExpr) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ void foo(int *p) {
+ int *q = {p};
+ int *r = {};
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, CXXDefaultInitExpr) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ int *g;
+ struct S {
+ int *field = g;
+ };
+ void foo(int *p) {
+ S s;
+ s.field = p;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary<RecordDecl>("S");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"field", 1U}, {"g", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, CXXConstructExprArrayInit) {
+ ASSERT_EQ(setUpTest(
+ R"cpp(
+ struct S {};
+ void foo(S *q) {
+ S arr[3]; // -VarDecl <...> arr 'S[3]' callinit
+ // `-CXXConstructExpr <...> 'S[3]' 'void () noexcept'
+ q = arr;
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"arr", 1U}}}));
+}
+
+//////////////////////////////////////////////////////////////
+// Template is ignored but instantiations are visited. //
+//////////////////////////////////////////////////////////////
+TEST_F(PointerFlowTest, FunctionTemplate) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ template <typename T>
+ T* f(T *p) {
+ int *q = p;
+ return q;
+ }
+ )cpp"));
+ ASSERT_FALSE(findEntityByName("f", AST->getASTContext()));
+}
+
+TEST_F(PointerFlowTest, MethodInClassTemplate) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ template <typename T>
+ struct Wrapper {
+ T *ptr;
+ void set(T *p) { ptr = p; }
+ };
+ )cpp"));
+ ASSERT_FALSE(findEntityByName("set", AST->getASTContext()));
+}
+
+TEST_F(PointerFlowTest, FunctionTemplateInstantiation) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ template <typename T>
+ T* f(T *p) {
+ int *q = p;
+ return q;
+ }
+
+ void test(int *p) {
+ f(p);
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary<FunctionDecl>("f");
+
+ ASSERT_TRUE(Sum);
+ ASSERT_EQ(*Sum, makeEdges(__LINE__, {{{"q", 1U}, {"p", 1U}},
+ {{"f", 1U, 1}, {"q", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, MethodInClassTemplateInstantiation) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ template <typename T>
+ struct Wrapper {
+ T *ptr;
+ void set(T *p) { ptr = p; }
+ };
+
+ void test(int *p) {
+ Wrapper<int> W;
+
+ W.set(p);
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary<FunctionDecl>("set");
+
+ ASSERT_TRUE(Sum);
+ ASSERT_EQ(*Sum, makeEdges(__LINE__, {{{"ptr", 1U}, {"p", 1U}}}));
+}
+
+//////////////////////////////////////////////////////////////
+// Robustness Tests (No Crash Tests) //
+//////////////////////////////////////////////////////////////
+
+#ifndef NDEBUG
+TEST_F(PointerFlowTest, StructuredBindingWithPointers) {
+ StringRef Code = R"cpp(
+ void foo() {
+ int *a[2];
+ auto [ptr1, ptr2] = a;
+ ptr1[5];
+ ptr2[3];
+ }
+ )cpp";
+
+ // BindingDecl may not be fully supported, but should not crash.
+ llvm::SaveAndRestore<bool> DebugFlag(llvm::DebugFlag, true);
+ llvm::setCurrentDebugType("ssaf-analyses");
+ testing::internal::CaptureStderr();
+
+ ASSERT_TRUE(setUpTest(Code));
+ // Verify the warning was logged
+ ASSERT_TRUE(StringRef(testing::internal::GetCapturedStderr())
+ .contains("failed to create EntityId for Decomposition"));
+}
+#endif
+
+TEST_F(PointerFlowTest, RHSResultsInNoEntityPointerLevel) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void f() {
+ int *p = new int[10];
+ const char *q = "hello";
+ }
+ struct S {
+ int *p;
+ void g() { p = (int *)this; }
+ };
+ )cpp"));
+ ASSERT_FALSE(getEntitySummary<FunctionDecl>("f"));
+ ASSERT_FALSE(getEntitySummary<CXXMethodDecl>("g"));
+}
+
+//////////////////////////////////////////////////////////////
+// Reference-to-pointer Tests //
+//////////////////////////////////////////////////////////////
+
+TEST_F(PointerFlowTest, ArgToRefParam) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void callee(int *&rp);
+ void caller(int *p) {
+ callee(p);
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary("caller");
+
+ ASSERT_TRUE(Sum);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"rp", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, ArgToRefParamLevel2) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void callee(int **&rp);
+ void caller(int **pp) {
+ callee(pp);
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary("caller");
+
+ ASSERT_TRUE(Sum);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"rp", 1U}, {"pp", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, InitRefPtr) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p) {
+ int *&rp = p;
+ int * const & crp = p;
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_TRUE(Sum);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"rp", 1U}, {"p", 1U}},
+ {{"crp", 1U}, {"p", 1U}}}));
+}
+
+TEST_F(PointerFlowTest, ReturnRefPtr) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ int *& f();
+ int *& foo() {
+ return f();
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_TRUE(Sum);
+ EXPECT_EQ(*Sum, makeEdges(__LINE__, {{{"foo", 1U, true}, {"f", 1U, true}}}));
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowWPATest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowWPATest.cpp
new file mode 100644
index 0000000000000..8c43ead9750ca
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowWPATest.cpp
@@ -0,0 +1,141 @@
+//===- PointerFlowWPATest.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestFixture.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h"
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace clang;
+using namespace ssaf;
+using testing::IsEmpty;
+using testing::UnorderedElementsAre;
+
+PointerFlowEntitySummary ssaf::buildPointerFlowEntitySummary(EdgeSet Edges);
+
+namespace {
+
+class PointerFlowWPATest : public TestFixture {
+protected:
+ static constexpr EntityLinkage ExternalLinkage =
+ EntityLinkage(EntityLinkageType::External);
+
+ std::unique_ptr<LUSummary> makeLUSummary() {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ return std::make_unique<LUSummary>(llvm::Triple("arm64-apple-macosx"),
+ std::move(NS));
+ }
+
+ EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ EntityName Name(USR.str(), "", NS);
+ EntityId Id = getIdTable(LU).getId(Name);
+ getLinkageTable(LU).insert({Id, ExternalLinkage});
+ return Id;
+ }
+
+ void insertSummary(LUSummary &LU, EntityId Id, EdgeSet Edges) {
+ getData(LU)[PointerFlowEntitySummary::summaryName()][Id] =
+ std::make_unique<PointerFlowEntitySummary>(
+ buildPointerFlowEntitySummary(std::move(Edges)));
+ }
+
+ const PointerFlowAnalysisResult &
+ runAnalysisForResult(std::unique_ptr<LUSummary> LU) {
+ AnalysisDriver Driver(std::move(LU));
+ auto WPAOrErr = Driver.run<PointerFlowAnalysisResult>();
+ EXPECT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
+ WPA = std::move(*WPAOrErr);
+ auto ROrErr = WPA.get<PointerFlowAnalysisResult>();
+ EXPECT_THAT_EXPECTED(ROrErr, llvm::Succeeded());
+ return *ROrErr;
+ }
+
+private:
+ WPASuite WPA = makeWPASuite();
+};
+
+TEST_F(PointerFlowWPATest, SingleEntitySummary) {
+ auto LU = makeLUSummary();
+ EntityId Foo = addEntity(*LU, "c:@F at foo");
+ EntityId Src = addEntity(*LU, "c:@F at foo@src");
+ EntityId Dest = addEntity(*LU, "c:@F at foo@dest");
+ auto Src1 = buildEntityPointerLevel(Src, 1);
+ auto Dest1 = buildEntityPointerLevel(Dest, 1);
+ auto Dest2 = buildEntityPointerLevel(Dest, 2);
+ EdgeSet Edges;
+
+ Edges[Src1] = {Dest1, Dest2};
+ insertSummary(*LU, Foo, std::move(Edges));
+
+ const auto &Result = runAnalysisForResult(std::move(LU));
+
+ ASSERT_EQ(Result.Edges.size(), 1u);
+ EXPECT_EQ(Result.Edges.at(Foo).size(), 1u);
+ EXPECT_THAT(Result.Edges.at(Foo).at(Src1),
+ UnorderedElementsAre(Dest1, Dest2));
+}
+
+TEST_F(PointerFlowWPATest, MultiEntitySummaries) {
+ auto LU = makeLUSummary();
+ EntityId Foo = addEntity(*LU, "c:@F at foo");
+ EntityId Bar = addEntity(*LU, "c:@F at bar");
+ EntityId FooSrc = addEntity(*LU, "c:@F at foo@src");
+ EntityId FooDest = addEntity(*LU, "c:@F at foo@dest");
+ EntityId BarSrc = addEntity(*LU, "c:@F at bar@src");
+ EntityId BarDest = addEntity(*LU, "c:@F at bar@dest");
+ auto FooSrc1 = buildEntityPointerLevel(FooSrc, 1);
+ auto BarSrc1 = buildEntityPointerLevel(BarSrc, 1);
+ EntityPointerLevelSet FooDests, BarDests;
+
+ for (unsigned I = 0; I < 5; ++I) {
+ FooDests.insert(buildEntityPointerLevel(FooDest, I));
+ BarDests.insert(buildEntityPointerLevel(BarDest, I));
+ }
+
+ EdgeSet FooEdges;
+ FooEdges[FooSrc1] = FooDests;
+ insertSummary(*LU, Foo, std::move(FooEdges));
+
+ EdgeSet BarEdges;
+ BarEdges[BarSrc1] = BarDests;
+ insertSummary(*LU, Bar, std::move(BarEdges));
+
+ const auto &R = runAnalysisForResult(std::move(LU));
+
+ EXPECT_EQ(R.Edges.size(), 2u);
+ EXPECT_EQ(R.Edges.at(Foo).at(FooSrc1), FooDests);
+ EXPECT_EQ(R.Edges.at(Bar).at(BarSrc1), BarDests);
+}
+
+TEST_F(PointerFlowWPATest, EmptySummary) {
+ auto LU = makeLUSummary();
+ EntityId Foo = addEntity(*LU, "c:@F at foo");
+
+ insertSummary(*LU, Foo, {});
+
+ const auto &R = runAnalysisForResult(std::move(LU));
+
+ ASSERT_EQ(R.Edges.count(Foo), 1u);
+ EXPECT_THAT(R.Edges.at(Foo), IsEmpty());
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
new file mode 100644
index 0000000000000..c2f4cb97c0fae
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
@@ -0,0 +1,783 @@
+//===- UnsafeBufferUsageTest.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "FindDecl.h"
+#include "TestFixture.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/SSAFOptions.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/SaveAndRestore.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <initializer_list>
+#include <memory>
+#include <optional>
+
+using namespace clang;
+using namespace ssaf;
+using testing::UnorderedElementsAre;
+
+namespace {
+class UnsafeBufferUsageTest : public TestFixture {
+protected:
+ SSAFOptions Opts;
+ TUSummary TUSum;
+ TUSummaryBuilder Builder;
+ std::unique_ptr<TUSummaryExtractor> Extractor;
+ std::unique_ptr<ASTUnit> AST;
+
+ UnsafeBufferUsageTest()
+ : TUSum(llvm::Triple("arm64-apple-macosx"),
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")),
+ Builder(TUSum, Opts) {}
+
+ bool setUpTest(StringRef Code) {
+ AST = tooling::buildASTFromCodeWithArgs(
+ Code, {"-Wno-unused-value", "-Wno-int-to-pointer-cast"});
+
+ Extractor =
+ makeTUSummaryExtractor(UnsafeBufferUsageEntitySummary::Name, Builder);
+
+ if (!Extractor) {
+ ADD_FAILURE() << "failed to find UnsafeBufferUsageTUSummaryExtractor";
+ return false;
+ }
+ Extractor->HandleTranslationUnit(AST->getASTContext());
+ return true;
+ }
+
+ template <typename ContributorDecl = NamedDecl>
+ const UnsafeBufferUsageEntitySummary *
+ getEntitySummary(StringRef ContributorEntityName) {
+ auto *ContributorDefn = findDeclByName<ContributorDecl>(
+ ContributorEntityName, AST->getASTContext());
+
+ if (!ContributorDefn) {
+ ADD_FAILURE() << "failed to find Decl of \"" << ContributorEntityName
+ << "\"";
+ return nullptr;
+ }
+
+ std::optional<EntityId> ContributorEntityId =
+ Extractor->addEntity(ContributorDefn);
+ if (!ContributorEntityId) {
+ ADD_FAILURE() << "failed to get EntityName for contributor \""
+ << ContributorEntityName << "\"";
+ return nullptr;
+ }
+
+ auto &TUSumData = getData(TUSum);
+ auto EntitiesSumIter =
+ TUSumData.find(UnsafeBufferUsageEntitySummary::summaryName());
+
+ // If none entity summary was collected, it may not be an entry in
+ // `TUSumData`:
+ if (EntitiesSumIter == TUSumData.end())
+ return nullptr;
+
+ auto EntitySumIter = EntitiesSumIter->second.find(*ContributorEntityId);
+
+ // If entity summary is empty, it may not exist:
+ if (EntitySumIter == EntitiesSumIter->second.end())
+ return nullptr;
+ return static_cast<const UnsafeBufferUsageEntitySummary *>(
+ EntitySumIter->second.get());
+ }
+
+ std::optional<EntityId> getEntityId(StringRef Name) {
+ if (const auto *D = findDeclByName(Name, AST->getASTContext()))
+ return Extractor->addEntity(D);
+ return std::nullopt;
+ }
+
+ std::optional<EntityId> getEntityIdForReturn(StringRef FunName) {
+ if (const auto *D = findFnByName(FunName, AST->getASTContext()))
+ return Extractor->addEntityForReturn(D);
+ return std::nullopt;
+ }
+
+ // Same as `std::pair<StringName, unsigned>` for a pair of entity declaration
+ // name and a pointer level with an extra optional flag for whether the entity
+ // represents a function return value:
+ struct EPLPair {
+ EPLPair(StringRef Name, unsigned Lv, bool isFunRet = false)
+ : Name(Name), Lv(Lv), isFunRet(isFunRet) {}
+
+ StringRef Name;
+ unsigned Lv;
+ bool isFunRet;
+ };
+
+ EntityPointerLevelSet makeSet(unsigned Line, ArrayRef<EPLPair> Pairs) {
+ auto EPLs = llvm::map_range(
+ Pairs, [this, Line](const EPLPair &Pair) -> EntityPointerLevel {
+ std::optional<EntityId> Entity = Pair.isFunRet
+ ? getEntityIdForReturn(Pair.Name)
+ : getEntityId(Pair.Name);
+ if (!Entity)
+ ADD_FAILURE_AT(__FILE__, Line) << "Entity not found: " << Pair.Name;
+ return buildEntityPointerLevel(*Entity, Pair.Lv);
+ });
+ return EntityPointerLevelSet{EPLs.begin(), EPLs.end()};
+ }
+};
+
+//////////////////////////////////////////////////////////////
+// Data Structure Tests //
+//////////////////////////////////////////////////////////////
+
+static llvm::iterator_range<EntityPointerLevelSet::iterator>
+getSubsetOf(const EntityPointerLevelSet &Set, EntityId Entity) {
+ return llvm::make_range(Set.equal_range(Entity));
+}
+
+TEST_F(UnsafeBufferUsageTest, EntityPointerLevelComparison) {
+ EntityIdTable Table;
+ EntityId E1 = Table.getId({"c:@F at foo", "", {}});
+ EntityId E2 = Table.getId({"c:@F at bar", "", {}});
+
+ auto P1 = buildEntityPointerLevel(E1, 2);
+ auto P2 = buildEntityPointerLevel(E1, 2);
+ auto P3 = buildEntityPointerLevel(E1, 1);
+ auto P4 = buildEntityPointerLevel(E2, 2);
+
+ EXPECT_EQ(P1, P2);
+ EXPECT_NE(P1, P3);
+ EXPECT_NE(P1, P4);
+ EXPECT_NE(P3, P4);
+ EXPECT_TRUE(P3 < P2);
+ EXPECT_TRUE(P3 < P4);
+ EXPECT_FALSE(P1 < P2);
+ EXPECT_FALSE(P2 < P1);
+}
+
+TEST_F(UnsafeBufferUsageTest, UnsafeBufferUsageEntityPointerLevelSetTest) {
+ EntityIdTable Table;
+ EntityId E1 = Table.getId({"c:@F at foo", "", {}});
+ EntityId E2 = Table.getId({"c:@F at bar", "", {}});
+ EntityId E3 = Table.getId({"c:@F at baz", "", {}});
+
+ auto P1 = buildEntityPointerLevel(E1, 1);
+ auto P2 = buildEntityPointerLevel(E1, 2);
+ auto P3 = buildEntityPointerLevel(E2, 1);
+ auto P4 = buildEntityPointerLevel(E2, 2);
+ auto P5 = buildEntityPointerLevel(E3, 1);
+
+ EntityPointerLevelSet Set{P1, P2, P3, P4, P5};
+
+ EXPECT_THAT(Set, UnorderedElementsAre(P1, P2, P3, P4, P5));
+ EXPECT_THAT(getSubsetOf(Set, E1), UnorderedElementsAre(P1, P2));
+ EXPECT_THAT(getSubsetOf(Set, E2), UnorderedElementsAre(P3, P4));
+ EXPECT_THAT(getSubsetOf(Set, E3), UnorderedElementsAre(P5));
+}
+
+//////////////////////////////////////////////////////////////
+// Extractor Tests //
+//////////////////////////////////////////////////////////////
+
+TEST_F(UnsafeBufferUsageTest, SimpleFunctionWithUnsafePointer) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p) {
+ p[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, PointerArithmetic) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p, int *q) {
+ *(p + 5);
+ *(q - 3);
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, PointerIncrementDecrement) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p, int *q, int *r, int *s) {
+ (++p)[5];
+ (q++)[5];
+ (--r)[5];
+ (s--)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum,
+ makeSet(__LINE__, {{"p", 1U}, {"q", 1U}, {"r", 1U}, {"s", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, PointerAssignment) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p, int *q) {
+ (p = q + 5)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, CompoundAssignment) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p, int *q) {
+ (p += 5)[5];
+ (q -= 3)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, MultiLevelPointer) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int **p, int **q, int **r) {
+ (*p)[5];
+ *(*q);
+ *(q[5]);
+ r[5][5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum,
+ makeSet(__LINE__, {{"p", 2U}, {"q", 1U}, {"r", 1U}, {"r", 2U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, ConditionalOperator) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int **p, int **q, int cond) {
+ (cond ? *p : *q)[5];
+ cond ? p[5] : q[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum,
+ makeSet(__LINE__, {{"p", 1U}, {"q", 1U}, {"p", 2U}, {"q", 2U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, CastExpression) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(void *p, int q) {
+ ((int*)p)[5];
+ ((int*)q)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, CommaOperator) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p, int x) {
+ (x++, p)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, CommaOperator2) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int **p, int **q, int x) {
+ (p[x] = 0, q[x] = 0)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}, {"q", 2U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, ParenthesizedExpression) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p) {
+ (((p)))[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, ArrayParameter) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int arr[], int arr2[][10]) {
+ int n = 5;
+ arr[100];
+ arr2[5][n];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"arr", 1U}, {"arr2", 1U}, {"arr2", 2U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, FunctionCall) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ int ** (*fp)();
+ int ** foo() {
+ fp = &foo;
+ foo()[5];
+ (*fp())[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ // No (foo, 2) because indirect calls are ignored.
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"foo", 1U, true}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, StructMemberAccess) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ struct S {
+ int *ptr;
+ int (*ptr_to_arr)[10];
+ };
+ void foo(struct S obj) {
+ int n = 5;
+ obj.ptr[5];
+ (*obj.ptr_to_arr)[n];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"ptr", 1U}, {"ptr_to_arr", 2U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, StringLiteralSubscript) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo() {
+ "hello"[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ // String literals should not generate pointer kind variables
+ EXPECT_EQ(Sum, nullptr);
+}
+
+TEST_F(UnsafeBufferUsageTest, OpaqueValueExpr) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p, int *q) {
+ (p ?: q)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}, {"q", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, AddressOfOperator) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int x) {
+ (&x)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+ // Address-of should not generate pointer kind variables for 'x':
+ EXPECT_EQ(Sum, nullptr);
+}
+
+TEST_F(UnsafeBufferUsageTest, AddressOfThenDereference) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p, int *q) {
+ (*(&p))[5];
+ (&(*q))[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1}, {"q", 1}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, PointerToArrayOfPointers) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo() {
+ int * arr[10];
+ int * (*p)[10] = &arr;
+
+ (*p)[5][5]; // '(*p)[5]' is unsafe
+ // '(*p)' is fine because 5 < 10
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 3}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, UnsafePointerInGlobalVariableInitializer) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ int *gp;
+ int x = gp[5];
+ )cpp"));
+ const auto *Sum = getEntitySummary("x");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, UnsafePointerInFieldInitializer) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ int *gp;
+ struct Foo {
+ int field = gp[5];
+ };
+ )cpp"));
+ const auto *Sum = getEntitySummary("Foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, UnsafePointerInFieldInitializer2) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ int *gp;
+ union Foo {
+ int field = gp[5];
+ int x;
+ };
+ )cpp"));
+ const auto *Sum = getEntitySummary("Foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, InitializerList) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ int *gp;
+ struct Foo {
+ int field;
+ int x;
+ };
+ Foo FooObj{gp[5], 0};
+ )cpp"));
+ const auto *Sum = getEntitySummary("FooObj");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, UnsafePointerInCXXCtorInitializer) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ struct Foo {
+ int member;
+ Foo(int *p) : member(p[5]) {}
+ };
+ )cpp"));
+ const auto *Sum = getEntitySummary<CXXConstructorDecl>("Foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, UnsafePointerInDefaultArg) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ int * gp;
+ void foo(int x = gp[5]);
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"gp", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, NestedDefinitions) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ int * a = [](){
+ struct Foo {
+ void bar(int * ptr) { ptr[3] = 0; }
+ };
+ return nullptr;
+ }();
+ )cpp"));
+ const auto *Sum = getEntitySummary("bar");
+
+ EXPECT_NE(Sum, nullptr);
+ // The closest contributor owns the fact:
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"ptr", 1U}}));
+
+ Sum = getEntitySummary("Foo");
+
+ EXPECT_EQ(Sum, nullptr);
+
+ Sum = getEntitySummary("a");
+
+ EXPECT_EQ(Sum, nullptr);
+}
+
+TEST_F(UnsafeBufferUsageTest, NestedDefinitions2) {
+ bool SetupSuccess = setUpTest(R"cpp(
+ int main(void) {
+ struct Foo {
+ void bar(int * ptr) { ptr[3] = 0; }
+ };
+ }
+ )cpp");
+
+ ASSERT_TRUE(SetupSuccess);
+
+ const auto *Sum = getEntitySummary("bar");
+
+ EXPECT_NE(Sum, nullptr);
+ // The closest contributor owns the fact:
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"ptr", 1U}}));
+
+ Sum = getEntitySummary("Foo");
+
+ EXPECT_EQ(Sum, nullptr);
+
+ Sum = getEntitySummary("main");
+
+ EXPECT_EQ(Sum, nullptr);
+}
+
+TEST_F(UnsafeBufferUsageTest, UnaryPlusSubscript) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int *p) {
+ (+p)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, PredefinedExprSubscript) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo() {
+ __func__[100];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_EQ(Sum, nullptr);
+}
+
+TEST_F(UnsafeBufferUsageTest, IntegerLiteralCastSubscript) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo() {
+ ((int *)0)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_EQ(Sum, nullptr);
+}
+
+TEST_F(UnsafeBufferUsageTest, CXXNewArraySubscript) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo() {
+ (new int[10])[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_EQ(Sum, nullptr);
+}
+
+TEST_F(UnsafeBufferUsageTest, CXXNullPtrSubscript) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo() {
+ ((int*)nullptr)[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_EQ(Sum, nullptr);
+}
+
+TEST_F(UnsafeBufferUsageTest, CXXThisSubscript) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ struct S {
+ void foo() {
+ this[5];
+ }
+ };
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_EQ(Sum, nullptr);
+}
+
+TEST_F(UnsafeBufferUsageTest, ExprWithCleanupsSubscript) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ struct Guard { ~Guard(); };
+ int *getPtr(Guard);
+ void foo() {
+ getPtr(Guard{})[5];
+ }
+ )cpp"));
+ const auto *Sum = getEntitySummary("foo");
+
+ EXPECT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"getPtr", 1U, true}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, MaterializeTemporaryExpr) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ struct S { int *get(); };
+ void foo(int *p) {
+ S{}.get()[5];
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"get", 1U, true}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, CXXScalarValueInitExpr) {
+ ASSERT_EQ(setUpTest(R"cpp(
+ using IntPtr = int*;
+
+ void foo(int *q) {
+ int p = IntPtr()[5]; // no EPL created for CXXScalarValueInitExpr
+ q[5];
+ }
+ )cpp"),
+ true);
+
+ auto *Sum = getEntitySummary("foo");
+
+ ASSERT_NE(Sum, nullptr);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"q", 1U}}));
+}
+
+//////////////////////////////////////////////////////////////
+// Template is ignored but instantiations are visited. //
+//////////////////////////////////////////////////////////////
+
+TEST_F(UnsafeBufferUsageTest, FunctionTemplate) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ template <typename T>
+ T* f(T *p) {
+ return &p[5];
+ }
+ )cpp"));
+ ASSERT_FALSE(findDeclByName("f", AST->getASTContext()));
+}
+
+TEST_F(UnsafeBufferUsageTest, MethodInClassTemplate) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ template <typename T>
+ struct Wrapper {
+ T *ptr;
+ void set(T *p) { ptr = p[5]; }
+ };
+ )cpp"));
+ ASSERT_FALSE(findDeclByName("set", AST->getASTContext()));
+}
+
+TEST_F(UnsafeBufferUsageTest, FunctionTemplateInstantiation) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ template<typename T>
+ void unsafe(T p) {
+ p[1] = p[2] + p[3];
+ }
+
+ void f(int *p) {
+ unsafe(p);
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary("unsafe");
+
+ ASSERT_TRUE(Sum);
+ ASSERT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
+}
+
+TEST_F(UnsafeBufferUsageTest, MethodInClassTemplateInstantiation) {
+ ASSERT_TRUE(setUpTest(R"cpp(
+ template<typename T>
+ struct UnsafeClass {
+ T p;
+ void unsafe_method() {
+ p[1] = p[2] + p[3];
+ }
+ };
+
+ void f(int *p) {
+ UnsafeClass<int *> UC;
+
+ UC.unsafe_method();
+ }
+ )cpp"));
+
+ auto *Sum = getEntitySummary("unsafe_method");
+
+ ASSERT_TRUE(Sum);
+ EXPECT_EQ(*Sum, makeSet(__LINE__, {{"p", 1U}}));
+}
+// Robustness test: unsupported constructs will not cause crash
+#ifndef NDEBUG
+TEST_F(UnsafeBufferUsageTest, StmtExprArrayAccess) {
+ // GNU statement expressions are not supported, but should not crash and
+ // should log a warning.
+ llvm::SaveAndRestore<bool> DebugFlag(llvm::DebugFlag, true);
+
+ llvm::setCurrentDebugType("ssaf-analyses");
+ testing::internal::CaptureStderr();
+
+ ASSERT_TRUE(setUpTest(R"cpp(
+ void foo(int i) {
+ ({ int *p = 0; p; })[i];
+ }
+ )cpp"));
+
+ // The only unsafe pointer is unsupported, so no summary should be produced.
+ ASSERT_FALSE(getEntitySummary("foo"));
+ // Verify the warning was logged
+ EXPECT_TRUE(
+ StringRef(testing::internal::GetCapturedStderr())
+ .contains("attempt to translate StmtExpr to EntityPointerLevels"));
+}
+#endif
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp b/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp
new file mode 100644
index 0000000000000..448f838297e8f
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp
@@ -0,0 +1,132 @@
+//===- UnsafeBufferUsageWPATest.cpp ---------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestFixture.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace clang;
+using namespace ssaf;
+using testing::IsEmpty;
+using testing::UnorderedElementsAre;
+
+UnsafeBufferUsageEntitySummary
+ssaf::buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet UnsafeBuffers);
+
+namespace {
+
+class UnsafeBufferUsageWPATest : public TestFixture {
+protected:
+ static constexpr EntityLinkage ExternalLinkage =
+ EntityLinkage(EntityLinkageType::External);
+
+ std::unique_ptr<LUSummary> makeLUSummary() {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ return std::make_unique<LUSummary>(llvm::Triple("arm64-apple-macosx"),
+ std::move(NS));
+ }
+
+ EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ EntityName Name(USR.str(), "", NS);
+ EntityId Id = getIdTable(LU).getId(Name);
+ getLinkageTable(LU).insert({Id, ExternalLinkage});
+ return Id;
+ }
+
+ void insertSummary(LUSummary &LU, EntityId Id, EntityPointerLevelSet EPLs) {
+ getData(LU)[UnsafeBufferUsageEntitySummary::summaryName()][Id] =
+ std::make_unique<UnsafeBufferUsageEntitySummary>(
+ buildUnsafeBufferUsageEntitySummary(std::move(EPLs)));
+ }
+
+ const UnsafeBufferUsageAnalysisResult &
+ runAnalysisForResult(std::unique_ptr<LUSummary> LU) {
+ AnalysisDriver Driver(std::move(LU));
+ auto WPAOrErr = Driver.run<UnsafeBufferUsageAnalysisResult>();
+ EXPECT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
+ WPA = std::move(*WPAOrErr);
+ auto ROrErr = WPA.get<UnsafeBufferUsageAnalysisResult>();
+ EXPECT_THAT_EXPECTED(ROrErr, llvm::Succeeded());
+ return *ROrErr;
+ }
+
+private:
+ WPASuite WPA = makeWPASuite();
+};
+
+TEST_F(UnsafeBufferUsageWPATest, SingleEntitySummary) {
+ auto LU = makeLUSummary();
+ EntityId Foo = addEntity(*LU, "c:@F at foo");
+ EntityId P = addEntity(*LU, "c:@F at foo@p");
+
+ EntityPointerLevelSet EPLs{buildEntityPointerLevel(P, 1),
+ buildEntityPointerLevel(P, 2),
+ buildEntityPointerLevel(P, 3)};
+ insertSummary(*LU, Foo, EPLs);
+
+ const auto &R = runAnalysisForResult(std::move(LU));
+
+ ASSERT_EQ(R.UnsafeBuffers.count(Foo), 1u);
+ EXPECT_THAT(R.UnsafeBuffers.at(Foo),
+ UnorderedElementsAre(buildEntityPointerLevel(P, 1),
+ buildEntityPointerLevel(P, 2),
+ buildEntityPointerLevel(P, 3)));
+}
+
+TEST_F(UnsafeBufferUsageWPATest, MultiEntitySummaries) {
+ auto LU = makeLUSummary();
+ EntityId Foo = addEntity(*LU, "c:@F at foo");
+ EntityId Bar = addEntity(*LU, "c:@F at bar");
+ EntityId P = addEntity(*LU, "c:@F at foo@p");
+ EntityId Q = addEntity(*LU, "c:@F at bar@q");
+
+ insertSummary(*LU, Foo,
+ {buildEntityPointerLevel(P, 1), buildEntityPointerLevel(P, 2),
+ buildEntityPointerLevel(P, 3)});
+ insertSummary(*LU, Bar,
+ {buildEntityPointerLevel(Q, 1), buildEntityPointerLevel(Q, 2)});
+
+ const auto &R = runAnalysisForResult(std::move(LU));
+
+ EXPECT_EQ(R.UnsafeBuffers.size(), 2u);
+ EXPECT_THAT(R.UnsafeBuffers.at(Foo),
+ UnorderedElementsAre(buildEntityPointerLevel(P, 1),
+ buildEntityPointerLevel(P, 2),
+ buildEntityPointerLevel(P, 3)));
+ EXPECT_THAT(R.UnsafeBuffers.at(Bar),
+ UnorderedElementsAre(buildEntityPointerLevel(Q, 1),
+ buildEntityPointerLevel(Q, 2)));
+}
+
+TEST_F(UnsafeBufferUsageWPATest, EmptySummary) {
+ auto LU = makeLUSummary();
+ EntityId Foo = addEntity(*LU, "c:@F at foo");
+
+ insertSummary(*LU, Foo, {});
+
+ const auto &R = runAnalysisForResult(std::move(LU));
+
+ ASSERT_EQ(R.UnsafeBuffers.count(Foo), 1u);
+ EXPECT_THAT(R.UnsafeBuffers.at(Foo), IsEmpty());
+}
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/BuildNamespaceTest.cpp b/clang/unittests/ScalableStaticAnalysis/BuildNamespaceTest.cpp
new file mode 100644
index 0000000000000..e98efd45ea6b0
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/BuildNamespaceTest.cpp
@@ -0,0 +1,158 @@
+//===- BuildNamespaceTest.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+namespace clang::ssaf {
+namespace {
+
+TEST(BuildNamespaceTest, Equality) {
+ auto BN1 = BuildNamespace::makeCompilationUnit("test.cpp");
+ auto BN2 = BuildNamespace::makeCompilationUnit("test.cpp");
+ auto BN3 = BuildNamespace::makeCompilationUnit("other.cpp");
+
+ EXPECT_EQ(BN1, BN2);
+ EXPECT_NE(BN1, BN3);
+}
+
+TEST(BuildNamespaceTest, DifferentKinds) {
+ BuildNamespace CU(BuildNamespaceKind::CompilationUnit, "test");
+ BuildNamespace LU(BuildNamespaceKind::LinkUnit, "test");
+
+ EXPECT_NE(CU, LU);
+}
+
+// NestedBuildNamespace Tests
+
+TEST(NestedBuildNamespaceTest, DefaultConstruction) {
+ NestedBuildNamespace NBN;
+ EXPECT_TRUE(NBN.empty());
+}
+
+TEST(NestedBuildNamespaceTest, SingleNamespaceConstruction) {
+ auto BN = BuildNamespace::makeCompilationUnit("test.cpp");
+ NestedBuildNamespace NBN(BN);
+
+ EXPECT_FALSE(NBN.empty());
+}
+
+TEST(NestedBuildNamespaceTest, MakeTU) {
+ auto NBN = NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ EXPECT_FALSE(NBN.empty());
+}
+
+TEST(NestedBuildNamespaceTest, Equality) {
+ auto NBN1 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ auto NBN2 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ auto NBN3 = NestedBuildNamespace::makeCompilationUnit("other.cpp");
+
+ EXPECT_EQ(NBN1, NBN2);
+ EXPECT_NE(NBN1, NBN3);
+}
+
+TEST(NestedBuildNamespaceTest, MakeQualified) {
+ auto NBN1 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ BuildNamespace LinkNS(BuildNamespaceKind::LinkUnit, "app");
+ NestedBuildNamespace NBN2(LinkNS);
+
+ auto Qualified = NBN1.makeQualified(NBN2);
+
+ EXPECT_NE(Qualified, NBN1);
+ EXPECT_NE(Qualified, NBN2);
+}
+
+TEST(NestedBuildNamespaceTest, EmptyQualified) {
+ NestedBuildNamespace Empty;
+ auto NBN = NestedBuildNamespace::makeCompilationUnit("test.cpp");
+
+ auto Qualified = Empty.makeQualified(NBN);
+ EXPECT_EQ(Qualified, NBN);
+}
+
+TEST(BuildNamespaceKindTest, FormatProvider) {
+ EXPECT_EQ(llvm::formatv("{0}", BuildNamespaceKind::CompilationUnit).str(),
+ "CompilationUnit");
+ EXPECT_EQ(llvm::formatv("{0}", BuildNamespaceKind::LinkUnit).str(),
+ "LinkUnit");
+}
+
+TEST(BuildNamespaceKindTest, StreamOutputCompilationUnit) {
+ std::string S;
+ llvm::raw_string_ostream(S) << BuildNamespaceKind::CompilationUnit;
+ EXPECT_EQ(S, "CompilationUnit");
+}
+
+TEST(BuildNamespaceKindTest, StreamOutputLinkUnit) {
+ std::string S;
+ llvm::raw_string_ostream(S) << BuildNamespaceKind::LinkUnit;
+ EXPECT_EQ(S, "LinkUnit");
+}
+
+TEST(BuildNamespaceTest, FormatProvider) {
+ EXPECT_EQ(
+ llvm::formatv("{0}", BuildNamespace(BuildNamespaceKind::CompilationUnit,
+ "test.cpp"))
+ .str(),
+ "BuildNamespace(CompilationUnit, test.cpp)");
+}
+
+TEST(NestedBuildNamespaceTest, FormatProvider) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
+ EXPECT_EQ(
+ llvm::formatv("{0}", NBN).str(),
+ "NestedBuildNamespace([BuildNamespace(CompilationUnit, test.cpp)])");
+}
+
+TEST(BuildNamespaceTest, StreamOutputCompilationUnit) {
+ BuildNamespace BN(BuildNamespaceKind::CompilationUnit, "test.cpp");
+ std::string S;
+ llvm::raw_string_ostream(S) << BN;
+ EXPECT_EQ(S, "BuildNamespace(CompilationUnit, test.cpp)");
+}
+
+TEST(BuildNamespaceTest, StreamOutputLinkUnit) {
+ BuildNamespace BN(BuildNamespaceKind::LinkUnit, "app");
+ std::string S;
+ llvm::raw_string_ostream(S) << BN;
+ EXPECT_EQ(S, "BuildNamespace(LinkUnit, app)");
+}
+
+TEST(NestedBuildNamespaceTest, StreamOutputEmpty) {
+ NestedBuildNamespace NBN;
+ std::string S;
+ llvm::raw_string_ostream(S) << NBN;
+ EXPECT_EQ(S, "NestedBuildNamespace([])");
+}
+
+TEST(NestedBuildNamespaceTest, StreamOutputSingle) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
+ std::string S;
+ llvm::raw_string_ostream(S) << NBN;
+ EXPECT_EQ(
+ S, "NestedBuildNamespace([BuildNamespace(CompilationUnit, test.cpp)])");
+}
+
+TEST(NestedBuildNamespaceTest, StreamOutputMultiple) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
+ NBN = NBN.makeQualified(NestedBuildNamespace(
+ BuildNamespace(BuildNamespaceKind::LinkUnit, "app")));
+ std::string S;
+ llvm::raw_string_ostream(S) << NBN;
+ EXPECT_EQ(S, "NestedBuildNamespace([BuildNamespace(CompilationUnit, "
+ "test.cpp), BuildNamespace(LinkUnit, app)])");
+}
+
+} // namespace
+} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt b/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
new file mode 100644
index 0000000000000..387f03dc76fc6
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/CMakeLists.txt
@@ -0,0 +1,56 @@
+add_distinct_clang_unittest(ClangScalableAnalysisTests
+ Analyses/PointerFlow/PointerFlowTest.cpp
+ Analyses/PointerFlow/PointerFlowWPATest.cpp
+ Analyses/CallGraph/CallGraphExtractorTest.cpp
+ Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp
+ Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp
+ ASTEntityMappingTest.cpp
+ BuildNamespaceTest.cpp
+ EntityIdTableTest.cpp
+ EntityIdTest.cpp
+ EntityLinkageTest.cpp
+ EntityLinkerTest.cpp
+ EntityNameTest.cpp
+ ErrorBuilderTest.cpp
+ Frontend/TUSummaryExtractorFrontendActionTest.cpp
+ LUSummaryTest.cpp
+ ModelStringConversionsTest.cpp
+ Registries/FancyAnalysisData.cpp
+ Registries/MockSerializationFormat.cpp
+ Registries/MockSummaryExtractor1.cpp
+ Registries/MockSummaryExtractor2.cpp
+ Registries/SerializationFormatRegistryTest.cpp
+ Registries/SummaryExtractorRegistryTest.cpp
+ Serialization/JSONFormatTest/JSONFormatTest.cpp
+ Serialization/JSONFormatTest/LUSummaryTest.cpp
+ Serialization/JSONFormatTest/TUSummaryTest.cpp
+ SourceTransformation/EmitterTest.cpp
+ SourceTransformation/RegistryTest.cpp
+ SummaryData/SummaryDataTest.cpp
+ SummaryNameTest.cpp
+ TestFixture.cpp
+ TUSummaryBuilderTest.cpp
+ WholeProgramAnalysis/AnalysisDriverTest.cpp
+ WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp
+
+ CLANG_LIBS
+ clangAST
+ clangASTMatchers
+ clangBasic
+ clangFrontend
+ clangScalableStaticAnalysisAnalyses
+ clangScalableStaticAnalysisCore
+ clangScalableStaticAnalysisFrontend
+ clangScalableStaticAnalysisSourceTransformation
+ clangSerialization
+ clangTooling
+ clangToolingCore
+
+ LINK_LIBS
+ LLVMTestingSupport
+
+ LLVM_COMPONENTS
+ FrontendOpenMP
+ Support
+ TargetParser
+ )
diff --git a/clang/unittests/ScalableStaticAnalysis/EntityIdTableTest.cpp b/clang/unittests/ScalableStaticAnalysis/EntityIdTableTest.cpp
new file mode 100644
index 0000000000000..ead7e35f8421f
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/EntityIdTableTest.cpp
@@ -0,0 +1,142 @@
+//===- EntityIdTableTest.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace ssaf {
+namespace {
+
+TEST(EntityIdTableTest, CreateNewEntity) {
+ EntityIdTable Table;
+
+ EntityName Entity("c:@F at foo", "", {});
+ Table.getId(Entity);
+
+ EXPECT_TRUE(Table.contains(Entity));
+}
+
+TEST(EntityIdTableTest, Idempotency) {
+ EntityIdTable Table;
+
+ EntityName Entity("c:@F at foo", "", {});
+ EntityName EntityCopy = Entity;
+
+ EntityId Id1 = Table.getId(Entity);
+ EntityId Id2 = Table.getId(Entity);
+ EntityId Id3 = Table.getId(EntityCopy);
+
+ EXPECT_EQ(Id1, Id2);
+ EXPECT_EQ(Id2, Id3);
+ EXPECT_EQ(Id1, Id3);
+}
+
+TEST(EntityIdTableTest, ExistsTrue) {
+ EntityIdTable Table;
+
+ EntityName Entity1("c:@F at foo", "", {});
+ EntityName Entity2("c:@V at bar", "", {});
+
+ Table.getId(Entity1);
+ Table.getId(Entity2);
+
+ EXPECT_TRUE(Table.contains(Entity1));
+ EXPECT_TRUE(Table.contains(Entity2));
+}
+
+TEST(EntityIdTableTest, ExistsFalse) {
+ EntityIdTable Table;
+
+ EntityName Entity1("c:@F at foo", "", {});
+ EntityName Entity2("c:@F at bar", "", {});
+
+ Table.getId(Entity1);
+
+ EXPECT_TRUE(Table.contains(Entity1));
+ EXPECT_FALSE(Table.contains(Entity2));
+}
+
+TEST(EntityIdTableTest, MultipleEntities) {
+ EntityIdTable Table;
+
+ EntityName Entity1("c:@F at foo", "", {});
+ EntityName Entity2("c:@F at bar", "", {});
+ EntityName Entity3("c:@V at baz", "", {});
+
+ EntityId Id1 = Table.getId(Entity1);
+ EntityId Id2 = Table.getId(Entity2);
+ EntityId Id3 = Table.getId(Entity3);
+
+ EXPECT_NE(Id1, Id2);
+ EXPECT_NE(Id1, Id3);
+ EXPECT_NE(Id2, Id3);
+}
+
+TEST(EntityIdTableTest, WithBuildNamespace) {
+ EntityIdTable Table;
+
+ NestedBuildNamespace NS = NestedBuildNamespace::makeCompilationUnit("test.o");
+
+ EntityName Entity1("c:@F at foo", "", NS);
+ EntityName Entity2("c:@F at foo", "",
+ NestedBuildNamespace::makeCompilationUnit("other.o"));
+
+ EntityId Id1 = Table.getId(Entity1);
+ EntityId Id2 = Table.getId(Entity2);
+
+ EXPECT_NE(Id1, Id2);
+}
+
+TEST(EntityIdTableTest, ForEachEmptyTable) {
+ EntityIdTable Table;
+
+ int CallbackCount = 0;
+ Table.forEach(
+ [&CallbackCount](const EntityName &, EntityId) { CallbackCount++; });
+
+ EXPECT_EQ(CallbackCount, 0);
+}
+
+TEST(EntityIdTableTest, ForEachMultipleEntities) {
+ EntityIdTable Table;
+
+ EntityName Entity1("c:@F at foo", "", {});
+ EntityName Entity2("c:@F at bar", "", {});
+ EntityName Entity3("c:@V at baz", "", {});
+
+ EntityId Id1 = Table.getId(Entity1);
+ EntityId Id2 = Table.getId(Entity2);
+ EntityId Id3 = Table.getId(Entity3);
+
+ std::set<EntityId> VisitedIds;
+ std::set<EntityName> VisitedNames;
+
+ Table.forEach([&](const EntityName &Name, EntityId Id) {
+ VisitedIds.insert(Id);
+ VisitedNames.insert(Name);
+ });
+
+ EXPECT_EQ(VisitedIds.size(), 3u);
+ EXPECT_EQ(VisitedNames.size(), 3u);
+
+ EXPECT_TRUE(VisitedIds.count(Id1));
+ EXPECT_TRUE(VisitedIds.count(Id2));
+ EXPECT_TRUE(VisitedIds.count(Id3));
+
+ EXPECT_TRUE(VisitedNames.count(Entity1));
+ EXPECT_TRUE(VisitedNames.count(Entity2));
+ EXPECT_TRUE(VisitedNames.count(Entity3));
+}
+
+} // namespace
+} // namespace ssaf
+} // namespace clang
diff --git a/clang/unittests/ScalableStaticAnalysis/EntityIdTest.cpp b/clang/unittests/ScalableStaticAnalysis/EntityIdTest.cpp
new file mode 100644
index 0000000000000..e01ceda75324a
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/EntityIdTest.cpp
@@ -0,0 +1,100 @@
+//===- EntityIdTest.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+#include <cctype>
+
+namespace clang::ssaf {
+namespace {
+
+static bool isNonNegativeInteger(llvm::StringRef S) {
+ return !S.empty() &&
+ llvm::all_of(S, [](unsigned char C) { return std::isdigit(C); });
+}
+
+TEST(EntityIdTest, Equality) {
+ EntityIdTable Table;
+
+ EntityName Entity1("c:@F at foo", "", {});
+ EntityName Entity2("c:@F at bar", "", {});
+
+ EntityId Id1 = Table.getId(Entity1);
+ EntityId Id2 = Table.getId(Entity2);
+ EntityId Id1Copy = Table.getId(Entity1);
+
+ EXPECT_EQ(Id1, Id1Copy);
+ EXPECT_FALSE(Id1 != Id1Copy);
+ EXPECT_FALSE(Id1 < Id1Copy);
+ EXPECT_FALSE(Id1Copy < Id1);
+
+ EXPECT_NE(Id1, Id2);
+ EXPECT_FALSE(Id1 == Id2);
+ EXPECT_TRUE(Id1 < Id2 || Id2 < Id1);
+}
+
+TEST(EntityIdTest, LessThan) {
+ EntityIdTable Table;
+
+ EntityName Entity1("c:@F at aaa", "", {});
+ EntityName Entity2("c:@F at bbb", "", {});
+
+ EntityId Id1 = Table.getId(Entity1);
+ EntityId Id2 = Table.getId(Entity2);
+
+ EXPECT_TRUE(Id1 < Id2 || Id2 < Id1);
+}
+
+TEST(EntityIdTest, Transitivity) {
+ EntityIdTable Table;
+
+ EntityName Entity1("c:@F at xxx", "", {});
+ EntityName Entity2("c:@F at yyy", "", {});
+ EntityName Entity3("c:@F at zzz", "", {});
+
+ EntityId Ids[3] = {Table.getId(Entity1), Table.getId(Entity2),
+ Table.getId(Entity3)};
+
+ std::sort(Ids, Ids + 3);
+
+ EXPECT_TRUE(Ids[0] < Ids[1] && Ids[1] < Ids[2]);
+}
+
+TEST(EntityIdTest, FormatProvider) {
+ EntityIdTable Table;
+ EntityName Entity("c:@F at foo", "", {});
+ EntityId Id = Table.getId(Entity);
+
+ std::string S = llvm::formatv("{0}", Id).str();
+ llvm::StringRef Ref(S);
+ ASSERT_TRUE(Ref.consume_front("EntityId("));
+ ASSERT_TRUE(Ref.consume_back(")"));
+ EXPECT_TRUE(isNonNegativeInteger(Ref));
+}
+
+TEST(EntityIdTest, StreamOutput) {
+ EntityIdTable Table;
+ EntityName Entity("c:@F at foo", "", {});
+ EntityId Id = Table.getId(Entity);
+
+ std::string S;
+ llvm::raw_string_ostream(S) << Id;
+
+ llvm::StringRef Ref(S);
+ ASSERT_TRUE(Ref.consume_front("EntityId("));
+ ASSERT_TRUE(Ref.consume_back(")"));
+ EXPECT_TRUE(isNonNegativeInteger(Ref));
+}
+
+} // namespace
+} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysis/EntityLinkageTest.cpp b/clang/unittests/ScalableStaticAnalysis/EntityLinkageTest.cpp
new file mode 100644
index 0000000000000..ccf38ec8d93fb
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/EntityLinkageTest.cpp
@@ -0,0 +1,117 @@
+//===- EntityLinkageTest.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using clang::ssaf::EntityLinkage;
+using clang::ssaf::EntityLinkageType;
+
+namespace {
+
+constexpr inline auto None = EntityLinkageType::None;
+constexpr inline auto Internal = EntityLinkageType::Internal;
+constexpr inline auto External = EntityLinkageType::External;
+
+TEST(EntityLinkageTest, Constructor) {
+ EntityLinkage NoneLinkage(None);
+ EntityLinkage InternalLinkage(Internal);
+ EntityLinkage ExternalLinkage(External);
+
+ EXPECT_EQ(NoneLinkage.getLinkage(), None);
+ EXPECT_EQ(InternalLinkage.getLinkage(), Internal);
+ EXPECT_EQ(ExternalLinkage.getLinkage(), External);
+}
+
+TEST(EntityLinkageTest, CopyConstructor) {
+ EntityLinkage Original(External);
+ EntityLinkage Copy = Original;
+
+ EXPECT_EQ(Copy.getLinkage(), External);
+ EXPECT_EQ(Copy.getLinkage(), Original.getLinkage());
+}
+
+TEST(EntityLinkageTest, AssignmentOperator) {
+ EntityLinkage Linkage1(None);
+ EntityLinkage Linkage2(External);
+
+ Linkage1 = Linkage2;
+
+ EXPECT_EQ(Linkage1.getLinkage(), External);
+ EXPECT_EQ(Linkage1.getLinkage(), Linkage2.getLinkage());
+}
+
+TEST(EntityLinkageTest, EqualityOperatorReflexive) {
+ EXPECT_EQ(EntityLinkage(None), EntityLinkage(None));
+ EXPECT_EQ(EntityLinkage(Internal), EntityLinkage(Internal));
+ EXPECT_EQ(EntityLinkage(External), EntityLinkage(External));
+}
+
+TEST(EntityLinkageTest, EqualityOperatorDistinct) {
+ EXPECT_NE(EntityLinkage(None), EntityLinkage(Internal));
+ EXPECT_NE(EntityLinkage(None), EntityLinkage(External));
+ EXPECT_NE(EntityLinkage(Internal), EntityLinkage(External));
+}
+
+TEST(EntityLinkageTypeTest, FormatProvider) {
+ EXPECT_EQ(llvm::formatv("{0}", EntityLinkageType::None).str(), "None");
+ EXPECT_EQ(llvm::formatv("{0}", EntityLinkageType::Internal).str(),
+ "Internal");
+ EXPECT_EQ(llvm::formatv("{0}", EntityLinkageType::External).str(),
+ "External");
+}
+
+TEST(EntityLinkageTypeTest, StreamOutputNone) {
+ std::string S;
+ llvm::raw_string_ostream(S) << EntityLinkageType::None;
+ EXPECT_EQ(S, "None");
+}
+
+TEST(EntityLinkageTypeTest, StreamOutputInternal) {
+ std::string S;
+ llvm::raw_string_ostream(S) << EntityLinkageType::Internal;
+ EXPECT_EQ(S, "Internal");
+}
+
+TEST(EntityLinkageTypeTest, StreamOutputExternal) {
+ std::string S;
+ llvm::raw_string_ostream(S) << EntityLinkageType::External;
+ EXPECT_EQ(S, "External");
+}
+
+TEST(EntityLinkageTest, FormatProvider) {
+ EXPECT_EQ(llvm::formatv("{0}", EntityLinkage(None)).str(),
+ "EntityLinkage(None)");
+ EXPECT_EQ(llvm::formatv("{0}", EntityLinkage(Internal)).str(),
+ "EntityLinkage(Internal)");
+ EXPECT_EQ(llvm::formatv("{0}", EntityLinkage(External)).str(),
+ "EntityLinkage(External)");
+}
+
+TEST(EntityLinkageTest, StreamOutputNone) {
+ std::string S;
+ llvm::raw_string_ostream(S) << EntityLinkage(None);
+ EXPECT_EQ(S, "EntityLinkage(None)");
+}
+
+TEST(EntityLinkageTest, StreamOutputInternal) {
+ std::string S;
+ llvm::raw_string_ostream(S) << EntityLinkage(Internal);
+ EXPECT_EQ(S, "EntityLinkage(Internal)");
+}
+
+TEST(EntityLinkageTest, StreamOutputExternal) {
+ std::string S;
+ llvm::raw_string_ostream(S) << EntityLinkage(External);
+ EXPECT_EQ(S, "EntityLinkage(External)");
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/EntityLinkerTest.cpp b/clang/unittests/ScalableStaticAnalysis/EntityLinkerTest.cpp
new file mode 100644
index 0000000000000..cd579e16991ef
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/EntityLinkerTest.cpp
@@ -0,0 +1,667 @@
+//===- EntityLinkerTest.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntityLinker.h"
+#include "TestFixture.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/EntitySummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace clang::ssaf;
+using namespace llvm;
+using ::testing::HasSubstr;
+using ::testing::Not;
+using ::testing::PrintToString;
+
+namespace {
+
+class MockEntitySummaryEncoding : public EntitySummaryEncoding {
+public:
+ MockEntitySummaryEncoding() : Id(++Index) {}
+
+ size_t getId() const { return Id; }
+
+ llvm::Error
+ patch(const std::map<EntityId, EntityId> &EntityResolutionTable) override {
+ PatchedIds = EntityResolutionTable;
+ return llvm::Error::success();
+ }
+
+ const std::map<EntityId, EntityId> &getPatchedIds() const {
+ return PatchedIds;
+ }
+
+ static size_t Index;
+
+private:
+ size_t Id;
+ std::map<EntityId, EntityId> PatchedIds;
+};
+
+size_t MockEntitySummaryEncoding::Index = 0;
+
+class EntityLinkerTest : public TestFixture {
+protected:
+ static constexpr EntityLinkage NoneLinkage =
+ EntityLinkage(EntityLinkageType::None);
+ static constexpr EntityLinkage InternalLinkage =
+ EntityLinkage(EntityLinkageType::Internal);
+ static constexpr EntityLinkage ExternalLinkage =
+ EntityLinkage(EntityLinkageType::External);
+
+ void SetUp() override {
+ // This ensures that the MockEntitySummary id assignment does not
+ // accidentally depend on test execution order.
+ MockEntitySummaryEncoding::Index = 0;
+ }
+
+ std::unique_ptr<TUSummaryEncoding> createTUSummaryEncoding(
+ BuildNamespaceKind Kind, llvm::StringRef Name,
+ llvm::Triple TargetTriple = llvm::Triple("arm64-apple-macosx")) {
+ return std::make_unique<TUSummaryEncoding>(std::move(TargetTriple),
+ BuildNamespace(Kind, Name));
+ }
+
+ size_t addSummaryData(TUSummaryEncoding &TU, EntityId EId,
+ llvm::StringRef SummaryNameStr) {
+ SummaryName SN(SummaryNameStr.str());
+ auto Summary = std::make_unique<MockEntitySummaryEncoding>();
+ const size_t ESId = Summary->getId();
+ getData(TU)[SN][EId] = std::move(Summary);
+ return ESId;
+ }
+
+ EntityId addEntity(TUSummaryEncoding &TU, llvm::StringRef USR,
+ EntityLinkage Linkage) {
+ EntityName Name(USR, "", NestedBuildNamespace());
+ EntityId Id = getIdTable(TU).getId(Name);
+ getLinkageTable(TU).insert({Id, Linkage});
+ return Id;
+ }
+};
+
+// ============================================================================
+// Entity ID Table Matchers
+// ============================================================================
+
+MATCHER_P(ContainsEntity, EntityName,
+ std::string(negation ? "does not contain" : "contains") +
+ " entity '" + PrintToString(EntityName) + "'") {
+ return arg.contains(EntityName);
+}
+
+MATCHER_P(IdTableHasSize, ExpectedCount,
+ std::string("has ") + PrintToString(ExpectedCount) + " entities") {
+ if (arg.count() != ExpectedCount) {
+ *result_listener << "has " << arg.count() << " entities";
+ return false;
+ }
+ return true;
+}
+
+// ============================================================================
+// Linkage Table Matchers
+// ============================================================================
+
+MATCHER_P2(EntityHasLinkage, EId, ExpectedLinkage,
+ std::string("entity has ") + PrintToString(ExpectedLinkage) +
+ " linkage") {
+ auto It = arg.find(EId);
+ if (It == arg.end()) {
+ *result_listener << "entity " << PrintToString(EId)
+ << " not found in linkage table";
+ return false;
+ }
+
+ const EntityLinkage &ActualLinkage = It->second;
+ if (ActualLinkage != ExpectedLinkage) {
+ *result_listener << "entity " << PrintToString(EId) << " has linkage "
+ << PrintToString(ActualLinkage);
+ return false;
+ }
+
+ return true;
+}
+
+MATCHER_P(LinkageTableHasSize, ExpectedSize,
+ std::string("linkage table has size ") +
+ PrintToString(ExpectedSize)) {
+ if (arg.size() != ExpectedSize) {
+ *result_listener << "has size " << arg.size();
+ return false;
+ }
+ return true;
+}
+
+// ============================================================================
+// Summary Data Matchers
+// ============================================================================
+
+MATCHER_P3(HasSummaryData, EId, ExpectedMockId, ExpectedResolutionMapping,
+ std::string("has summary data for entity with expected mock ID ") +
+ PrintToString(ExpectedMockId)) {
+
+ auto It = arg.find(EId);
+ if (It == arg.end()) {
+ *result_listener << "entity " << PrintToString(EId)
+ << " not found in summary data";
+ return false;
+ }
+
+ auto *Mock = static_cast<const MockEntitySummaryEncoding *>(It->second.get());
+
+ if (Mock->getId() != ExpectedMockId) {
+ *result_listener << "entity " << PrintToString(EId) << " has mock ID "
+ << Mock->getId() << " (expected " << ExpectedMockId << ")";
+ return false;
+ }
+
+ if (Mock->getPatchedIds() != ExpectedResolutionMapping) {
+ *result_listener << "entity " << PrintToString(EId)
+ << " has different resolution mapping";
+ return false;
+ }
+
+ return true;
+}
+
+MATCHER_P(SummaryDataHasSize, ExpectedSize,
+ std::string("summary data has size ") + PrintToString(ExpectedSize)) {
+ if (arg.size() != ExpectedSize) {
+ *result_listener << "has size " << arg.size();
+ return false;
+ }
+ return true;
+}
+
+// ============================================================================
+// ENTITY LINKER TESTS
+// ============================================================================
+
+TEST_F(EntityLinkerTest, CreatesEmptyLinker) {
+ NestedBuildNamespace LUNamespace(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "LU")});
+
+ EntityLinker Linker(llvm::Triple("arm64-apple-macosx"), LUNamespace);
+
+ const auto Output = std::move(Linker).takeOutput();
+ EXPECT_EQ(getIdTable(Output).count(), 0u);
+ EXPECT_EQ(getLinkageTable(Output).size(), 0u);
+ EXPECT_EQ(getData(Output).size(), 0u);
+}
+
+TEST_F(EntityLinkerTest, LinksEmptyTranslationUnit) {
+ NestedBuildNamespace LUNamespace(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "LU")});
+
+ EntityLinker Linker(llvm::Triple("arm64-apple-macosx"), LUNamespace);
+
+ auto TUEmpty =
+ createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TUEmpty");
+
+ EXPECT_THAT_ERROR(Linker.link(std::move(TUEmpty)), llvm::Succeeded());
+
+ const auto Output = std::move(Linker).takeOutput();
+ EXPECT_EQ(getIdTable(Output).count(), 0u);
+ EXPECT_EQ(getLinkageTable(Output).size(), 0u);
+ EXPECT_EQ(getData(Output).size(), 0u);
+}
+
+TEST_F(EntityLinkerTest, LinksOneTranslationUnit) {
+ NestedBuildNamespace LUNamespace(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "LU")});
+
+ EntityLinker Linker(llvm::Triple("arm64-apple-macosx"), LUNamespace);
+
+ auto TU = createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TU");
+
+ const auto TU_A_Id = addEntity(*TU, "A", NoneLinkage);
+ const auto TU_A_S1_Data = addSummaryData(*TU, TU_A_Id, "S1");
+ const auto TU_A_S2_Data = addSummaryData(*TU, TU_A_Id, "S2");
+
+ const auto TU_B_Id = addEntity(*TU, "B", InternalLinkage);
+ const auto TU_B_S1_Data = addSummaryData(*TU, TU_B_Id, "S1");
+ const auto TU_B_S2_Data = addSummaryData(*TU, TU_B_Id, "S2");
+
+ const auto TU_C_Id = addEntity(*TU, "C", ExternalLinkage);
+ const auto TU_C_S1_Data = addSummaryData(*TU, TU_C_Id, "S1");
+
+ const auto TU_D_Id = addEntity(*TU, "D", ExternalLinkage);
+ const auto TU_D_S2_Data = addSummaryData(*TU, TU_D_Id, "S2");
+
+ const BuildNamespace TUNamespace = getTUNamespace(*TU);
+
+ ASSERT_THAT_ERROR(Linker.link(std::move(TU)), llvm::Succeeded());
+
+ const auto Output = std::move(Linker).takeOutput();
+ const auto &IdTable = getIdTable(Output);
+ const auto &Entities = getEntities(IdTable);
+ const auto &LinkageTable = getLinkageTable(Output);
+ const auto &Data = getData(Output);
+
+ NestedBuildNamespace LocalNamespace =
+ NestedBuildNamespace(TUNamespace).makeQualified(LUNamespace);
+
+ EntityName LU_A_Name("A", "", LocalNamespace);
+ EntityName LU_B_Name("B", "", LocalNamespace);
+ EntityName LU_C_Name("C", "", LUNamespace);
+ EntityName LU_D_Name("D", "", LUNamespace);
+
+ // EntityIdTable Tests.
+ {
+ ASSERT_THAT(IdTable, IdTableHasSize(4u));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_A_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_B_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_C_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_D_Name));
+ }
+
+ // This is safe since we confirmed that these entities are present in the
+ // block above.
+ const auto LU_A_Id = Entities.at(LU_A_Name);
+ const auto LU_B_Id = Entities.at(LU_B_Name);
+ const auto LU_C_Id = Entities.at(LU_C_Name);
+ const auto LU_D_Id = Entities.at(LU_D_Name);
+
+ // LinkageTable Tests.
+ {
+ ASSERT_THAT(LinkageTable, LinkageTableHasSize(4u));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_A_Id, NoneLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_B_Id, InternalLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_C_Id, ExternalLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_D_Id, ExternalLinkage));
+ }
+
+ std::map<EntityId, EntityId> Resolution = {{TU_A_Id, LU_A_Id},
+ {TU_B_Id, LU_B_Id},
+ {TU_C_Id, LU_C_Id},
+ {TU_D_Id, LU_D_Id}};
+
+ // Data Tests.
+ {
+ ASSERT_EQ(Data.size(), 2u);
+
+ // S1 Data Tests.
+ {
+ SummaryName S1("S1");
+ ASSERT_NE(Data.find(S1), Data.end());
+ const auto &S1Data = Data.at(S1);
+
+ ASSERT_THAT(S1Data, SummaryDataHasSize(3u));
+ ASSERT_THAT(S1Data, HasSummaryData(LU_A_Id, TU_A_S1_Data, Resolution));
+ ASSERT_THAT(S1Data, HasSummaryData(LU_B_Id, TU_B_S1_Data, Resolution));
+ ASSERT_THAT(S1Data, HasSummaryData(LU_C_Id, TU_C_S1_Data, Resolution));
+ }
+
+ // S2 Data Tests.
+ {
+ SummaryName S2("S2");
+ ASSERT_NE(Data.find(S2), Data.end());
+ const auto &S2Data = Data.at(S2);
+
+ ASSERT_THAT(S2Data, SummaryDataHasSize(3u));
+ ASSERT_THAT(S2Data, HasSummaryData(LU_A_Id, TU_A_S2_Data, Resolution));
+ ASSERT_THAT(S2Data, HasSummaryData(LU_B_Id, TU_B_S2_Data, Resolution));
+ ASSERT_THAT(S2Data, HasSummaryData(LU_D_Id, TU_D_S2_Data, Resolution));
+ }
+ }
+}
+
+TEST_F(EntityLinkerTest, LinksTwoTranslationUnits) {
+ NestedBuildNamespace LUNamespace(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "LU")});
+
+ EntityLinker Linker(llvm::Triple("arm64-apple-macosx"), LUNamespace);
+
+ auto TU1 =
+ createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TU1");
+
+ // None linkage entities in TU1
+ const auto TU1_X_Id = addEntity(*TU1, "X", NoneLinkage);
+ const auto TU1_X_S1_Data = addSummaryData(*TU1, TU1_X_Id, "S1");
+
+ const auto TU1_Y_Id = addEntity(*TU1, "Y", NoneLinkage);
+ const auto TU1_Y_S2_Data = addSummaryData(*TU1, TU1_Y_Id, "S2");
+
+ const auto TU1_Z_Id = addEntity(*TU1, "Z", NoneLinkage);
+ const auto TU1_Z_S1_Data = addSummaryData(*TU1, TU1_Z_Id, "S1");
+ const auto TU1_Z_S2_Data = addSummaryData(*TU1, TU1_Z_Id, "S2");
+
+ // Internal linkage entities in TU1
+ const auto TU1_A_Id = addEntity(*TU1, "A", InternalLinkage);
+ const auto TU1_A_S1_Data = addSummaryData(*TU1, TU1_A_Id, "S1");
+
+ const auto TU1_B_Id = addEntity(*TU1, "B", InternalLinkage);
+ const auto TU1_B_S2_Data = addSummaryData(*TU1, TU1_B_Id, "S2");
+
+ const auto TU1_C_Id = addEntity(*TU1, "C", InternalLinkage);
+ const auto TU1_C_S1_Data = addSummaryData(*TU1, TU1_C_Id, "S1");
+ const auto TU1_C_S2_Data = addSummaryData(*TU1, TU1_C_Id, "S2");
+
+ // External linkage entities in TU1
+ const auto TU1_P_Id = addEntity(*TU1, "P", ExternalLinkage);
+ const auto TU1_P_S1_Data = addSummaryData(*TU1, TU1_P_Id, "S1");
+
+ const auto TU1_Q_Id = addEntity(*TU1, "Q", ExternalLinkage);
+ const auto TU1_Q_S2_Data = addSummaryData(*TU1, TU1_Q_Id, "S2");
+
+ const auto TU1_R_Id = addEntity(*TU1, "R", ExternalLinkage);
+ const auto TU1_R_S1_Data = addSummaryData(*TU1, TU1_R_Id, "S1");
+ const auto TU1_R_S2_Data = addSummaryData(*TU1, TU1_R_Id, "S2");
+
+ const BuildNamespace TU1Namespace = getTUNamespace(*TU1);
+
+ ASSERT_THAT_ERROR(Linker.link(std::move(TU1)), llvm::Succeeded());
+
+ auto TU2 =
+ createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TU2");
+
+ // None linkage entities in TU2 - includes duplicates and uniques
+ const auto TU2_X_Id = addEntity(*TU2, "X", NoneLinkage);
+ const auto TU2_X_S2_Data = addSummaryData(*TU2, TU2_X_Id, "S2");
+
+ const auto TU2_Y_Id = addEntity(*TU2, "Y", NoneLinkage);
+ const auto TU2_Y_S1_Data = addSummaryData(*TU2, TU2_Y_Id, "S1");
+
+ const auto TU2_W_Id = addEntity(*TU2, "W", NoneLinkage);
+ const auto TU2_W_S1_Data = addSummaryData(*TU2, TU2_W_Id, "S1");
+ const auto TU2_W_S2_Data = addSummaryData(*TU2, TU2_W_Id, "S2");
+
+ // Internal linkage entities in TU2 - includes duplicates and unique
+ const auto TU2_A_Id = addEntity(*TU2, "A", InternalLinkage);
+ const auto TU2_A_S2_Data = addSummaryData(*TU2, TU2_A_Id, "S2");
+
+ const auto TU2_B_Id = addEntity(*TU2, "B", InternalLinkage);
+ const auto TU2_B_S1_Data = addSummaryData(*TU2, TU2_B_Id, "S1");
+
+ const auto TU2_D_Id = addEntity(*TU2, "D", InternalLinkage);
+ const auto TU2_D_S1_Data = addSummaryData(*TU2, TU2_D_Id, "S1");
+ const auto TU2_D_S2_Data = addSummaryData(*TU2, TU2_D_Id, "S2");
+
+ // External linkage entities in TU2 - includes duplicates (will be dropped)
+ // and uniques
+ const auto TU2_P_Id = addEntity(*TU2, "P", ExternalLinkage);
+ const auto TU2_P_S2_Data = addSummaryData(*TU2, TU2_P_Id, "S2");
+
+ const auto TU2_Q_Id = addEntity(*TU2, "Q", ExternalLinkage);
+ const auto TU2_Q_S1_Data = addSummaryData(*TU2, TU2_Q_Id, "S1");
+
+ const auto TU2_R_Id = addEntity(*TU2, "R", ExternalLinkage);
+ const auto TU2_R_S1_Data = addSummaryData(*TU2, TU2_R_Id, "S1");
+ const auto TU2_R_S2_Data = addSummaryData(*TU2, TU2_R_Id, "S2");
+
+ const auto TU2_S_Id = addEntity(*TU2, "S", ExternalLinkage);
+ const auto TU2_S_S1_Data = addSummaryData(*TU2, TU2_S_Id, "S1");
+ const auto TU2_S_S2_Data = addSummaryData(*TU2, TU2_S_Id, "S2");
+
+ const BuildNamespace TU2Namespace = getTUNamespace(*TU2);
+
+ ASSERT_THAT_ERROR(Linker.link(std::move(TU2)), llvm::Succeeded());
+
+ const auto Output = std::move(Linker).takeOutput();
+ const auto &IdTable = getIdTable(Output);
+ const auto &Entities = getEntities(IdTable);
+ const auto &LinkageTable = getLinkageTable(Output);
+ const auto &Data = getData(Output);
+
+ NestedBuildNamespace TU1LocalNamespace =
+ NestedBuildNamespace(TU1Namespace).makeQualified(LUNamespace);
+
+ NestedBuildNamespace TU2LocalNamespace =
+ NestedBuildNamespace(TU2Namespace).makeQualified(LUNamespace);
+
+ // None linkage entities use local namespace (TU scoped)
+ EntityName LU_TU1_X_Name("X", "", TU1LocalNamespace);
+ EntityName LU_TU1_Y_Name("Y", "", TU1LocalNamespace);
+ EntityName LU_TU1_Z_Name("Z", "", TU1LocalNamespace);
+ EntityName LU_TU2_X_Name("X", "", TU2LocalNamespace);
+ EntityName LU_TU2_Y_Name("Y", "", TU2LocalNamespace);
+ EntityName LU_TU2_W_Name("W", "", TU2LocalNamespace);
+
+ // Internal linkage entities use local namespace (TU scoped)
+ EntityName LU_TU1_A_Name("A", "", TU1LocalNamespace);
+ EntityName LU_TU1_B_Name("B", "", TU1LocalNamespace);
+ EntityName LU_TU1_C_Name("C", "", TU1LocalNamespace);
+ EntityName LU_TU2_A_Name("A", "", TU2LocalNamespace);
+ EntityName LU_TU2_B_Name("B", "", TU2LocalNamespace);
+ EntityName LU_TU2_D_Name("D", "", TU2LocalNamespace);
+
+ // External linkage entities use LU namespace (shared across TUs)
+ EntityName LU_P_Name("P", "", LUNamespace);
+ EntityName LU_Q_Name("Q", "", LUNamespace);
+ EntityName LU_R_Name("R", "", LUNamespace);
+ EntityName LU_S_Name("S", "", LUNamespace);
+
+ // EntityIdTable Tests.
+ {
+ // Should have 6 None + 6 Internal + 4 External = 16 entities total
+ ASSERT_THAT(IdTable, IdTableHasSize(16u));
+
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_X_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_Y_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_Z_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_X_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_Y_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_W_Name));
+
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_A_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_B_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU1_C_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_A_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_B_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_TU2_D_Name));
+
+ ASSERT_THAT(IdTable, ContainsEntity(LU_P_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_Q_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_R_Name));
+ ASSERT_THAT(IdTable, ContainsEntity(LU_S_Name));
+ }
+
+ // This is safe since we confirmed that these entities are present in the
+ // block above.
+ const auto LU_TU1_X_Id = Entities.at(LU_TU1_X_Name);
+ const auto LU_TU1_Y_Id = Entities.at(LU_TU1_Y_Name);
+ const auto LU_TU1_Z_Id = Entities.at(LU_TU1_Z_Name);
+ const auto LU_TU2_X_Id = Entities.at(LU_TU2_X_Name);
+ const auto LU_TU2_Y_Id = Entities.at(LU_TU2_Y_Name);
+ const auto LU_TU2_W_Id = Entities.at(LU_TU2_W_Name);
+ const auto LU_TU1_A_Id = Entities.at(LU_TU1_A_Name);
+ const auto LU_TU1_B_Id = Entities.at(LU_TU1_B_Name);
+ const auto LU_TU1_C_Id = Entities.at(LU_TU1_C_Name);
+ const auto LU_TU2_A_Id = Entities.at(LU_TU2_A_Name);
+ const auto LU_TU2_B_Id = Entities.at(LU_TU2_B_Name);
+ const auto LU_TU2_D_Id = Entities.at(LU_TU2_D_Name);
+ const auto LU_P_Id = Entities.at(LU_P_Name);
+ const auto LU_Q_Id = Entities.at(LU_Q_Name);
+ const auto LU_R_Id = Entities.at(LU_R_Name);
+ const auto LU_S_Id = Entities.at(LU_S_Name);
+
+ // LinkageTable Tests.
+ {
+ ASSERT_THAT(LinkageTable, LinkageTableHasSize(16u));
+
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_X_Id, NoneLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_Y_Id, NoneLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_Z_Id, NoneLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_X_Id, NoneLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_Y_Id, NoneLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_W_Id, NoneLinkage));
+
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_A_Id, InternalLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_B_Id, InternalLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU1_C_Id, InternalLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_A_Id, InternalLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_B_Id, InternalLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_TU2_D_Id, InternalLinkage));
+
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_P_Id, ExternalLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_Q_Id, ExternalLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_R_Id, ExternalLinkage));
+ ASSERT_THAT(LinkageTable, EntityHasLinkage(LU_S_Id, ExternalLinkage));
+ }
+
+ // Data Tests.
+ {
+ ASSERT_EQ(Data.size(), 2u);
+
+ // Build entity resolution mappings for each TU.
+ std::map<EntityId, EntityId> TU1Resolution = {
+ {TU1_X_Id, LU_TU1_X_Id}, {TU1_Y_Id, LU_TU1_Y_Id},
+ {TU1_Z_Id, LU_TU1_Z_Id}, {TU1_A_Id, LU_TU1_A_Id},
+ {TU1_B_Id, LU_TU1_B_Id}, {TU1_C_Id, LU_TU1_C_Id},
+ {TU1_P_Id, LU_P_Id}, {TU1_Q_Id, LU_Q_Id},
+ {TU1_R_Id, LU_R_Id}};
+
+ std::map<EntityId, EntityId> TU2Resolution = {
+ {TU2_X_Id, LU_TU2_X_Id}, {TU2_Y_Id, LU_TU2_Y_Id},
+ {TU2_W_Id, LU_TU2_W_Id}, {TU2_A_Id, LU_TU2_A_Id},
+ {TU2_B_Id, LU_TU2_B_Id}, {TU2_D_Id, LU_TU2_D_Id},
+ {TU2_P_Id, LU_P_Id}, {TU2_Q_Id, LU_Q_Id},
+ {TU2_R_Id, LU_R_Id}, {TU2_S_Id, LU_S_Id}};
+
+ // S1 Data Tests.
+ {
+ SummaryName S1("S1");
+ ASSERT_NE(Data.find(S1), Data.end());
+ const auto &S1Data = Data.at(S1);
+
+ // S1 should contain: TU1(X,Z,A,C,P,R) + TU2(Y,W,B,D,Q,S) = 12 entities.
+ ASSERT_THAT(S1Data, SummaryDataHasSize(12u));
+
+ // TU1 entities in S1.
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_TU1_X_Id, TU1_X_S1_Data, TU1Resolution));
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_TU1_Z_Id, TU1_Z_S1_Data, TU1Resolution));
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_TU1_A_Id, TU1_A_S1_Data, TU1Resolution));
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_TU1_C_Id, TU1_C_S1_Data, TU1Resolution));
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_P_Id, TU1_P_S1_Data, TU1Resolution));
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_R_Id, TU1_R_S1_Data, TU1Resolution));
+
+ // TU2 entities in S1.
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_TU2_Y_Id, TU2_Y_S1_Data, TU2Resolution));
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_TU2_W_Id, TU2_W_S1_Data, TU2Resolution));
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_TU2_B_Id, TU2_B_S1_Data, TU2Resolution));
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_TU2_D_Id, TU2_D_S1_Data, TU2Resolution));
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_Q_Id, TU2_Q_S1_Data, TU2Resolution));
+ ASSERT_THAT(S1Data,
+ Not(HasSummaryData(LU_R_Id, TU2_R_S1_Data, TU2Resolution)));
+ ASSERT_THAT(S1Data,
+ HasSummaryData(LU_S_Id, TU2_S_S1_Data, TU2Resolution));
+ }
+
+ // S2 Data Tests.
+ {
+ SummaryName S2("S2");
+ ASSERT_NE(Data.find(S2), Data.end());
+ const auto &S2Data = Data.at(S2);
+
+ // S2 should contain: TU1(Y,Z,B,C,Q,R) + TU2(X,W,A,D,P,S) = 12 entities.
+ ASSERT_THAT(S2Data, SummaryDataHasSize(12u));
+
+ // TU1 entities in S2.
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_TU1_Y_Id, TU1_Y_S2_Data, TU1Resolution));
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_TU1_Z_Id, TU1_Z_S2_Data, TU1Resolution));
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_TU1_B_Id, TU1_B_S2_Data, TU1Resolution));
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_TU1_C_Id, TU1_C_S2_Data, TU1Resolution));
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_Q_Id, TU1_Q_S2_Data, TU1Resolution));
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_R_Id, TU1_R_S2_Data, TU1Resolution));
+
+ // TU2 entities in S2.
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_TU2_X_Id, TU2_X_S2_Data, TU2Resolution));
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_TU2_W_Id, TU2_W_S2_Data, TU2Resolution));
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_TU2_A_Id, TU2_A_S2_Data, TU2Resolution));
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_TU2_D_Id, TU2_D_S2_Data, TU2Resolution));
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_P_Id, TU2_P_S2_Data, TU2Resolution));
+ ASSERT_THAT(S2Data,
+ Not(HasSummaryData(LU_R_Id, TU2_R_S2_Data, TU2Resolution)));
+ ASSERT_THAT(S2Data,
+ HasSummaryData(LU_S_Id, TU2_S_S2_Data, TU2Resolution));
+ }
+ }
+}
+
+TEST_F(EntityLinkerTest, RejectsDuplicateTUSummary) {
+ NestedBuildNamespace LUNamespace(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "LU")});
+
+ EntityLinker Linker(llvm::Triple("arm64-apple-macosx"), LUNamespace);
+
+ auto TU1 = createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TU");
+
+ ASSERT_THAT_ERROR(Linker.link(std::move(TU1)), llvm::Succeeded());
+
+ auto TU2 = createTUSummaryEncoding(BuildNamespaceKind::CompilationUnit, "TU");
+
+ ASSERT_THAT_ERROR(Linker.link(std::move(TU2)),
+ llvm::FailedWithMessage(
+ HasSubstr("failed to link TU summary: duplicate "
+ "BuildNamespace(CompilationUnit, TU)")));
+}
+
+// Reproduces a crash when linking internal-linkage entities
+// (e.g. "static inline" functions) that share the same USR across TUs.
+TEST_F(EntityLinkerTest, InternalLinkageWithEmptyNamespaceAcrossTUs) {
+ constexpr auto LinkUnit = BuildNamespaceKind::LinkUnit;
+ constexpr auto CompilationUnit = BuildNamespaceKind::CompilationUnit;
+ EntityLinker Linker(llvm::Triple("arm64-apple-macosx"),
+ NestedBuildNamespace{BuildNamespace(LinkUnit, "LU")});
+
+ auto TU1 = createTUSummaryEncoding(CompilationUnit, "TU1");
+ addEntity(*TU1, "some_static_inline", InternalLinkage);
+ ASSERT_THAT_ERROR(Linker.link(std::move(TU1)), llvm::Succeeded());
+
+ auto TU2 = createTUSummaryEncoding(CompilationUnit, "TU2");
+ addEntity(*TU2, "some_static_inline", InternalLinkage);
+ ASSERT_THAT_ERROR(Linker.link(std::move(TU2)), llvm::Succeeded());
+
+ // Check that the two internal symbols are not merged.
+ const auto Output = std::move(Linker).takeOutput();
+ const auto &IdTable = getIdTable(Output);
+
+ NestedBuildNamespace TU1NS{{{CompilationUnit, "TU1"}, {LinkUnit, "LU"}}};
+ NestedBuildNamespace TU2NS{{{CompilationUnit, "TU2"}, {LinkUnit, "LU"}}};
+ EntityName ExpectedTU1Name("some_static_inline", "", TU1NS);
+ EntityName ExpectedTU2Name("some_static_inline", "", TU2NS);
+
+ ASSERT_EQ(IdTable.count(), 2u);
+ EXPECT_THAT(IdTable, ContainsEntity(ExpectedTU1Name));
+ EXPECT_THAT(IdTable, ContainsEntity(ExpectedTU2Name));
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/EntityNameTest.cpp b/clang/unittests/ScalableStaticAnalysis/EntityNameTest.cpp
new file mode 100644
index 0000000000000..698b17efb6384
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/EntityNameTest.cpp
@@ -0,0 +1,95 @@
+//===- EntityNameTest.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+namespace clang::ssaf {
+namespace {
+
+TEST(EntityNameTest, Equality) {
+ auto NBN1 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ auto NBN2 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
+
+ EntityName EN1("c:@F at foo", "", NBN1);
+ EntityName EN2("c:@F at foo", "", NBN2);
+ EntityName EN3("c:@F at bar", "", NBN1);
+
+ EXPECT_EQ(EN1, EN2);
+ EXPECT_NE(EN1, EN3);
+}
+
+TEST(EntityNameTest, EqualityWithDifferentSuffix) {
+ auto NBN = NestedBuildNamespace::makeCompilationUnit("test.cpp");
+
+ EntityName EN1("c:@F at foo", "1", NBN);
+ EntityName EN2("c:@F at foo", "2", NBN);
+
+ EXPECT_NE(EN1, EN2);
+}
+
+TEST(EntityNameTest, EqualityWithDifferentNamespace) {
+ auto NBN1 = NestedBuildNamespace::makeCompilationUnit("test1.cpp");
+ auto NBN2 = NestedBuildNamespace::makeCompilationUnit("test2.cpp");
+
+ EntityName EN1("c:@F at foo", "", NBN1);
+ EntityName EN2("c:@F at foo", "", NBN2);
+
+ EXPECT_NE(EN1, EN2);
+}
+
+TEST(EntityNameTest, MakeQualified) {
+ auto NBN1 = NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ EntityName EN("c:@F at foo", "", NBN1);
+
+ BuildNamespace LinkNS(BuildNamespaceKind::LinkUnit, "app");
+ NestedBuildNamespace NBN2(LinkNS);
+
+ auto Qualified = EN.makeQualified(NBN2);
+
+ EXPECT_NE(Qualified, EN);
+}
+
+TEST(EntityNameTest, FormatProvider) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
+ EntityName EN("c:@F at foo", "", NBN);
+ EXPECT_EQ(
+ llvm::formatv("{0}", EN).str(),
+ "EntityName(c:@F at foo, , "
+ "NestedBuildNamespace([BuildNamespace(CompilationUnit, test.cpp)]))");
+}
+
+TEST(EntityNameTest, StreamOutputNoSuffix) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
+ EntityName EN("c:@F at foo", "", NBN);
+ std::string S;
+ llvm::raw_string_ostream(S) << EN;
+ EXPECT_EQ(
+ S, "EntityName(c:@F at foo, , "
+ "NestedBuildNamespace([BuildNamespace(CompilationUnit, test.cpp)]))");
+}
+
+TEST(EntityNameTest, StreamOutputWithSuffix) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
+ EntityName EN("c:@F at foo", "1", NBN);
+ std::string S;
+ llvm::raw_string_ostream(S) << EN;
+ EXPECT_EQ(
+ S, "EntityName(c:@F at foo, 1, "
+ "NestedBuildNamespace([BuildNamespace(CompilationUnit, test.cpp)]))");
+}
+
+} // namespace
+} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysis/ErrorBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysis/ErrorBuilderTest.cpp
new file mode 100644
index 0000000000000..5a5b74f82ae0f
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/ErrorBuilderTest.cpp
@@ -0,0 +1,196 @@
+//===- ErrorBuilderTest.cpp -----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Support/ErrorBuilder.h"
+#include "gtest/gtest.h"
+#include <system_error>
+
+using namespace llvm;
+
+namespace clang::ssaf {
+
+namespace {
+
+class ErrorBuilderTest : public ::testing::Test {
+protected:
+ struct ErrorInfo {
+ std::error_code Code;
+ std::string Message;
+ };
+
+ ErrorInfo extractErrorInfo(Error Err) {
+ ErrorInfo Info;
+
+ handleAllErrors(std::move(Err), [&](const StringError &SE) {
+ Info.Code = SE.convertToErrorCode();
+ Info.Message = SE.getMessage();
+ });
+
+ return Info;
+ }
+};
+
+TEST_F(ErrorBuilderTest, CreatesSimpleError) {
+ auto Err =
+ ErrorBuilder::create(std::errc::invalid_argument, "test error").build();
+
+ auto Info = extractErrorInfo(std::move(Err));
+
+ EXPECT_EQ(Info.Code, std::errc::invalid_argument);
+ EXPECT_EQ(Info.Message, "test error");
+}
+
+TEST_F(ErrorBuilderTest, CreatesErrorWithErrorCode) {
+ auto EC = std::make_error_code(std::errc::no_such_file_or_directory);
+ auto Err = ErrorBuilder::create(EC, "file not found").build();
+
+ auto Info = extractErrorInfo(std::move(Err));
+
+ EXPECT_EQ(Info.Code, std::errc::no_such_file_or_directory);
+ EXPECT_EQ(Info.Message, "file not found");
+}
+
+TEST_F(ErrorBuilderTest, CreatesErrorWithFormattedMessage) {
+ auto Err = ErrorBuilder::create(std::errc::invalid_argument,
+ "field '{0}' has value {1}", "age", 150)
+ .build();
+
+ auto Info = extractErrorInfo(std::move(Err));
+
+ EXPECT_EQ(Info.Code, std::errc::invalid_argument);
+ EXPECT_EQ(Info.Message, "field 'age' has value 150");
+}
+
+TEST_F(ErrorBuilderTest, AddsPlainContext) {
+ auto Err = ErrorBuilder::create(std::errc::invalid_argument, "inner error")
+ .context("outer context")
+ .build();
+
+ auto Info = extractErrorInfo(std::move(Err));
+
+ EXPECT_EQ(Info.Code, std::errc::invalid_argument);
+ EXPECT_EQ(Info.Message, "outer context\ninner error");
+}
+
+TEST_F(ErrorBuilderTest, AddsMultipleContextLayers) {
+ auto Err = ErrorBuilder::create(std::errc::invalid_argument,
+ "expected {0} but got {1} in field '{2}'",
+ "string", "number", "value")
+ .context("parsing line {0}", 42)
+ .context("reading file '{0}'", "config.json")
+ .build();
+
+ auto Info = extractErrorInfo(std::move(Err));
+
+ EXPECT_EQ(Info.Code, std::errc::invalid_argument);
+ EXPECT_EQ(Info.Message, "reading file 'config.json'\n"
+ "parsing line 42\n"
+ "expected string but got number in field 'value'");
+}
+
+TEST_F(ErrorBuilderTest, HandlesSpecialCharactersInContext) {
+ auto Err = ErrorBuilder::create(std::errc::invalid_argument,
+ "special chars: {0}", "test\nwith\nnewlines")
+ .context("tab\tseparated\tvalues")
+ .build();
+
+ auto Info = extractErrorInfo(std::move(Err));
+
+ EXPECT_EQ(Info.Code, std::errc::invalid_argument);
+ EXPECT_EQ(Info.Message, "tab\tseparated\tvalues\n"
+ "special chars: test\n"
+ "with\n"
+ "newlines");
+}
+
+TEST_F(ErrorBuilderTest, WrapsExistingError) {
+ auto OriginalErr =
+ createStringError(std::errc::invalid_argument, "original error message");
+
+ auto WrappedErr = ErrorBuilder::wrap(std::move(OriginalErr))
+ .context("additional context")
+ .build();
+
+ auto Info = extractErrorInfo(std::move(WrappedErr));
+
+ EXPECT_EQ(Info.Code, std::errc::invalid_argument);
+ EXPECT_EQ(Info.Message, "additional context\noriginal error message");
+}
+
+TEST_F(ErrorBuilderTest, WrapsMultipleJoinedErrors) {
+ auto Err1 = createStringError(std::errc::invalid_argument, "first");
+ auto Err2 = createStringError(std::errc::argument_list_too_long, "second");
+ auto Err3 = createStringError(std::errc::filename_too_long, "third");
+
+ auto JoinedErr =
+ joinErrors(std::move(Err1), joinErrors(std::move(Err2), std::move(Err3)));
+
+ auto WrappedErr = ErrorBuilder::wrap(std::move(JoinedErr))
+ .context("wrapping three joined errors")
+ .build();
+
+ auto Info = extractErrorInfo(std::move(WrappedErr));
+
+ EXPECT_EQ(Info.Code, std::errc::invalid_argument);
+ // All three messages combined with " + " in the order they were handled
+ EXPECT_EQ(Info.Message,
+ "wrapping three joined errors\nfirst + second + third");
+}
+
+TEST_F(ErrorBuilderTest, WrapsErrorWithEmptyMessage) {
+ auto EmptyErr = createStringError(std::errc::invalid_argument, "");
+
+ auto WrappedErr = ErrorBuilder::wrap(std::move(EmptyErr))
+ .context("")
+ .context("wrapping error with empty message")
+ .context("")
+ .build();
+
+ auto Info = extractErrorInfo(std::move(WrappedErr));
+
+ EXPECT_EQ(Info.Code, std::errc::invalid_argument);
+ EXPECT_EQ(Info.Message, "wrapping error with empty message");
+}
+
+TEST_F(ErrorBuilderTest, CreatesErrorWithEmptyMessage) {
+ auto Err = ErrorBuilder::create(std::errc::invalid_argument, "")
+ .context("")
+ .context("creating error with empty message")
+ .context("")
+ .build();
+
+ auto Info = extractErrorInfo(std::move(Err));
+
+ EXPECT_EQ(Info.Code, std::errc::invalid_argument);
+ EXPECT_EQ(Info.Message, "creating error with empty message");
+}
+
+#ifndef NDEBUG
+// Death test only works in debug builds where assertions are enabled
+TEST_F(ErrorBuilderTest, TriggersAssertionOnWrappingSuccessError) {
+ EXPECT_DEATH(
+ {
+ auto SuccessErr = Error::success();
+ ErrorBuilder::wrap(std::move(SuccessErr));
+ },
+ "Cannot wrap a success error - check for success before calling wrap");
+}
+#endif // !NDEBUG
+
+TEST_F(ErrorBuilderTest, FatalTerminatesExecution) {
+ EXPECT_DEATH(
+ {
+ ErrorBuilder::fatal("Entity {0} with {1} linkage already exists", 42,
+ "Internal");
+ },
+ "Entity 42 with Internal linkage already exists");
+}
+
+} // namespace
+
+} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysis/FindDecl.h b/clang/unittests/ScalableStaticAnalysis/FindDecl.h
new file mode 100644
index 0000000000000..65dee7f741287
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/FindDecl.h
@@ -0,0 +1,53 @@
+//===- FindDecl.h -----------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_FINDDECL_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_FINDDECL_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DynamicRecursiveASTVisitor.h"
+
+namespace clang::ssaf {
+
+template <typename SomeDecl = clang::NamedDecl>
+const SomeDecl *findDeclByName(StringRef Name, ASTContext &Ctx) {
+ class NamedDeclFinder : public DynamicRecursiveASTVisitor {
+ public:
+ StringRef SearchingName;
+ const NamedDecl *FoundDecl = nullptr;
+
+ NamedDeclFinder(StringRef SearchingName) : SearchingName(SearchingName) {
+ ShouldVisitTemplateInstantiations = true;
+ }
+
+ bool VisitDecl(Decl *D) override {
+ if (D->isTemplated())
+ return true;
+ if (const auto *ND = dyn_cast<SomeDecl>(D)) {
+ if (ND->getNameAsString() == SearchingName) {
+ FoundDecl = ND;
+ return false;
+ }
+ }
+ return true;
+ }
+ };
+
+ NamedDeclFinder Finder(Name);
+
+ Finder.TraverseDecl(Ctx.getTranslationUnitDecl());
+ return dyn_cast_or_null<SomeDecl>(Finder.FoundDecl);
+}
+
+inline const FunctionDecl *findFnByName(StringRef Name, ASTContext &Ctx) {
+ return findDeclByName<FunctionDecl>(Name, Ctx);
+}
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_FINDDECL_H
diff --git a/clang/unittests/ScalableStaticAnalysis/LUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysis/LUSummaryTest.cpp
new file mode 100644
index 0000000000000..b67859e09c66d
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/LUSummaryTest.cpp
@@ -0,0 +1,25 @@
+//===- LUSummaryTest.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "gtest/gtest.h"
+
+namespace clang::ssaf {
+namespace {
+
+TEST(LUSummaryTest, GetNamespace) {
+ BuildNamespace LU(BuildNamespaceKind::LinkUnit, "app");
+ NestedBuildNamespace NS(LU);
+ LUSummary Summary(llvm::Triple("arm64-apple-macosx"), NS);
+
+ EXPECT_EQ(Summary.getNamespace(), NS);
+}
+
+} // namespace
+} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysis/ModelStringConversionsTest.cpp b/clang/unittests/ScalableStaticAnalysis/ModelStringConversionsTest.cpp
new file mode 100644
index 0000000000000..ff24a8358612d
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/ModelStringConversionsTest.cpp
@@ -0,0 +1,106 @@
+//===- ModelStringConversionsTest.cpp -------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../../lib/ScalableStaticAnalysis/Core/ModelStringConversions.h"
+#include "gtest/gtest.h"
+
+using namespace clang::ssaf;
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+// BuildNamespaceKind
+//===----------------------------------------------------------------------===//
+
+TEST(BuildNamespaceKindStringTest, ToStringCompilationUnit) {
+ EXPECT_EQ(buildNamespaceKindToString(BuildNamespaceKind::CompilationUnit),
+ "CompilationUnit");
+}
+
+TEST(BuildNamespaceKindStringTest, ToStringLinkUnit) {
+ EXPECT_EQ(buildNamespaceKindToString(BuildNamespaceKind::LinkUnit),
+ "LinkUnit");
+}
+
+TEST(BuildNamespaceKindStringTest, FromStringCompilationUnit) {
+ EXPECT_EQ(buildNamespaceKindFromString("CompilationUnit"),
+ BuildNamespaceKind::CompilationUnit);
+}
+
+TEST(BuildNamespaceKindStringTest, FromStringLinkUnit) {
+ EXPECT_EQ(buildNamespaceKindFromString("LinkUnit"),
+ BuildNamespaceKind::LinkUnit);
+}
+
+TEST(BuildNamespaceKindStringTest, FromStringUnknown) {
+ EXPECT_EQ(buildNamespaceKindFromString("compilation_unit"), std::nullopt);
+ EXPECT_EQ(buildNamespaceKindFromString("link_unit"), std::nullopt);
+ EXPECT_EQ(buildNamespaceKindFromString(""), std::nullopt);
+ EXPECT_EQ(buildNamespaceKindFromString("unknown"), std::nullopt);
+}
+
+TEST(BuildNamespaceKindStringTest, RoundTrip) {
+ EXPECT_EQ(buildNamespaceKindFromString(buildNamespaceKindToString(
+ BuildNamespaceKind::CompilationUnit)),
+ BuildNamespaceKind::CompilationUnit);
+ EXPECT_EQ(buildNamespaceKindFromString(
+ buildNamespaceKindToString(BuildNamespaceKind::LinkUnit)),
+ BuildNamespaceKind::LinkUnit);
+}
+
+//===----------------------------------------------------------------------===//
+// EntityLinkageType
+//===----------------------------------------------------------------------===//
+
+TEST(EntityLinkageTypeStringTest, ToStringNone) {
+ EXPECT_EQ(entityLinkageTypeToString(EntityLinkageType::None), "None");
+}
+
+TEST(EntityLinkageTypeStringTest, ToStringInternal) {
+ EXPECT_EQ(entityLinkageTypeToString(EntityLinkageType::Internal), "Internal");
+}
+
+TEST(EntityLinkageTypeStringTest, ToStringExternal) {
+ EXPECT_EQ(entityLinkageTypeToString(EntityLinkageType::External), "External");
+}
+
+TEST(EntityLinkageTypeStringTest, FromStringNone) {
+ EXPECT_EQ(entityLinkageTypeFromString("None"), EntityLinkageType::None);
+}
+
+TEST(EntityLinkageTypeStringTest, FromStringInternal) {
+ EXPECT_EQ(entityLinkageTypeFromString("Internal"),
+ EntityLinkageType::Internal);
+}
+
+TEST(EntityLinkageTypeStringTest, FromStringExternal) {
+ EXPECT_EQ(entityLinkageTypeFromString("External"),
+ EntityLinkageType::External);
+}
+
+TEST(EntityLinkageTypeStringTest, FromStringUnknown) {
+ EXPECT_EQ(entityLinkageTypeFromString("none"), std::nullopt);
+ EXPECT_EQ(entityLinkageTypeFromString("internal"), std::nullopt);
+ EXPECT_EQ(entityLinkageTypeFromString("external"), std::nullopt);
+ EXPECT_EQ(entityLinkageTypeFromString(""), std::nullopt);
+ EXPECT_EQ(entityLinkageTypeFromString("unknown"), std::nullopt);
+}
+
+TEST(EntityLinkageTypeStringTest, RoundTrip) {
+ EXPECT_EQ(entityLinkageTypeFromString(
+ entityLinkageTypeToString(EntityLinkageType::None)),
+ EntityLinkageType::None);
+ EXPECT_EQ(entityLinkageTypeFromString(
+ entityLinkageTypeToString(EntityLinkageType::Internal)),
+ EntityLinkageType::Internal);
+ EXPECT_EQ(entityLinkageTypeFromString(
+ entityLinkageTypeToString(EntityLinkageType::External)),
+ EntityLinkageType::External);
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/FancyAnalysisData.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/FancyAnalysisData.cpp
new file mode 100644
index 0000000000000..5f078e6d23ce5
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/FancyAnalysisData.cpp
@@ -0,0 +1,60 @@
+//===- FancyAnalysisData.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Registries/MockSerializationFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Registry.h"
+
+using namespace clang;
+using namespace ssaf;
+
+using SpecialFileRepresentation =
+ MockSerializationFormat::SpecialFileRepresentation;
+
+namespace {
+struct FancyAnalysisData final : EntitySummary {
+ SummaryName getSummaryName() const override {
+ return SummaryName("FancyAnalysis");
+ }
+
+ std::string Text;
+};
+} // namespace
+
+static SpecialFileRepresentation
+serializeFancyAnalysis(const EntitySummary &Data,
+ MockSerializationFormat &Format) {
+ const auto &FancyAnalysis = static_cast<const FancyAnalysisData &>(Data);
+ return SpecialFileRepresentation{/*MockRepresentation=*/FancyAnalysis.Text};
+}
+
+static std::unique_ptr<EntitySummary>
+deserializeFancyAnalysis(const SpecialFileRepresentation &File,
+ EntityIdTable &) {
+ auto Result = std::make_unique<FancyAnalysisData>();
+ Result->Text = File.MockRepresentation;
+ return std::move(Result);
+}
+
+namespace {
+using FormatInfo = MockSerializationFormat::FormatInfo;
+struct FancyAnalysisFormatInfo final : FormatInfo {
+ FancyAnalysisFormatInfo()
+ : FormatInfo{
+ SummaryName("FancyAnalysis"),
+ serializeFancyAnalysis,
+ deserializeFancyAnalysis,
+ } {}
+};
+} // namespace
+
+static llvm::Registry<FormatInfo>::Add<FancyAnalysisFormatInfo>
+ RegisterFormatInfo("FancyAnalysisData",
+ "Format info for FancyAnalysisData for the "
+ "MockSerializationFormat format");
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.cpp
new file mode 100644
index 0000000000000..915fe15af832c
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.cpp
@@ -0,0 +1,232 @@
+//===- MockSerializationFormat.cpp ----------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Registries/MockSerializationFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <functional>
+#include <memory>
+#include <set>
+
+using namespace clang;
+using namespace ssaf;
+
+LLVM_DEFINE_REGISTRY(llvm::Registry<MockSerializationFormat::FormatInfo>)
+
+MockSerializationFormat::MockSerializationFormat() {
+ for (const auto &FormatInfoEntry : llvm::Registry<FormatInfo>::entries()) {
+ std::unique_ptr<FormatInfo> Info = FormatInfoEntry.instantiate();
+ bool Inserted = FormatInfos.try_emplace(Info->ForSummary, *Info).second;
+ if (!Inserted) {
+ llvm::report_fatal_error(
+ "Format info was already registered for summary name: " +
+ Info->ForSummary.str());
+ }
+ }
+}
+
+void MockSerializationFormat::forEachRegisteredAnalysis(
+ llvm::function_ref<void(llvm::StringRef, llvm::StringRef)> Callback) const {
+ for (const auto &Entry : llvm::Registry<FormatInfo>::entries())
+ Callback(Entry.getName(), Entry.getDesc());
+}
+
+llvm::Expected<TUSummary>
+MockSerializationFormat::readTUSummary(llvm::StringRef Path) {
+ BuildNamespace NS(BuildNamespaceKind::CompilationUnit, "Mock.cpp");
+ TUSummary Summary(llvm::Triple("arm64-apple-macosx"), NS);
+
+ auto ManifestFile = llvm::MemoryBuffer::getFile(Path + "/analyses.txt");
+ if (!ManifestFile) {
+ return llvm::createStringError(ManifestFile.getError(),
+ "Failed to read manifest file");
+ }
+ llvm::StringRef ManifestFileContent = (*ManifestFile)->getBuffer();
+
+ llvm::SmallVector<llvm::StringRef, 5> Analyses;
+ ManifestFileContent.split(Analyses, /*Separator=*/"\n", /*MaxSplit=*/-1,
+ /*KeepEmpty=*/false);
+
+ for (llvm::StringRef Analysis : Analyses) {
+ SummaryName Name(Analysis.str());
+ auto InputFile =
+ llvm::MemoryBuffer::getFile(Path + "/" + Name.str() + ".special");
+ if (!InputFile) {
+ return llvm::createStringError(InputFile.getError(),
+ "Failed to read analysis file");
+ }
+ auto InfoIt = FormatInfos.find(Name);
+ if (InfoIt == FormatInfos.end()) {
+ return llvm::createStringError(
+ std::make_error_code(std::errc::invalid_argument),
+ "No FormatInfo was registered for summary name: " + Name.str());
+ }
+ const auto &InfoEntry = InfoIt->second;
+ assert(InfoEntry.ForSummary == Name);
+
+ SpecialFileRepresentation Repr{(*InputFile)->getBuffer().str()};
+ auto &Table = getIdTable(Summary);
+
+ std::unique_ptr<EntitySummary> Result = InfoEntry.Deserialize(Repr, Table);
+ if (!Result) {
+ return llvm::createStringError(
+ std::make_error_code(std::errc::invalid_argument),
+ "Failed to deserialize EntitySummary for analysis: " + Name.str());
+ }
+
+ EntityId FooId = Table.getId(EntityName{"c:@F at foo", "", /*Namespace=*/{}});
+ auto &IdMappings = getData(Summary).try_emplace(Name).first->second;
+ [[maybe_unused]] bool Inserted =
+ IdMappings.try_emplace(FooId, std::move(Result)).second;
+ assert(Inserted);
+ }
+
+ return std::move(Summary);
+}
+
+llvm::Error MockSerializationFormat::writeTUSummary(const TUSummary &Summary,
+ llvm::StringRef Path) {
+ std::error_code EC;
+
+ // Check if output directory exists, create if needed
+ if (!llvm::sys::fs::exists(Path)) {
+ EC = llvm::sys::fs::create_directories(Path);
+ if (EC) {
+ return llvm::createStringError(EC, "Failed to create output directory '" +
+ Path + "': " + EC.message());
+ }
+ }
+
+ std::set<SummaryName> Analyses;
+ for (const auto &[SummaryName, EntityMappings] : getData(Summary)) {
+ [[maybe_unused]] bool Inserted = Analyses.insert(SummaryName).second;
+ assert(Inserted);
+ for (const auto &Data : llvm::make_second_range(EntityMappings)) {
+ auto InfoIt = FormatInfos.find(SummaryName);
+ if (InfoIt == FormatInfos.end()) {
+ return llvm::createStringError(
+ std::make_error_code(std::errc::invalid_argument),
+ "There was no FormatInfo registered for summary name '" +
+ SummaryName.str() + "'");
+ }
+ const auto &InfoEntry = InfoIt->second;
+ assert(InfoEntry.ForSummary == SummaryName);
+
+ auto Output = InfoEntry.Serialize(*Data, *this);
+
+ std::string AnalysisFilePath =
+ (Path + "/" + SummaryName.str() + ".special").str();
+ llvm::raw_fd_ostream AnalysisOutputFile(AnalysisFilePath, EC);
+ if (EC) {
+ return llvm::createStringError(
+ EC, "Failed to create file '" + AnalysisFilePath +
+ "': " + llvm::StringRef(EC.message()));
+ }
+ AnalysisOutputFile << Output.MockRepresentation;
+ }
+ }
+
+ std::string ManifestFilePath = (Path + "/analyses.txt").str();
+ llvm::raw_fd_ostream ManifestFile(ManifestFilePath, EC);
+ if (EC) {
+ return llvm::createStringError(
+ EC, "Failed to create manifest file '" + ManifestFilePath +
+ "': " + llvm::StringRef(EC.message()));
+ }
+
+ interleave(map_range(Analyses, std::mem_fn(&SummaryName::str)), ManifestFile,
+ "\n");
+ ManifestFile << "\n";
+
+ return llvm::Error::success();
+}
+
+static SerializationFormatRegistry::Add<MockSerializationFormat>
+ RegisterFormat("MockSerializationFormat",
+ "A serialization format for testing");
+
+llvm::Expected<TUSummaryEncoding>
+MockSerializationFormat::readTUSummaryEncoding(llvm::StringRef Path) {
+ llvm_unreachable(
+ "MockSerializationFormat does not support TUSummaryEncoding");
+}
+
+llvm::Error MockSerializationFormat::writeTUSummaryEncoding(
+ const TUSummaryEncoding &SummaryEncoding, llvm::StringRef Path) {
+ llvm_unreachable(
+ "MockSerializationFormat does not support TUSummaryEncoding");
+}
+
+llvm::Expected<LUSummary>
+MockSerializationFormat::readLUSummary(llvm::StringRef Path) {
+ llvm_unreachable("MockSerializationFormat does not support LUSummary");
+}
+
+llvm::Error MockSerializationFormat::writeLUSummary(const LUSummary &Summary,
+ llvm::StringRef Path) {
+ llvm_unreachable("MockSerializationFormat does not support LUSummary");
+}
+
+llvm::Expected<LUSummaryEncoding>
+MockSerializationFormat::readLUSummaryEncoding(llvm::StringRef Path) {
+ llvm_unreachable(
+ "MockSerializationFormat does not support LUSummaryEncoding");
+}
+
+llvm::Error MockSerializationFormat::writeLUSummaryEncoding(
+ const LUSummaryEncoding &SummaryEncoding, llvm::StringRef Path) {
+ llvm_unreachable(
+ "MockSerializationFormat does not support LUSummaryEncoding");
+}
+
+llvm::Expected<WPASuite>
+MockSerializationFormat::readWPASuite(llvm::StringRef Path) {
+ llvm_unreachable("MockSerializationFormat does not support WPASuite");
+}
+
+llvm::Error MockSerializationFormat::writeWPASuite(const WPASuite &Suite,
+ llvm::StringRef Path) {
+ llvm_unreachable("MockSerializationFormat does not support WPASuite");
+}
+
+llvm::Expected<Artifact>
+MockSerializationFormat::readArtifact(llvm::StringRef Path) {
+ llvm_unreachable("MockSerializationFormat does not support readArtifact");
+}
+
+llvm::Error MockSerializationFormat::writeArtifact(const Artifact &A,
+ llvm::StringRef Path) {
+ llvm_unreachable("MockSerializationFormat does not support writeArtifact");
+}
+
+llvm::Expected<ArtifactEncoding>
+MockSerializationFormat::readArtifactEncoding(llvm::StringRef Path) {
+ llvm_unreachable(
+ "MockSerializationFormat does not support readArtifactEncoding");
+}
+
+llvm::Error
+MockSerializationFormat::writeArtifactEncoding(const ArtifactEncoding &E,
+ llvm::StringRef Path) {
+ llvm_unreachable(
+ "MockSerializationFormat does not support writeArtifactEncoding");
+}
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.h b/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.h
new file mode 100644
index 0000000000000..2ecaab9fb0132
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/MockSerializationFormat.h
@@ -0,0 +1,85 @@
+//===- MockSerializationFormat.h --------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
+
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormat.h"
+#include "clang/Support/Compiler.h"
+#include "llvm/ADT/STLFunctionalExtras.h"
+#include "llvm/Support/Registry.h"
+#include <string>
+
+namespace clang::ssaf {
+
+class MockSerializationFormat final : public SerializationFormat {
+public:
+ MockSerializationFormat();
+
+ llvm::Expected<TUSummary> readTUSummary(llvm::StringRef Path) override;
+
+ llvm::Error writeTUSummary(const TUSummary &Summary,
+ llvm::StringRef Path) override;
+
+ llvm::Expected<TUSummaryEncoding>
+ readTUSummaryEncoding(llvm::StringRef Path) override;
+
+ llvm::Error writeTUSummaryEncoding(const TUSummaryEncoding &SummaryEncoding,
+ llvm::StringRef Path) override;
+
+ llvm::Expected<LUSummary> readLUSummary(llvm::StringRef Path) override;
+
+ llvm::Error writeLUSummary(const LUSummary &Summary,
+ llvm::StringRef Path) override;
+
+ llvm::Expected<LUSummaryEncoding>
+ readLUSummaryEncoding(llvm::StringRef Path) override;
+
+ llvm::Error writeLUSummaryEncoding(const LUSummaryEncoding &SummaryEncoding,
+ llvm::StringRef Path) override;
+
+ llvm::Expected<Artifact> readArtifact(llvm::StringRef Path) override;
+
+ llvm::Error writeArtifact(const Artifact &A, llvm::StringRef Path) override;
+
+ llvm::Expected<ArtifactEncoding>
+ readArtifactEncoding(llvm::StringRef Path) override;
+
+ llvm::Error writeArtifactEncoding(const ArtifactEncoding &E,
+ llvm::StringRef Path) override;
+
+ llvm::Expected<WPASuite> readWPASuite(llvm::StringRef Path) override;
+
+ llvm::Error writeWPASuite(const WPASuite &Suite,
+ llvm::StringRef Path) override;
+
+ /// Lists what analyses implement this particular serialisation format.
+ void forEachRegisteredAnalysis(
+ llvm::function_ref<void(llvm::StringRef Name, llvm::StringRef Desc)>
+ Callback) const override;
+
+ struct SpecialFileRepresentation {
+ std::string MockRepresentation;
+ };
+
+ using SerializerFn = llvm::function_ref<SpecialFileRepresentation(
+ const EntitySummary &, MockSerializationFormat &)>;
+ using DeserializerFn = llvm::function_ref<std::unique_ptr<EntitySummary>(
+ const SpecialFileRepresentation &, EntityIdTable &)>;
+
+ using FormatInfo = FormatInfoEntry<SerializerFn, DeserializerFn>;
+ std::map<SummaryName, FormatInfo> FormatInfos;
+};
+
+} // namespace clang::ssaf
+
+LLVM_DECLARE_REGISTRY(
+ llvm::Registry<clang::ssaf::MockSerializationFormat::FormatInfo>)
+
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKSERIALIZATIONFORMAT_H
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor1.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor1.cpp
new file mode 100644
index 0000000000000..2ff32394ae42b
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor1.cpp
@@ -0,0 +1,44 @@
+//===- MockSummaryExtractor1.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MockTUSummaryBuilder.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+class MockSummaryExtractor1 : public TUSummaryExtractor {
+public:
+ MockSummaryExtractor1(TUSummaryBuilder &Builder)
+ : TUSummaryExtractor(Builder) {
+ getFakeBuilder().sendMessage(
+ "MockSummaryExtractor1 constructor was invoked");
+ }
+
+ ~MockSummaryExtractor1() {
+ getFakeBuilder().sendMessage(
+ "MockSummaryExtractor1 destructor was invoked");
+ }
+
+ void HandleTranslationUnit(ASTContext &Ctx) override {
+ getFakeBuilder().sendMessage(
+ "MockSummaryExtractor1 HandleTranslationUnit was invoked");
+ }
+
+ MockTUSummaryBuilder &getFakeBuilder() {
+ return static_cast<MockTUSummaryBuilder &>(SummaryBuilder);
+ }
+};
+
+} // namespace
+
+static TUSummaryExtractorRegistry::Add<MockSummaryExtractor1>
+ RegisterExtractor("MockSummaryExtractor1", "Mock summary extractor 1");
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor2.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor2.cpp
new file mode 100644
index 0000000000000..9465d4d96a26b
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/MockSummaryExtractor2.cpp
@@ -0,0 +1,44 @@
+//===- MockSummaryExtractor2.cpp ------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MockTUSummaryBuilder.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+class MockSummaryExtractor2 : public TUSummaryExtractor {
+public:
+ MockSummaryExtractor2(TUSummaryBuilder &Builder)
+ : TUSummaryExtractor(Builder) {
+ getFakeBuilder().sendMessage(
+ "MockSummaryExtractor2 constructor was invoked");
+ }
+
+ ~MockSummaryExtractor2() {
+ getFakeBuilder().sendMessage(
+ "MockSummaryExtractor2 destructor was invoked");
+ }
+
+ void HandleTranslationUnit(ASTContext &Ctx) override {
+ getFakeBuilder().sendMessage(
+ "MockSummaryExtractor2 HandleTranslationUnit was invoked");
+ }
+
+ MockTUSummaryBuilder &getFakeBuilder() {
+ return static_cast<MockTUSummaryBuilder &>(SummaryBuilder);
+ }
+};
+
+} // namespace
+
+static TUSummaryExtractorRegistry::Add<MockSummaryExtractor2>
+ RegisterExtractor("MockSummaryExtractor2", "Mock summary extractor 2");
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/MockTUSummaryBuilder.h b/clang/unittests/ScalableStaticAnalysis/Registries/MockTUSummaryBuilder.h
new file mode 100644
index 0000000000000..87689634dc061
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/MockTUSummaryBuilder.h
@@ -0,0 +1,31 @@
+//===- MockTUSummaryBuilder.h -----------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKTUSUMMARYBUILDER_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKTUSUMMARYBUILDER_H
+
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace clang::ssaf {
+
+class MockTUSummaryBuilder : public TUSummaryBuilder {
+public:
+ using TUSummaryBuilder::TUSummaryBuilder;
+ void sendMessage(llvm::Twine Message) { Stream << Message << '\n'; }
+ std::string consumeMessages() { return std::move(OutputBuffer); }
+
+private:
+ std::string OutputBuffer;
+ llvm::raw_string_ostream Stream = llvm::raw_string_ostream{OutputBuffer};
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_REGISTRIES_MOCKTUSUMMARYBUILDER_H
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/SerializationFormatRegistryTest.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/SerializationFormatRegistryTest.cpp
new file mode 100644
index 0000000000000..bb61b95e0ccf6
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/SerializationFormatRegistryTest.cpp
@@ -0,0 +1,115 @@
+//===- SummaryExtractorRegistryTest.cpp -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/ScopeExit.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace llvm;
+using namespace clang;
+using namespace ssaf;
+
+// Returns the file name and content in a map.
+static std::map<std::string, std::string> readFilesFromDir(StringRef DirPath) {
+ std::map<std::string, std::string> Result;
+ std::error_code EC;
+
+ for (sys::fs::directory_iterator It(DirPath, EC), End; It != End && !EC;
+ It.increment(EC)) {
+ StringRef FilePath = It->path();
+
+ if (sys::fs::is_directory(FilePath))
+ continue;
+
+ auto BufferOrErr = MemoryBuffer::getFile(FilePath);
+ if (!BufferOrErr)
+ continue;
+
+ // Store only the filename (relative to DirPath).
+ StringRef FileName = sys::path::filename(FilePath);
+ Result[FileName.str()] = BufferOrErr.get()->getBuffer().str();
+ }
+
+ return Result;
+}
+namespace {
+
+TEST(SerializationFormatRegistryTest, isFormatRegistered) {
+ EXPECT_FALSE(isFormatRegistered("Non-existent-format"));
+ EXPECT_TRUE(isFormatRegistered("MockSerializationFormat"));
+}
+
+TEST(SerializationFormatRegistryTest, EnumeratingRegistryEntries) {
+ auto Formats = SerializationFormatRegistry::entries();
+ ASSERT_GE(std::distance(Formats.begin(), Formats.end()), 1U);
+ EXPECT_TRUE(llvm::any_of(Formats, [](const auto &Entry) {
+ return StringRef(Entry.getName()) == "MockSerializationFormat";
+ }));
+}
+
+TEST(SerializationFormatRegistryTest, Roundtrip) {
+ // Create temporary input directory
+ SmallString<128> InputDir;
+ std::error_code EC = sys::fs::createUniqueDirectory("ssaf-input", InputDir);
+ ASSERT_FALSE(EC) << "Failed to create input directory: " << EC.message();
+ llvm::scope_exit CleanupInputOnExit(
+ [&] { sys::fs::remove_directories(InputDir); });
+
+ // Create input files
+ SmallString<128> AnalysesFile = InputDir;
+ sys::path::append(AnalysesFile, "analyses.txt");
+ {
+ raw_fd_ostream OS(AnalysesFile, EC);
+ ASSERT_FALSE(EC) << "Failed to create analyses.txt: " << EC.message();
+ OS << "FancyAnalysis\n";
+ }
+
+ SmallString<128> FancyAnalysisFile = InputDir;
+ sys::path::append(FancyAnalysisFile, "FancyAnalysis.special");
+ {
+ raw_fd_ostream OS(FancyAnalysisFile, EC);
+ ASSERT_FALSE(EC) << "Failed to create FancyAnalysis.special: "
+ << EC.message();
+ OS << "Some FancyAnalysisData...";
+ }
+
+ std::unique_ptr<SerializationFormat> Format =
+ makeFormat("MockSerializationFormat");
+ ASSERT_TRUE(Format);
+
+ auto LoadedSummaryOrErr = Format->readTUSummary(InputDir);
+ ASSERT_THAT_EXPECTED(LoadedSummaryOrErr, Succeeded());
+ TUSummary LoadedSummary = std::move(*LoadedSummaryOrErr);
+
+ // Create a temporary output directory
+ SmallString<128> OutputDir;
+ EC = sys::fs::createUniqueDirectory("ssaf-test", OutputDir);
+ ASSERT_FALSE(EC) << "Failed to create temporary directory: " << EC.message();
+ llvm::scope_exit CleanupOnExit(
+ [&] { sys::fs::remove_directories(OutputDir); });
+
+ auto WriteErr = Format->writeTUSummary(LoadedSummary, OutputDir);
+ ASSERT_THAT_ERROR(std::move(WriteErr), Succeeded());
+
+ EXPECT_EQ(readFilesFromDir(OutputDir),
+ (std::map<std::string, std::string>{
+ {"analyses.txt", "FancyAnalysis\n"},
+ {"FancyAnalysis.special", "Some FancyAnalysisData..."},
+ }));
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/Registries/SummaryExtractorRegistryTest.cpp b/clang/unittests/ScalableStaticAnalysis/Registries/SummaryExtractorRegistryTest.cpp
new file mode 100644
index 0000000000000..db7c7ad835bb6
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Registries/SummaryExtractorRegistryTest.cpp
@@ -0,0 +1,113 @@
+//===- SummaryExtractorRegistryTest.cpp -----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "MockTUSummaryBuilder.h"
+#include "clang/Frontend/MultiplexConsumer.h"
+#include "clang/Frontend/SSAFOptions.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/StringRef.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <memory>
+
+using namespace clang;
+using namespace ssaf;
+
+[[nodiscard]]
+static TUSummary makeFakeSummary() {
+ return TUSummary(
+ llvm::Triple("arm64-apple-macosx"),
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp"));
+}
+
+namespace {
+
+TEST(SummaryExtractorRegistryTest, isTUSummaryExtractorRegistered) {
+ EXPECT_FALSE(isTUSummaryExtractorRegistered("Non-existent-extractor"));
+ EXPECT_TRUE(isTUSummaryExtractorRegistered("MockSummaryExtractor1"));
+ EXPECT_TRUE(isTUSummaryExtractorRegistered("MockSummaryExtractor2"));
+}
+
+TEST(SummaryExtractorRegistryTest, EnumeratingRegistryEntries) {
+ std::set<llvm::StringRef> ActualNames;
+ for (const auto &Entry : TUSummaryExtractorRegistry::entries()) {
+ bool Inserted = ActualNames.insert(Entry.getName()).second;
+ EXPECT_TRUE(Inserted);
+ }
+
+ EXPECT_THAT(ActualNames, testing::IsSupersetOf({"MockSummaryExtractor1",
+ "MockSummaryExtractor2"}));
+}
+
+TEST(SummaryExtractorRegistryTest, InstantiatingExtractor1) {
+ SSAFOptions Opts;
+ TUSummary Summary = makeFakeSummary();
+ MockTUSummaryBuilder FakeBuilder(Summary, Opts);
+ {
+ auto Consumer =
+ makeTUSummaryExtractor("MockSummaryExtractor1", FakeBuilder);
+ EXPECT_TRUE(Consumer);
+ EXPECT_EQ(FakeBuilder.consumeMessages(),
+ "MockSummaryExtractor1 constructor was invoked\n");
+ }
+ EXPECT_EQ(FakeBuilder.consumeMessages(),
+ "MockSummaryExtractor1 destructor was invoked\n");
+}
+
+TEST(SummaryExtractorRegistryTest, InstantiatingExtractor2) {
+ SSAFOptions Opts;
+ TUSummary Summary = makeFakeSummary();
+ MockTUSummaryBuilder FakeBuilder(Summary, Opts);
+ {
+ auto Consumer =
+ makeTUSummaryExtractor("MockSummaryExtractor2", FakeBuilder);
+ EXPECT_TRUE(Consumer);
+ EXPECT_EQ(FakeBuilder.consumeMessages(),
+ "MockSummaryExtractor2 constructor was invoked\n");
+ }
+ EXPECT_EQ(FakeBuilder.consumeMessages(),
+ "MockSummaryExtractor2 destructor was invoked\n");
+}
+
+TEST(SummaryExtractorRegistryTest, InvokingExtractors) {
+ SSAFOptions Opts;
+ TUSummary Summary = makeFakeSummary();
+ MockTUSummaryBuilder FakeBuilder(Summary, Opts);
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
+ for (std::string Name : {"MockSummaryExtractor1", "MockSummaryExtractor2"}) {
+ auto Consumer = makeTUSummaryExtractor(Name, FakeBuilder);
+ ASSERT_TRUE(Consumer);
+ Consumers.push_back(std::move(Consumer));
+ }
+ EXPECT_EQ(FakeBuilder.consumeMessages(),
+ "MockSummaryExtractor1 constructor was invoked\n"
+ "MockSummaryExtractor2 constructor was invoked\n");
+
+ {
+ MultiplexConsumer Multiplexer(std::move(Consumers));
+ auto AST = tooling::buildASTFromCode(R"cpp(int x = 42;)cpp");
+ ASSERT_TRUE(AST);
+
+ Multiplexer.HandleTranslationUnit(AST->getASTContext());
+ EXPECT_EQ(FakeBuilder.consumeMessages(),
+ "MockSummaryExtractor1 HandleTranslationUnit was invoked\n"
+ "MockSummaryExtractor2 HandleTranslationUnit was invoked\n");
+ }
+
+ std::string OwnedMessages = FakeBuilder.consumeMessages();
+ StringRef View = OwnedMessages;
+ EXPECT_EQ(View.count('\n'), 2u);
+
+ // The destruction order is indeterminate.
+ EXPECT_TRUE(View.contains("MockSummaryExtractor1 destructor was invoked\n"));
+ EXPECT_TRUE(View.contains("MockSummaryExtractor2 destructor was invoked\n"));
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.cpp b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.cpp
new file mode 100644
index 0000000000000..777625dc9fed7
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.cpp
@@ -0,0 +1,639 @@
+//===- JSONFormatTest.cpp -------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Shared normalization helpers for SSAF JSON serialization format unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONFormatTest.h"
+
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/Registry.h"
+#include "llvm/Testing/Support/Error.h"
+#ifndef _WIN32
+#include <unistd.h>
+#endif
+
+using namespace clang::ssaf;
+using namespace llvm;
+using PathString = JSONFormatTest::PathString;
+
+// ============================================================================
+// Test Fixture
+// ============================================================================
+
+void JSONFormatTest::SetUp() {
+ std::error_code EC =
+ llvm::sys::fs::createUniqueDirectory("json-format-test", TestDir);
+ ASSERT_FALSE(EC) << "Failed to create temp directory: " << EC.message();
+}
+
+void JSONFormatTest::TearDown() { llvm::sys::fs::remove_directories(TestDir); }
+
+JSONFormatTest::PathString
+JSONFormatTest::makePath(llvm::StringRef FileOrDirectoryName) const {
+ PathString FullPath = TestDir;
+ llvm::sys::path::append(FullPath, FileOrDirectoryName);
+
+ return FullPath;
+}
+
+PathString JSONFormatTest::makePath(llvm::StringRef Dir,
+ llvm::StringRef FileName) const {
+ PathString FullPath = TestDir;
+ llvm::sys::path::append(FullPath, Dir, FileName);
+
+ return FullPath;
+}
+
+llvm::Expected<PathString>
+JSONFormatTest::makeDirectory(llvm::StringRef DirectoryName) const {
+ PathString DirPath = makePath(DirectoryName);
+
+ std::error_code EC = llvm::sys::fs::create_directory(DirPath);
+ if (EC) {
+ return llvm::createStringError(EC, "Failed to create directory '%s': %s",
+ DirPath.c_str(), EC.message().c_str());
+ }
+
+ return DirPath;
+}
+
+llvm::Expected<PathString>
+JSONFormatTest::makeSymlink(llvm::StringRef TargetFileName,
+ llvm::StringRef SymlinkFileName) const {
+ PathString TargetPath = makePath(TargetFileName);
+ PathString SymlinkPath = makePath(SymlinkFileName);
+
+ std::error_code EC = llvm::sys::fs::create_link(TargetPath, SymlinkPath);
+ if (EC) {
+ return llvm::createStringError(
+ EC, "Failed to create symlink '%s' -> '%s': %s", SymlinkPath.c_str(),
+ TargetPath.c_str(), EC.message().c_str());
+ }
+
+ return SymlinkPath;
+}
+
+llvm::Error JSONFormatTest::setPermission(llvm::StringRef FileName,
+ llvm::sys::fs::perms Perms) const {
+ PathString Path = makePath(FileName);
+
+ std::error_code EC = llvm::sys::fs::setPermissions(Path, Perms);
+ if (EC) {
+ return llvm::createStringError(EC, "Failed to set permissions on '%s': %s",
+ Path.c_str(), EC.message().c_str());
+ }
+
+ return llvm::Error::success();
+}
+
+bool JSONFormatTest::permissionsAreEnforced() const {
+#ifdef _WIN32
+ return false;
+#else
+ if (getuid() == 0) {
+ return false;
+ }
+
+ // Write a probe file, remove read permission, and try to open it.
+ PathString ProbePath = makePath("perm-probe.json");
+
+ {
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(ProbePath, EC);
+ if (EC) {
+ return true; // Probe setup failed; assume enforced to avoid
+ // silently suppressing the test.
+ }
+ OS << "{}";
+ }
+
+ std::error_code PermEC = llvm::sys::fs::setPermissions(
+ ProbePath, llvm::sys::fs::perms::owner_write);
+ if (PermEC) {
+ return true; // Probe setup failed; assume enforced to avoid
+ // silently suppressing the test.
+ }
+
+ auto Buffer = llvm::MemoryBuffer::getFile(ProbePath, /*IsText=*/true);
+ bool Enforced = !Buffer; // If open failed, permissions are enforced.
+
+ // Restore permissions so TearDown can clean up the temp directory.
+ llvm::sys::fs::setPermissions(ProbePath, llvm::sys::fs::perms::all_all);
+
+ return Enforced;
+#endif
+}
+
+llvm::Expected<llvm::json::Value>
+JSONFormatTest::readJSONFromFile(llvm::StringRef FileName) const {
+ PathString FilePath = makePath(FileName);
+
+ auto BufferOrError = llvm::MemoryBuffer::getFile(FilePath, /*IsText=*/true);
+ if (!BufferOrError) {
+ return llvm::createStringError(BufferOrError.getError(),
+ "Failed to read file: %s", FilePath.c_str());
+ }
+
+ llvm::Expected<llvm::json::Value> ExpectedValue =
+ llvm::json::parse(BufferOrError.get()->getBuffer());
+ if (!ExpectedValue) {
+ return ExpectedValue.takeError();
+ }
+
+ return *ExpectedValue;
+}
+
+llvm::Expected<PathString>
+JSONFormatTest::writeJSON(llvm::StringRef JSON,
+ llvm::StringRef FileName) const {
+ PathString FilePath = makePath(FileName);
+
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(FilePath, EC);
+ if (EC) {
+ return llvm::createStringError(EC, "Failed to create file '%s': %s",
+ FilePath.c_str(), EC.message().c_str());
+ }
+
+ OS << JSON;
+ OS.close();
+
+ if (OS.has_error()) {
+ return llvm::createStringError(
+ OS.error(), "Failed to write to file '%s': %s", FilePath.c_str(),
+ OS.error().message().c_str());
+ }
+
+ return FilePath;
+}
+
+// ============================================================================
+// Summary JSON Normalization Helpers
+// ============================================================================
+
+namespace {
+
+llvm::Error normalizeIDTable(json::Array &IDTable,
+ llvm::StringRef SummaryClassName) {
+ for (const auto &[Index, Entry] : llvm::enumerate(IDTable)) {
+ const auto *EntryObj = Entry.getAsObject();
+ if (!EntryObj) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: id_table entry at index %zu "
+ "is not an object",
+ SummaryClassName.data(), Index);
+ }
+
+ const auto *IDValue = EntryObj->get("id");
+ if (!IDValue) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: id_table entry at index %zu "
+ "does not contain an 'id' field",
+ SummaryClassName.data(), Index);
+ }
+
+ if (!IDValue->getAsUINT64()) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: id_table entry at index %zu "
+ "'id' field is not a valid entity id integer",
+ SummaryClassName.data(), Index);
+ }
+ }
+
+ // Safe to dereference: all entries were validated above.
+ llvm::sort(IDTable, [](const json::Value &A, const json::Value &B) {
+ return *A.getAsObject()->get("id")->getAsUINT64() <
+ *B.getAsObject()->get("id")->getAsUINT64();
+ });
+
+ return llvm::Error::success();
+}
+
+llvm::Error normalizeLinkageTable(json::Array &LinkageTable,
+ llvm::StringRef SummaryClassName) {
+ for (const auto &[Index, Entry] : llvm::enumerate(LinkageTable)) {
+ const auto *EntryObj = Entry.getAsObject();
+ if (!EntryObj) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: linkage_table entry at index "
+ "%zu is not an object",
+ SummaryClassName.data(), Index);
+ }
+
+ const auto *IDValue = EntryObj->get("id");
+ if (!IDValue) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: linkage_table entry at index "
+ "%zu does not contain an 'id' field",
+ SummaryClassName.data(), Index);
+ }
+
+ if (!IDValue->getAsUINT64()) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: linkage_table entry at index "
+ "%zu 'id' field is not a valid entity id integer",
+ SummaryClassName.data(), Index);
+ }
+ }
+
+ // Safe to dereference: all entries were validated above.
+ llvm::sort(LinkageTable, [](const json::Value &A, const json::Value &B) {
+ return *A.getAsObject()->get("id")->getAsUINT64() <
+ *B.getAsObject()->get("id")->getAsUINT64();
+ });
+
+ return llvm::Error::success();
+}
+
+llvm::Error normalizeSummaryData(json::Array &SummaryData, size_t DataIndex,
+ llvm::StringRef SummaryClassName) {
+ for (const auto &[SummaryIndex, SummaryEntry] :
+ llvm::enumerate(SummaryData)) {
+ const auto *SummaryEntryObj = SummaryEntry.getAsObject();
+ if (!SummaryEntryObj) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: data entry at index %zu, "
+ "summary_data entry at index %zu is not an object",
+ SummaryClassName.data(), DataIndex, SummaryIndex);
+ }
+
+ const auto *EntityIDValue = SummaryEntryObj->get("entity_id");
+ if (!EntityIDValue) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: data entry at index %zu, "
+ "summary_data entry at index %zu does not contain an "
+ "'entity_id' field",
+ SummaryClassName.data(), DataIndex, SummaryIndex);
+ }
+
+ if (!EntityIDValue->getAsUINT64()) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: data entry at index %zu, "
+ "summary_data entry at index %zu 'entity_id' field is not "
+ "a valid entity id integer",
+ SummaryClassName.data(), DataIndex, SummaryIndex);
+ }
+ }
+
+ // Safe to dereference: all entries were validated above.
+ llvm::sort(SummaryData, [](const json::Value &A, const json::Value &B) {
+ return *A.getAsObject()->get("entity_id")->getAsUINT64() <
+ *B.getAsObject()->get("entity_id")->getAsUINT64();
+ });
+
+ return llvm::Error::success();
+}
+
+llvm::Error normalizeData(json::Array &Data, llvm::StringRef SummaryClassName) {
+ for (const auto &[DataIndex, DataEntry] : llvm::enumerate(Data)) {
+ auto *DataEntryObj = DataEntry.getAsObject();
+ if (!DataEntryObj) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: data entry at index %zu "
+ "is not an object",
+ SummaryClassName.data(), DataIndex);
+ }
+
+ if (!DataEntryObj->getString("summary_name")) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: data entry at index %zu "
+ "does not contain a 'summary_name' string field",
+ SummaryClassName.data(), DataIndex);
+ }
+
+ auto *SummaryData = DataEntryObj->getArray("summary_data");
+ if (!SummaryData) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: data entry at index %zu "
+ "does not contain a 'summary_data' array field",
+ SummaryClassName.data(), DataIndex);
+ }
+
+ if (auto Err =
+ normalizeSummaryData(*SummaryData, DataIndex, SummaryClassName)) {
+ return Err;
+ }
+ }
+
+ // Safe to dereference: all entries were validated above.
+ llvm::sort(Data, [](const json::Value &A, const json::Value &B) {
+ return *A.getAsObject()->getString("summary_name") <
+ *B.getAsObject()->getString("summary_name");
+ });
+
+ return llvm::Error::success();
+}
+
+Expected<json::Value> normalizeSummaryJSON(json::Value Val,
+ llvm::StringRef SummaryClassName) {
+ auto *Obj = Val.getAsObject();
+ if (!Obj) {
+ return createStringError(inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: expected an object",
+ SummaryClassName.data());
+ }
+
+ auto *IDTable = Obj->getArray("id_table");
+ if (!IDTable) {
+ return createStringError(inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: 'id_table' "
+ "field is either missing or has the wrong type",
+ SummaryClassName.data());
+ }
+ if (auto Err = normalizeIDTable(*IDTable, SummaryClassName)) {
+ return std::move(Err);
+ }
+
+ auto *LinkageTable = Obj->getArray("linkage_table");
+ if (!LinkageTable) {
+ return createStringError(inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: 'linkage_table' "
+ "field is either missing or has the wrong type",
+ SummaryClassName.data());
+ }
+ if (auto Err = normalizeLinkageTable(*LinkageTable, SummaryClassName)) {
+ return std::move(Err);
+ }
+
+ auto *Data = Obj->getArray("data");
+ if (!Data) {
+ return createStringError(inconvertibleErrorCode(),
+ "Cannot normalize %s JSON: 'data' "
+ "field is either missing or has the wrong type",
+ SummaryClassName.data());
+ }
+ if (auto Err = normalizeData(*Data, SummaryClassName)) {
+ return std::move(Err);
+ }
+
+ return Val;
+}
+
+} // namespace
+
+// ============================================================================
+// SummaryTest Fixture Implementation
+// ============================================================================
+
+llvm::Error SummaryTest::readFromString(StringRef JSON,
+ StringRef FileName) const {
+ auto ExpectedFilePath = writeJSON(JSON, FileName);
+ if (!ExpectedFilePath) {
+ return ExpectedFilePath.takeError();
+ }
+ return GetParam().ReadFromFile(*ExpectedFilePath);
+}
+
+llvm::Error SummaryTest::readFromFile(StringRef FileName) const {
+ return GetParam().ReadFromFile(makePath(FileName));
+}
+
+llvm::Error SummaryTest::writeEmpty(StringRef FileName) const {
+ return GetParam().WriteEmpty(makePath(FileName));
+}
+
+llvm::Error SummaryTest::readWriteRoundTrip(StringRef InputFileName,
+ StringRef OutputFileName) const {
+ return GetParam().ReadWriteRoundTrip(makePath(InputFileName),
+ makePath(OutputFileName));
+}
+
+void SummaryTest::readWriteCompare(StringRef JSON) const {
+ const PathString InputFileName("input.json");
+ const PathString OutputFileName("output.json");
+
+ auto ExpectedInputFilePath = writeJSON(JSON, InputFileName);
+ ASSERT_THAT_EXPECTED(ExpectedInputFilePath, Succeeded());
+
+ ASSERT_THAT_ERROR(readWriteRoundTrip(InputFileName, OutputFileName),
+ Succeeded());
+
+ auto ExpectedInputJSON = readJSONFromFile(InputFileName);
+ ASSERT_THAT_EXPECTED(ExpectedInputJSON, Succeeded());
+
+ auto ExpectedOutputJSON = readJSONFromFile(OutputFileName);
+ ASSERT_THAT_EXPECTED(ExpectedOutputJSON, Succeeded());
+
+ auto ExpectedNormalizedInputJSON =
+ normalizeSummaryJSON(*ExpectedInputJSON, GetParam().SummaryClassName);
+ ASSERT_THAT_EXPECTED(ExpectedNormalizedInputJSON, Succeeded());
+
+ auto ExpectedNormalizedOutputJSON =
+ normalizeSummaryJSON(*ExpectedOutputJSON, GetParam().SummaryClassName);
+ ASSERT_THAT_EXPECTED(ExpectedNormalizedOutputJSON, Succeeded());
+
+ ASSERT_EQ(*ExpectedNormalizedInputJSON, *ExpectedNormalizedOutputJSON)
+ << "Serialization is broken: input is different from output\n"
+ << "Input: "
+ << llvm::formatv("{0:2}", *ExpectedNormalizedInputJSON).str() << "\n"
+ << "Output: "
+ << llvm::formatv("{0:2}", *ExpectedNormalizedOutputJSON).str();
+}
+
+namespace {
+
+// ============================================================================
+// First Test Analysis - Simple analysis for testing JSON serialization.
+// ============================================================================
+
+json::Object serializePairsEntitySummaryForJSONFormatTest(
+ const EntitySummary &Summary, JSONFormat::EntityIdToJSONFn ToJSON) {
+ const auto &TA =
+ static_cast<const PairsEntitySummaryForJSONFormatTest &>(Summary);
+ json::Array PairsArray;
+ for (const auto &[First, Second] : TA.Pairs) {
+ PairsArray.push_back(json::Object{
+ {"first", ToJSON(First)},
+ {"second", ToJSON(Second)},
+ });
+ }
+ return json::Object{{"pairs", std::move(PairsArray)}};
+}
+
+Expected<std::unique_ptr<EntitySummary>>
+deserializePairsEntitySummaryForJSONFormatTest(
+ const json::Object &Obj, EntityIdTable &IdTable,
+ JSONFormat::EntityIdFromJSONFn FromJSON) {
+ auto Result = std::make_unique<PairsEntitySummaryForJSONFormatTest>();
+ const json::Array *PairsArray = Obj.getArray("pairs");
+ if (!PairsArray) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid field 'pairs'");
+ }
+ for (const auto &[Index, Value] : llvm::enumerate(*PairsArray)) {
+ const json::Object *Pair = Value.getAsObject();
+ if (!Pair) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "pairs element at index %zu is not a JSON object", Index);
+ }
+ const json::Object *FirstObj = Pair->getObject("first");
+ if (!FirstObj) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "missing or invalid 'first' field at index '%zu'", Index);
+ }
+ const json::Object *SecondObj = Pair->getObject("second");
+ if (!SecondObj) {
+ return createStringError(
+ inconvertibleErrorCode(),
+ "missing or invalid 'second' field at index '%zu'", Index);
+ }
+ auto ExpectedFirst = FromJSON(*FirstObj);
+ if (!ExpectedFirst) {
+ return createStringError(inconvertibleErrorCode(),
+ "invalid 'first' entity id at index '%zu': %s",
+ Index,
+ toString(ExpectedFirst.takeError()).c_str());
+ }
+ auto ExpectedSecond = FromJSON(*SecondObj);
+ if (!ExpectedSecond) {
+ return createStringError(inconvertibleErrorCode(),
+ "invalid 'second' entity id at index '%zu': %s",
+ Index,
+ toString(ExpectedSecond.takeError()).c_str());
+ }
+ Result->Pairs.emplace_back(*ExpectedFirst, *ExpectedSecond);
+ }
+ return std::move(Result);
+}
+
+struct PairsEntitySummaryForJSONFormatTestFormatInfo final
+ : JSONFormat::FormatInfo {
+ PairsEntitySummaryForJSONFormatTestFormatInfo()
+ : JSONFormat::FormatInfo(
+ SummaryName("PairsEntitySummaryForJSONFormatTest"),
+ serializePairsEntitySummaryForJSONFormatTest,
+ deserializePairsEntitySummaryForJSONFormatTest) {}
+};
+
+llvm::Registry<JSONFormat::FormatInfo>::Add<
+ PairsEntitySummaryForJSONFormatTestFormatInfo>
+ RegisterPairsEntitySummaryForJSONFormatTest(
+ "PairsEntitySummaryForJSONFormatTest",
+ "Format info for PairsArrayEntitySummary");
+
+// ============================================================================
+// Second Test Analysis - Simple analysis for multi-summary round-trip tests.
+// ============================================================================
+
+json::Object
+serializeTagsEntitySummaryForJSONFormatTest(const EntitySummary &Summary,
+ JSONFormat::EntityIdToJSONFn) {
+ const auto &TA =
+ static_cast<const TagsEntitySummaryForJSONFormatTest &>(Summary);
+ json::Array TagsArray;
+ for (const auto &Tag : TA.Tags) {
+ TagsArray.push_back(Tag);
+ }
+ return json::Object{{"tags", std::move(TagsArray)}};
+}
+
+Expected<std::unique_ptr<EntitySummary>>
+deserializeTagsEntitySummaryForJSONFormatTest(const json::Object &Obj,
+ EntityIdTable &,
+ JSONFormat::EntityIdFromJSONFn) {
+ auto Result = std::make_unique<TagsEntitySummaryForJSONFormatTest>();
+ const json::Array *TagsArray = Obj.getArray("tags");
+ if (!TagsArray) {
+ return createStringError(inconvertibleErrorCode(),
+ "missing or invalid field 'tags'");
+ }
+ for (const auto &[Index, Value] : llvm::enumerate(*TagsArray)) {
+ auto Tag = Value.getAsString();
+ if (!Tag) {
+ return createStringError(inconvertibleErrorCode(),
+ "tags element at index %zu is not a string",
+ Index);
+ }
+ Result->Tags.push_back(Tag->str());
+ }
+ return std::move(Result);
+}
+
+struct TagsEntitySummaryForJSONFormatTestFormatInfo final
+ : JSONFormat::FormatInfo {
+ TagsEntitySummaryForJSONFormatTestFormatInfo()
+ : JSONFormat::FormatInfo(
+ SummaryName("TagsEntitySummaryForJSONFormatTest"),
+ serializeTagsEntitySummaryForJSONFormatTest,
+ deserializeTagsEntitySummaryForJSONFormatTest) {}
+};
+
+llvm::Registry<JSONFormat::FormatInfo>::Add<
+ TagsEntitySummaryForJSONFormatTestFormatInfo>
+ RegisterTagsEntitySummaryForJSONFormatTest(
+ "TagsEntitySummaryForJSONFormatTest",
+ "Format info for TagsEntitySummary");
+
+// ============================================================================
+// NullEntitySummaryForJSONFormatTest - For null data checks
+// ============================================================================
+
+struct NullEntitySummaryForJSONFormatTestFormatInfo final
+ : JSONFormat::FormatInfo {
+ NullEntitySummaryForJSONFormatTestFormatInfo()
+ : JSONFormat::FormatInfo(
+ SummaryName("NullEntitySummaryForJSONFormatTest"),
+ [](const EntitySummary &, JSONFormat::EntityIdToJSONFn)
+ -> json::Object { return json::Object{}; },
+ [](const json::Object &, EntityIdTable &,
+ JSONFormat::EntityIdFromJSONFn)
+ -> llvm::Expected<std::unique_ptr<EntitySummary>> {
+ return nullptr;
+ }) {}
+};
+
+llvm::Registry<JSONFormat::FormatInfo>::Add<
+ NullEntitySummaryForJSONFormatTestFormatInfo>
+ RegisterNullEntitySummaryForJSONFormatTest(
+ "NullEntitySummaryForJSONFormatTest",
+ "Format info for NullEntitySummary");
+
+// ============================================================================
+// MismatchedEntitySummaryForJSONFormatTest - For mismatched SummaryName checks
+// ============================================================================
+
+struct MismatchedEntitySummaryForJSONFormatTestFormatInfo final
+ : JSONFormat::FormatInfo {
+ MismatchedEntitySummaryForJSONFormatTestFormatInfo()
+ : JSONFormat::FormatInfo(
+ SummaryName("MismatchedEntitySummaryForJSONFormatTest"),
+ [](const EntitySummary &, JSONFormat::EntityIdToJSONFn)
+ -> json::Object { return json::Object{}; },
+ [](const json::Object &, EntityIdTable &,
+ JSONFormat::EntityIdFromJSONFn)
+ -> llvm::Expected<std::unique_ptr<EntitySummary>> {
+ return std::make_unique<
+ MismatchedEntitySummaryForJSONFormatTest>();
+ }) {}
+};
+
+llvm::Registry<JSONFormat::FormatInfo>::Add<
+ MismatchedEntitySummaryForJSONFormatTestFormatInfo>
+ RegisterMismatchedEntitySummaryForJSONFormatTest(
+ "MismatchedEntitySummaryForJSONFormatTest",
+ "Format info for MismatchedEntitySummary");
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.h b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.h
new file mode 100644
index 0000000000000..b411ed3f91573
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/JSONFormatTest.h
@@ -0,0 +1,172 @@
+//===- JSONFormatTest.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Test fixture and helpers for SSAF JSON serialization format unit tests.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
+
+#include "TestFixture.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <functional>
+#include <string>
+
+namespace clang::ssaf {
+
+// ============================================================================
+// Test Fixture
+// ============================================================================
+
+class JSONFormatTest : public TestFixture {
+public:
+ using PathString = llvm::SmallString<128>;
+
+protected:
+ llvm::SmallString<128> TestDir;
+
+ void SetUp() override;
+
+ void TearDown() override;
+
+ PathString makePath(llvm::StringRef FileOrDirectoryName) const;
+
+ PathString makePath(llvm::StringRef Dir, llvm::StringRef FileName) const;
+
+ llvm::Expected<PathString> makeDirectory(llvm::StringRef DirectoryName) const;
+
+ llvm::Expected<PathString> makeSymlink(llvm::StringRef TargetFileName,
+ llvm::StringRef SymlinkFileName) const;
+
+ llvm::Error setPermission(llvm::StringRef FileName,
+ llvm::sys::fs::perms Perms) const;
+
+ // Returns true if Unix file permission checks are enforced in this
+ // environment. Returns false if running as root (uid 0), or if a probe
+ // file with read permission removed can still be opened, indicating that
+ // permission checks are not enforced (e.g. certain container setups).
+ // Tests that rely on permission-based failure conditions should skip
+ // themselves when this returns false.
+ bool permissionsAreEnforced() const;
+
+ llvm::Expected<llvm::json::Value>
+ readJSONFromFile(llvm::StringRef FileName) const;
+
+ llvm::Expected<PathString> writeJSON(llvm::StringRef JSON,
+ llvm::StringRef FileName) const;
+};
+
+// ============================================================================
+// SummaryOps - Parameterization struct for TUSummary/LUSummary test suites
+// ============================================================================
+
+struct SummaryOps {
+ // Suffix appended to the test name by GTest to identify this parameter
+ // instantiation (e.g. "Resolved", "Encoding").
+ std::string GTestInstantiationSuffix;
+
+ // Human-readable name of the summary class under test (e.g. "TUSummary").
+ // Used in diagnostic messages to identify which summary type an error
+ // originated from.
+ std::string SummaryClassName;
+
+ std::function<llvm::Error(llvm::StringRef FilePath)> ReadFromFile;
+
+ std::function<llvm::Error(llvm::StringRef FilePath)> WriteEmpty;
+
+ std::function<llvm::Error(llvm::StringRef InputFilePath,
+ llvm::StringRef OutputFilePath)>
+ ReadWriteRoundTrip;
+};
+
+// ============================================================================
+// SummaryTest Test Fixture
+// ============================================================================
+
+class SummaryTest : public JSONFormatTest,
+ public ::testing::WithParamInterface<SummaryOps> {
+protected:
+ llvm::Error readFromString(llvm::StringRef JSON,
+ llvm::StringRef FileName = "test.json") const;
+
+ llvm::Error readFromFile(llvm::StringRef FileName) const;
+
+ llvm::Error writeEmpty(llvm::StringRef FileName) const;
+
+ llvm::Error readWriteRoundTrip(llvm::StringRef InputFileName,
+ llvm::StringRef OutputFileName) const;
+
+ void readWriteCompare(llvm::StringRef JSON) const;
+};
+
+// ============================================================================
+// First Test Analysis - Simple analysis for testing JSON serialization.
+// ============================================================================
+
+struct PairsEntitySummaryForJSONFormatTest final : EntitySummary {
+
+ SummaryName getSummaryName() const override {
+ return SummaryName("PairsEntitySummaryForJSONFormatTest");
+ }
+
+ std::vector<std::pair<EntityId, EntityId>> Pairs;
+};
+
+// ============================================================================
+// Second Test Analysis - Simple analysis for multi-summary round-trip tests.
+// ============================================================================
+
+struct TagsEntitySummaryForJSONFormatTest final : EntitySummary {
+ SummaryName getSummaryName() const override {
+ return SummaryName("TagsEntitySummaryForJSONFormatTest");
+ }
+
+ std::vector<std::string> Tags;
+};
+
+// ============================================================================
+// NullEntitySummaryForJSONFormatTest - For null data checks
+// ============================================================================
+
+struct NullEntitySummaryForJSONFormatTest final : EntitySummary {
+ SummaryName getSummaryName() const override {
+ return SummaryName("NullEntitySummaryForJSONFormatTest");
+ }
+};
+
+// ============================================================================
+// UnregisteredEntitySummaryForJSONFormatTest - For missing FormatInfo checks
+// ============================================================================
+
+struct UnregisteredEntitySummaryForJSONFormatTest final : EntitySummary {
+ SummaryName getSummaryName() const override {
+ return SummaryName("UnregisteredEntitySummaryForJSONFormatTest");
+ }
+};
+
+// ============================================================================
+// MismatchedEntitySummaryForJSONFormatTest - For mismatched SummaryName checks
+// ============================================================================
+
+struct MismatchedEntitySummaryForJSONFormatTest final : EntitySummary {
+ SummaryName getSummaryName() const override {
+ return SummaryName("MismatchedEntitySummaryForJSONFormatTest_WrongName");
+ }
+};
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_SERIALIZATION_JSONFORMATTEST_JSONFORMATTEST_H
diff --git a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/LUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/LUSummaryTest.cpp
new file mode 100644
index 0000000000000..3a9ed5aebfd7e
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/LUSummaryTest.cpp
@@ -0,0 +1,452 @@
+//===- LUSummaryTest.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Unit tests for SSAF JSON serialization format reading and writing of
+// LUSummary and LUSummaryEncoding.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONFormatTest.h"
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+
+#include <memory>
+#include <vector>
+
+using namespace clang::ssaf;
+using namespace llvm;
+using ::testing::AllOf;
+using ::testing::HasSubstr;
+
+namespace {
+
+// ============================================================================
+// LUSummaryOps - Parameterization for LUSummary/LUSummaryEncoding tests
+// ============================================================================
+
+SummaryOps LUSummaryOps{
+ "Resolved", "LUSummary",
+ [](llvm::StringRef FilePath) -> llvm::Error {
+ auto Result = JSONFormat().readLUSummary(FilePath);
+ return Result ? llvm::Error::success() : Result.takeError();
+ },
+ [](llvm::StringRef FilePath) -> llvm::Error {
+ BuildNamespace BN(BuildNamespaceKind::CompilationUnit, "test.cpp");
+ NestedBuildNamespace NBN(std::move(BN));
+ LUSummary S(llvm::Triple("arm64-apple-macosx"), std::move(NBN));
+ return JSONFormat().writeLUSummary(S, FilePath);
+ },
+ [](llvm::StringRef InputFilePath,
+ llvm::StringRef OutputFilePath) -> llvm::Error {
+ auto ExpectedS = JSONFormat().readLUSummary(InputFilePath);
+ if (!ExpectedS) {
+ return ExpectedS.takeError();
+ }
+ return JSONFormat().writeLUSummary(*ExpectedS, OutputFilePath);
+ }};
+
+SummaryOps LUSummaryEncodingOps{
+ "Encoding", "LUSummary",
+ [](llvm::StringRef FilePath) -> llvm::Error {
+ auto Result = JSONFormat().readLUSummaryEncoding(FilePath);
+ return Result ? llvm::Error::success() : Result.takeError();
+ },
+ [](llvm::StringRef FilePath) -> llvm::Error {
+ BuildNamespace BN(BuildNamespaceKind::CompilationUnit, "test.cpp");
+ NestedBuildNamespace NBN(std::move(BN));
+ LUSummaryEncoding E(llvm::Triple("arm64-apple-macosx"), std::move(NBN));
+ return JSONFormat().writeLUSummaryEncoding(E, FilePath);
+ },
+ [](llvm::StringRef InputFilePath,
+ llvm::StringRef OutputFilePath) -> llvm::Error {
+ auto ExpectedE = JSONFormat().readLUSummaryEncoding(InputFilePath);
+ if (!ExpectedE) {
+ return ExpectedE.takeError();
+ }
+ return JSONFormat().writeLUSummaryEncoding(*ExpectedE, OutputFilePath);
+ }};
+
+// ============================================================================
+// LUSummaryTest Test Fixture
+// ============================================================================
+
+class LUSummaryTest : public SummaryTest {};
+
+INSTANTIATE_TEST_SUITE_P(JSONFormat, LUSummaryTest,
+ ::testing::Values(LUSummaryOps, LUSummaryEncodingOps),
+ [](const ::testing::TestParamInfo<SummaryOps> &Info) {
+ return Info.param.GTestInstantiationSuffix;
+ });
+
+// ============================================================================
+// JSONFormatLUSummaryTest Test Fixture
+// ============================================================================
+
+class JSONFormatLUSummaryTest : public JSONFormatTest {
+protected:
+ llvm::Expected<LUSummary> readLUSummaryFromFile(StringRef FileName) const {
+ PathString FilePath = makePath(FileName);
+ return JSONFormat().readLUSummary(FilePath);
+ }
+
+ llvm::Expected<LUSummary>
+ readLUSummaryFromString(StringRef JSON,
+ StringRef FileName = "test.json") const {
+ auto ExpectedFilePath = writeJSON(JSON, FileName);
+ if (!ExpectedFilePath) {
+ return ExpectedFilePath.takeError();
+ }
+
+ return readLUSummaryFromFile(FileName);
+ }
+
+ llvm::Error writeLUSummary(const LUSummary &Summary,
+ StringRef FileName) const {
+ PathString FilePath = makePath(FileName);
+ return JSONFormat().writeLUSummary(Summary, FilePath);
+ }
+};
+
+// ============================================================================
+// readJSON() Error Tests
+// ============================================================================
+
+TEST_P(LUSummaryTest, NonexistentFile) {
+ auto Result = readFromFile("nonexistent.json");
+
+ EXPECT_THAT_ERROR(std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("reading LUSummary from"),
+ HasSubstr("file does not exist"))));
+}
+
+TEST_P(LUSummaryTest, PathIsDirectory) {
+ PathString DirName("test_directory.json");
+
+ auto ExpectedDirPath = makeDirectory(DirName);
+ ASSERT_THAT_EXPECTED(ExpectedDirPath, Succeeded());
+
+ auto Result = readFromFile(DirName);
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("reading LUSummary from"),
+ HasSubstr("path is a directory, not a file"))));
+}
+
+TEST_P(LUSummaryTest, NotJsonExtension) {
+ PathString FileName("test.txt");
+
+ auto ExpectedFilePath = writeJSON("{}", FileName);
+ ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
+
+ auto Result = readFromFile(FileName);
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(
+ AllOf(HasSubstr("reading LUSummary from file"),
+ HasSubstr("failed to read file"),
+ HasSubstr("file does not end with '.json' extension"))));
+}
+
+TEST_P(LUSummaryTest, BrokenSymlink) {
+#ifdef _WIN32
+ GTEST_SKIP() << "Symlink model differs on Windows";
+#endif
+
+ const PathString SymlinkFileName("broken_symlink.json");
+
+ // Create a symlink pointing to a non-existent file
+ auto ExpectedSymlinkPath =
+ makeSymlink("nonexistent_target.json", "broken_symlink.json");
+ ASSERT_THAT_EXPECTED(ExpectedSymlinkPath, Succeeded());
+
+ auto Result = readFromFile(SymlinkFileName);
+
+ EXPECT_THAT_ERROR(std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("reading LUSummary from"),
+ HasSubstr("failed to read file"))));
+}
+
+TEST_P(LUSummaryTest, NoReadPermission) {
+ if (!permissionsAreEnforced()) {
+ GTEST_SKIP() << "File permission checks are not enforced in this "
+ "environment";
+ }
+
+ PathString FileName("no-read-permission.json");
+
+ auto ExpectedFilePath = writeJSON(R"({
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "id_table": [],
+ "linkage_table": [],
+ "data": []
+ })",
+ FileName);
+ ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
+
+ auto PermError = setPermission(FileName, sys::fs::perms::owner_write |
+ sys::fs::perms::owner_exe);
+ ASSERT_THAT_ERROR(std::move(PermError), Succeeded());
+
+ auto Result = readFromFile(FileName);
+
+ EXPECT_THAT_ERROR(std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("reading LUSummary from"),
+ HasSubstr("failed to read file"))));
+
+ // Restore permissions for cleanup
+ auto RestoreError = setPermission(FileName, sys::fs::perms::all_all);
+ EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded());
+}
+
+// ============================================================================
+// JSONFormat::entityDataMapFromJSON() Error Tests
+// ============================================================================
+
+TEST_F(JSONFormatLUSummaryTest, ReadEntitySummaryMissingData) {
+ auto Result = readLUSummaryFromString(R"({
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "target_triple": "arm64-apple-macosx",
+ "type": "LUSummary",
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "NullEntitySummaryForJSONFormatTest",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {}
+ }
+ ]
+ }
+ ]
+ })");
+
+ EXPECT_THAT_EXPECTED(
+ Result,
+ FailedWithMessage(AllOf(
+ HasSubstr("reading LUSummary from file"),
+ HasSubstr("reading SummaryData entries from field 'data'"),
+ HasSubstr("reading SummaryData entry from index '0'"),
+ HasSubstr("reading EntitySummary entries from field 'summary_data'"),
+ HasSubstr("reading EntitySummary entry from index '0'"),
+ HasSubstr("failed to deserialize EntitySummary"),
+ HasSubstr("null EntitySummary data for "
+ "'SummaryName(NullEntitySummaryForJSONFormatTest)'"))));
+}
+
+TEST_F(JSONFormatLUSummaryTest, ReadEntitySummaryMismatchedSummaryName) {
+ auto Result = readLUSummaryFromString(R"({
+ "lu_namespace": [
+ {
+ "kind": "LinkUnit",
+ "name": "test.exe"
+ }
+ ],
+ "target_triple": "arm64-apple-macosx",
+ "type": "LUSummary",
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "MismatchedEntitySummaryForJSONFormatTest",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {}
+ }
+ ]
+ }
+ ]
+ })");
+
+ EXPECT_THAT_EXPECTED(
+ Result,
+ FailedWithMessage(AllOf(
+ HasSubstr("reading LUSummary from file"),
+ HasSubstr("reading SummaryData entries from field 'data'"),
+ HasSubstr("reading SummaryData entry from index '0'"),
+ HasSubstr("reading EntitySummary entries from field 'summary_data'"),
+ HasSubstr("reading EntitySummary entry from index '0'"),
+ HasSubstr("failed to deserialize EntitySummary"),
+ HasSubstr("EntitySummary data for "
+ "'SummaryName(MismatchedEntitySummaryForJSONFormatTest)'"
+ " reports mismatched "
+ "'SummaryName(MismatchedEntitySummaryForJSONFormatTest_"
+ "WrongName)'"))));
+}
+
+// ============================================================================
+// JSONFormat::entityDataMapEntryToJSON() Fatal Tests
+// ============================================================================
+
+TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryMissingData) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::LinkUnit, "test.exe"));
+ LUSummary Summary(llvm::Triple("arm64-apple-macosx"), std::move(NBN));
+
+ NestedBuildNamespace Namespace =
+ NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ EntityId EI = getIdTable(Summary).getId(
+ EntityName{"c:@F at foo", "", std::move(Namespace)});
+
+ SummaryName SN("NullEntitySummaryForJSONFormatTest");
+ getData(Summary)[SN][EI] = nullptr;
+
+ EXPECT_DEATH(
+ { (void)writeLUSummary(Summary, "output.json"); },
+ "JSONFormat - null EntitySummary data for "
+ "'SummaryName\\(NullEntitySummaryForJSONFormatTest\\)'");
+}
+
+TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryMismatchedSummaryName) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::LinkUnit, "test.exe"));
+ LUSummary Summary(llvm::Triple("arm64-apple-macosx"), std::move(NBN));
+
+ NestedBuildNamespace Namespace =
+ NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ EntityId EI = getIdTable(Summary).getId(
+ EntityName{"c:@F at foo", "", std::move(Namespace)});
+
+ SummaryName SN("MismatchedEntitySummaryForJSONFormatTest");
+ getData(Summary)[SN][EI] =
+ std::make_unique<MismatchedEntitySummaryForJSONFormatTest>();
+
+ EXPECT_DEATH(
+ { (void)writeLUSummary(Summary, "output.json"); },
+ "JSONFormat - EntitySummary data for "
+ "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest\\)' "
+ "reports "
+ "mismatched "
+ "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest_WrongName\\)'");
+}
+
+// ============================================================================
+// JSONFormat::writeJSON() Error Tests
+// ============================================================================
+
+TEST_P(LUSummaryTest, WriteFileAlreadyExists) {
+ PathString FileName("existing.json");
+
+ auto ExpectedFilePath = writeJSON("{}", FileName);
+ ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
+
+ auto Result = writeEmpty(FileName);
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("writing LUSummary to file"),
+ HasSubstr("failed to write file"),
+ HasSubstr("file already exists"))));
+}
+
+TEST_P(LUSummaryTest, WriteParentDirectoryNotFound) {
+ PathString FilePath = makePath("nonexistent-dir", "test.json");
+
+ auto Result = GetParam().WriteEmpty(FilePath);
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("writing LUSummary to file"),
+ HasSubstr("failed to write file"),
+ HasSubstr("parent directory does not exist"))));
+}
+
+TEST_P(LUSummaryTest, WriteNotJsonExtension) {
+ auto Result = writeEmpty("test.txt");
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(
+ AllOf(HasSubstr("writing LUSummary to file"),
+ HasSubstr("failed to write file"),
+ HasSubstr("file does not end with '.json' extension"))));
+}
+
+TEST_P(LUSummaryTest, WriteStreamOpenFailure) {
+ if (!permissionsAreEnforced()) {
+ GTEST_SKIP() << "File permission checks are not enforced in this "
+ "environment";
+ }
+
+ const PathString DirName("write-protected-dir");
+
+ auto ExpectedDirPath = makeDirectory(DirName);
+ ASSERT_THAT_EXPECTED(ExpectedDirPath, Succeeded());
+
+ auto PermError = setPermission(DirName, sys::fs::perms::owner_read |
+ sys::fs::perms::owner_exe);
+ ASSERT_THAT_ERROR(std::move(PermError), Succeeded());
+
+ PathString FilePath = makePath(DirName, "test.json");
+
+ auto Result = GetParam().WriteEmpty(FilePath);
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("writing LUSummary to file"),
+ HasSubstr("failed to write file"))));
+
+ // Restore permissions for cleanup
+ auto RestoreError = setPermission(DirName, sys::fs::perms::all_all);
+ EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded());
+}
+
+// ============================================================================
+// JSONFormat::writeLUSummary() Error Tests (LUSummary-only)
+// ============================================================================
+
+TEST_F(JSONFormatLUSummaryTest, WriteEntitySummaryNoFormatInfo) {
+ NestedBuildNamespace NBN(
+ BuildNamespace(BuildNamespaceKind::LinkUnit, "test.exe"));
+ LUSummary Summary(llvm::Triple("arm64-apple-macosx"), std::move(NBN));
+
+ NestedBuildNamespace Namespace =
+ NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ EntityId EI = getIdTable(Summary).getId(
+ EntityName{"c:@F at foo", "", std::move(Namespace)});
+
+ SummaryName UnknownSN("UnregisteredEntitySummaryForJSONFormatTest");
+ getData(Summary)[UnknownSN][EI] =
+ std::make_unique<UnregisteredEntitySummaryForJSONFormatTest>();
+
+ auto Result = writeLUSummary(Summary, "output.json");
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(AllOf(
+ HasSubstr("writing LUSummary to file"),
+ HasSubstr("writing SummaryData entry to index '0'"),
+ HasSubstr("writing EntitySummary entries to field "
+ "'summary_data'"),
+ HasSubstr("writing EntitySummary entry to index '0'"),
+ HasSubstr("writing EntitySummary to field 'entity_summary'"),
+ HasSubstr("failed to serialize EntitySummary"),
+ HasSubstr(
+ "no FormatInfo registered for "
+ "'SummaryName(UnregisteredEntitySummaryForJSONFormatTest)'"))));
+}
+
+} // anonymous namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/TUSummaryTest.cpp b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/TUSummaryTest.cpp
new file mode 100644
index 0000000000000..1c2a890f2ddc9
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/Serialization/JSONFormatTest/TUSummaryTest.cpp
@@ -0,0 +1,445 @@
+//===- TUSummaryTest.cpp --------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Unit tests for SSAF JSON serialization format reading and writing of
+// TUSummary and TUSummaryEncoding.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JSONFormatTest.h"
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Serialization/JSONFormat.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
+
+#include <memory>
+
+using namespace clang::ssaf;
+using namespace llvm;
+using ::testing::AllOf;
+using ::testing::HasSubstr;
+
+namespace {
+
+// ============================================================================
+// TUSummaryOps - Parameterization for TUSummary/TUSummaryEncoding tests
+// ============================================================================
+
+SummaryOps TUSummaryOps{
+ "Resolved", "TUSummary",
+ [](llvm::StringRef FilePath) -> llvm::Error {
+ auto Result = JSONFormat().readTUSummary(FilePath);
+ return Result ? llvm::Error::success() : Result.takeError();
+ },
+ [](llvm::StringRef FilePath) -> llvm::Error {
+ BuildNamespace BN(BuildNamespaceKind::CompilationUnit, "test.cpp");
+ TUSummary S(llvm::Triple("arm64-apple-macosx"), std::move(BN));
+ return JSONFormat().writeTUSummary(S, FilePath);
+ },
+ [](llvm::StringRef InputFilePath,
+ llvm::StringRef OutputFilePath) -> llvm::Error {
+ auto ExpectedS = JSONFormat().readTUSummary(InputFilePath);
+ if (!ExpectedS) {
+ return ExpectedS.takeError();
+ }
+ return JSONFormat().writeTUSummary(*ExpectedS, OutputFilePath);
+ }};
+
+SummaryOps TUSummaryEncodingOps{
+ "Encoding", "TUSummary",
+ [](llvm::StringRef FilePath) -> llvm::Error {
+ auto Result = JSONFormat().readTUSummaryEncoding(FilePath);
+ return Result ? llvm::Error::success() : Result.takeError();
+ },
+ [](llvm::StringRef FilePath) -> llvm::Error {
+ BuildNamespace BN(BuildNamespaceKind::CompilationUnit, "test.cpp");
+ TUSummaryEncoding E(llvm::Triple("arm64-apple-macosx"), std::move(BN));
+ return JSONFormat().writeTUSummaryEncoding(E, FilePath);
+ },
+ [](llvm::StringRef InputFilePath,
+ llvm::StringRef OutputFilePath) -> llvm::Error {
+ auto ExpectedE = JSONFormat().readTUSummaryEncoding(InputFilePath);
+ if (!ExpectedE) {
+ return ExpectedE.takeError();
+ }
+ return JSONFormat().writeTUSummaryEncoding(*ExpectedE, OutputFilePath);
+ }};
+
+// ============================================================================
+// LUSummaryTest Test Fixture
+// ============================================================================
+
+class TUSummaryTest : public SummaryTest {};
+
+INSTANTIATE_TEST_SUITE_P(JSONFormat, TUSummaryTest,
+ ::testing::Values(TUSummaryOps, TUSummaryEncodingOps),
+ [](const ::testing::TestParamInfo<SummaryOps> &Info) {
+ return Info.param.GTestInstantiationSuffix;
+ });
+
+// ============================================================================
+// JSONFormatTUSummaryTest Test Fixture
+// ============================================================================
+
+class JSONFormatTUSummaryTest : public JSONFormatTest {
+protected:
+ llvm::Expected<TUSummary> readTUSummaryFromFile(StringRef FileName) const {
+ PathString FilePath = makePath(FileName);
+ return JSONFormat().readTUSummary(FilePath);
+ }
+
+ llvm::Expected<TUSummary>
+ readTUSummaryFromString(StringRef JSON,
+ StringRef FileName = "test.json") const {
+ auto ExpectedFilePath = writeJSON(JSON, FileName);
+ if (!ExpectedFilePath) {
+ return ExpectedFilePath.takeError();
+ }
+
+ return readTUSummaryFromFile(FileName);
+ }
+
+ llvm::Error writeTUSummary(const TUSummary &Summary,
+ StringRef FileName) const {
+ PathString FilePath = makePath(FileName);
+ return JSONFormat().writeTUSummary(Summary, FilePath);
+ }
+};
+
+// ============================================================================
+// readJSON() Error Tests
+// ============================================================================
+
+TEST_P(TUSummaryTest, NonexistentFile) {
+ auto Result = readFromFile("nonexistent.json");
+
+ EXPECT_THAT_ERROR(std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"),
+ HasSubstr("file does not exist"))));
+}
+
+TEST_P(TUSummaryTest, PathIsDirectory) {
+ PathString DirName("test_directory.json");
+
+ auto ExpectedDirPath = makeDirectory(DirName);
+ ASSERT_THAT_EXPECTED(ExpectedDirPath, Succeeded());
+
+ auto Result = readFromFile(DirName);
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"),
+ HasSubstr("path is a directory, not a file"))));
+}
+
+TEST_P(TUSummaryTest, NotJsonExtension) {
+ PathString FileName("test.txt");
+
+ auto ExpectedFilePath = writeJSON("{}", FileName);
+ ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
+
+ auto Result = readFromFile(FileName);
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(
+ AllOf(HasSubstr("reading TUSummary from file"),
+ HasSubstr("failed to read file"),
+ HasSubstr("file does not end with '.json' extension"))));
+}
+
+TEST_P(TUSummaryTest, BrokenSymlink) {
+#ifdef _WIN32
+ GTEST_SKIP() << "Symlink model differs on Windows";
+#endif
+
+ const PathString SymlinkFileName("broken_symlink.json");
+
+ // Create a symlink pointing to a non-existent file
+ auto ExpectedSymlinkPath =
+ makeSymlink("nonexistent_target.json", SymlinkFileName);
+ ASSERT_THAT_EXPECTED(ExpectedSymlinkPath, Succeeded());
+
+ auto Result = readFromFile(SymlinkFileName);
+
+ EXPECT_THAT_ERROR(std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"),
+ HasSubstr("failed to read file"))));
+}
+
+TEST_P(TUSummaryTest, NoReadPermission) {
+ if (!permissionsAreEnforced()) {
+ GTEST_SKIP() << "File permission checks are not enforced in this "
+ "environment";
+ }
+
+ PathString FileName("no-read-permission.json");
+
+ auto ExpectedFilePath = writeJSON(R"({
+ "tu_namespace": {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ "id_table": [],
+ "linkage_table": [],
+ "data": []
+ })",
+ FileName);
+ ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
+
+ auto PermError = setPermission(FileName, sys::fs::perms::owner_write |
+ sys::fs::perms::owner_exe);
+ ASSERT_THAT_ERROR(std::move(PermError), Succeeded());
+
+ auto Result = readFromFile(FileName);
+
+ EXPECT_THAT_ERROR(std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("reading TUSummary from"),
+ HasSubstr("failed to read file"))));
+
+ // Restore permissions for cleanup
+ auto RestoreError = setPermission(FileName, sys::fs::perms::all_all);
+ EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded());
+}
+
+// ============================================================================
+// JSONFormat::entityDataMapEntryFromJSON() Error Tests
+// ============================================================================
+
+TEST_F(JSONFormatTUSummaryTest, ReadEntitySummaryMissingData) {
+ auto Result = readTUSummaryFromString(R"({
+ "tu_namespace": {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ "target_triple": "arm64-apple-macosx",
+ "type": "TUSummary",
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "NullEntitySummaryForJSONFormatTest",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {}
+ }
+ ]
+ }
+ ]
+ })");
+
+ EXPECT_THAT_EXPECTED(
+ Result,
+ FailedWithMessage(AllOf(
+ HasSubstr("reading TUSummary from file"),
+ HasSubstr("reading SummaryData entries from field 'data'"),
+ HasSubstr("reading SummaryData entry from index '0'"),
+ HasSubstr("reading EntitySummary entries from field 'summary_data'"),
+ HasSubstr("reading EntitySummary entry from index '0'"),
+ HasSubstr("failed to deserialize EntitySummary"),
+ HasSubstr("null EntitySummary data for "
+ "'SummaryName(NullEntitySummaryForJSONFormatTest)'"))));
+}
+
+TEST_F(JSONFormatTUSummaryTest, ReadEntitySummaryMismatchedSummaryName) {
+ auto Result = readTUSummaryFromString(R"({
+ "tu_namespace": {
+ "kind": "CompilationUnit",
+ "name": "test.cpp"
+ },
+ "target_triple": "arm64-apple-macosx",
+ "type": "TUSummary",
+ "id_table": [],
+ "linkage_table": [],
+ "data": [
+ {
+ "summary_name": "MismatchedEntitySummaryForJSONFormatTest",
+ "summary_data": [
+ {
+ "entity_id": 0,
+ "entity_summary": {}
+ }
+ ]
+ }
+ ]
+ })");
+
+ EXPECT_THAT_EXPECTED(
+ Result,
+ FailedWithMessage(AllOf(
+ HasSubstr("reading TUSummary from file"),
+ HasSubstr("reading SummaryData entries from field 'data'"),
+ HasSubstr("reading SummaryData entry from index '0'"),
+ HasSubstr("reading EntitySummary entries from field 'summary_data'"),
+ HasSubstr("reading EntitySummary entry from index '0'"),
+ HasSubstr("failed to deserialize EntitySummary"),
+ HasSubstr("EntitySummary data for "
+ "'SummaryName(MismatchedEntitySummaryForJSONFormatTest)' "
+ "reports "
+ "mismatched "
+ "'SummaryName(MismatchedEntitySummaryForJSONFormatTest_"
+ "WrongName)"
+ "'"))));
+}
+
+// ============================================================================
+// JSONFormat::entityDataMapEntryToJSON() Fatal Tests
+// ============================================================================
+
+TEST_F(JSONFormatTUSummaryTest, WriteEntitySummaryMissingData) {
+ TUSummary Summary(
+ llvm::Triple("arm64-apple-macosx"),
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
+
+ NestedBuildNamespace Namespace =
+ NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ EntityId EI = getIdTable(Summary).getId(
+ EntityName{"c:@F at foo", "", std::move(Namespace)});
+
+ SummaryName SN("NullEntitySummaryForJSONFormatTest");
+ getData(Summary)[SN][EI] = nullptr;
+
+ EXPECT_DEATH(
+ { (void)writeTUSummary(Summary, "output.json"); },
+ "JSONFormat - null EntitySummary data for "
+ "'SummaryName\\(NullEntitySummaryForJSONFormatTest\\)'");
+}
+
+TEST_F(JSONFormatTUSummaryTest, WriteEntitySummaryMismatchedSummaryName) {
+ TUSummary Summary(
+ llvm::Triple("arm64-apple-macosx"),
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
+
+ NestedBuildNamespace Namespace =
+ NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ EntityId EI = getIdTable(Summary).getId(
+ EntityName{"c:@F at foo", "", std::move(Namespace)});
+
+ SummaryName SN("MismatchedEntitySummaryForJSONFormatTest");
+ getData(Summary)[SN][EI] =
+ std::make_unique<MismatchedEntitySummaryForJSONFormatTest>();
+
+ EXPECT_DEATH(
+ { (void)writeTUSummary(Summary, "output.json"); },
+ "JSONFormat - EntitySummary data for "
+ "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest\\)' reports "
+ "mismatched "
+ "'SummaryName\\(MismatchedEntitySummaryForJSONFormatTest_WrongName\\)"
+ "'");
+}
+
+// ============================================================================
+// JSONFormat::writeJSON() Error Tests
+// ============================================================================
+
+TEST_P(TUSummaryTest, WriteFileAlreadyExists) {
+ PathString FileName("existing.json");
+
+ auto ExpectedFilePath = writeJSON("{}", FileName);
+ ASSERT_THAT_EXPECTED(ExpectedFilePath, Succeeded());
+
+ auto Result = writeEmpty(FileName);
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("writing TUSummary to file"),
+ HasSubstr("failed to write file"),
+ HasSubstr("file already exists"))));
+}
+
+TEST_P(TUSummaryTest, WriteParentDirectoryNotFound) {
+ PathString FilePath = makePath("nonexistent-dir", "test.json");
+
+ auto Result = GetParam().WriteEmpty(FilePath);
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("writing TUSummary to file"),
+ HasSubstr("failed to write file"),
+ HasSubstr("parent directory does not exist"))));
+}
+
+TEST_P(TUSummaryTest, WriteNotJsonExtension) {
+ auto Result = writeEmpty("test.txt");
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(
+ AllOf(HasSubstr("writing TUSummary to file"),
+ HasSubstr("failed to write file"),
+ HasSubstr("file does not end with '.json' extension"))));
+}
+
+TEST_P(TUSummaryTest, WriteStreamOpenFailure) {
+ if (!permissionsAreEnforced()) {
+ GTEST_SKIP() << "File permission checks are not enforced in this "
+ "environment";
+ }
+
+ const PathString DirName("write-protected-dir");
+
+ auto ExpectedDirPath = makeDirectory(DirName);
+ ASSERT_THAT_EXPECTED(ExpectedDirPath, Succeeded());
+
+ auto PermError = setPermission(DirName, sys::fs::perms::owner_read |
+ sys::fs::perms::owner_exe);
+ ASSERT_THAT_ERROR(std::move(PermError), Succeeded());
+
+ PathString FilePath = makePath(DirName, "test.json");
+
+ auto Result = GetParam().WriteEmpty(FilePath);
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(AllOf(HasSubstr("writing TUSummary to file"),
+ HasSubstr("failed to write file"))));
+
+ // Restore permissions for cleanup
+ auto RestoreError = setPermission(DirName, sys::fs::perms::all_all);
+ EXPECT_THAT_ERROR(std::move(RestoreError), Succeeded());
+}
+
+// ============================================================================
+// JSONFormat::writeTUSummary() Error Tests (TUSummary-only)
+// ============================================================================
+
+TEST_F(JSONFormatTUSummaryTest, WriteEntitySummaryNoFormatInfo) {
+ TUSummary Summary(
+ llvm::Triple("arm64-apple-macosx"),
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "test.cpp"));
+
+ NestedBuildNamespace Namespace =
+ NestedBuildNamespace::makeCompilationUnit("test.cpp");
+ EntityId EI = getIdTable(Summary).getId(
+ EntityName{"c:@F at foo", "", std::move(Namespace)});
+
+ SummaryName UnknownSN("UnregisteredEntitySummaryForJSONFormatTest");
+ getData(Summary)[UnknownSN][EI] =
+ std::make_unique<UnregisteredEntitySummaryForJSONFormatTest>();
+
+ auto Result = writeTUSummary(Summary, "output.json");
+
+ EXPECT_THAT_ERROR(
+ std::move(Result),
+ FailedWithMessage(AllOf(
+ HasSubstr("writing TUSummary to file"),
+ HasSubstr("writing SummaryData entry to index '0'"),
+ HasSubstr("writing EntitySummary entries to field "
+ "'summary_data'"),
+ HasSubstr("writing EntitySummary entry to index '0'"),
+ HasSubstr("writing EntitySummary to field 'entity_summary'"),
+ HasSubstr("failed to serialize EntitySummary"),
+ HasSubstr(
+ "no FormatInfo registered for "
+ "'SummaryName(UnregisteredEntitySummaryForJSONFormatTest)'"))));
+}
+
+} // anonymous namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/SourceTransformation/EmitterTest.cpp b/clang/unittests/ScalableStaticAnalysis/SourceTransformation/EmitterTest.cpp
new file mode 100644
index 0000000000000..a2a1eac1a1e03
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/SourceTransformation/EmitterTest.cpp
@@ -0,0 +1,81 @@
+//===- EmitterTest.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Basic/Sarif.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/ScalableStaticAnalysis/SourceTransformation/SourceEditEmitter.h"
+#include "clang/ScalableStaticAnalysis/SourceTransformation/TransformationReportEmitter.h"
+#include "gtest/gtest.h"
+#include <vector>
+
+using namespace llvm;
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+
+class RecordingEditEmitter : public SourceEditEmitter {
+public:
+ std::vector<clang::tooling::Replacement> Replacements;
+
+ void addReplacement(clang::tooling::Replacement R) override {
+ Replacements.push_back(std::move(R));
+ }
+};
+
+class RecordingReportEmitter : public TransformationReportEmitter {
+public:
+ struct Entry {
+ std::string RuleId;
+ clang::SarifResultLevel Level;
+ clang::CharSourceRange Range;
+ std::string Message;
+ };
+ std::vector<Entry> Results;
+
+ void addResult(StringRef RuleId, clang::SarifResultLevel Level,
+ clang::CharSourceRange Range, StringRef Message) override {
+ Results.push_back({RuleId.str(), Level, Range, Message.str()});
+ }
+};
+
+TEST(SourceEditEmitterTest, AccumulatesInOrder) {
+ RecordingEditEmitter E;
+ E.addReplacement(clang::tooling::Replacement("a.cpp", 0, 0, "// 1"));
+ E.addReplacement(clang::tooling::Replacement("a.cpp", 10, 0, "// 2"));
+ ASSERT_EQ(E.Replacements.size(), 2u);
+ EXPECT_EQ(E.Replacements[0].getReplacementText(), "// 1");
+ EXPECT_EQ(E.Replacements[1].getReplacementText(), "// 2");
+ EXPECT_EQ(E.Replacements[0].getOffset(), 0u);
+ EXPECT_EQ(E.Replacements[1].getOffset(), 10u);
+}
+
+TEST(TransformationReportEmitterTest, AccumulatesInOrder) {
+ RecordingReportEmitter R;
+ R.addResult("rule-a", clang::SarifResultLevel::Note, clang::CharSourceRange{},
+ "first");
+ R.addResult("rule-b", clang::SarifResultLevel::Warning,
+ clang::CharSourceRange{}, "second");
+ ASSERT_EQ(R.Results.size(), 2u);
+ EXPECT_EQ(R.Results[0].RuleId, "rule-a");
+ EXPECT_EQ(R.Results[0].Level, clang::SarifResultLevel::Note);
+ EXPECT_EQ(R.Results[0].Message, "first");
+ EXPECT_EQ(R.Results[1].RuleId, "rule-b");
+ EXPECT_EQ(R.Results[1].Level, clang::SarifResultLevel::Warning);
+ EXPECT_EQ(R.Results[1].Message, "second");
+}
+
+TEST(TransformationReportEmitterTest, AcceptsInvalidRange) {
+ RecordingReportEmitter R;
+ R.addResult("rule", clang::SarifResultLevel::Note, clang::CharSourceRange{},
+ "no-location");
+ ASSERT_EQ(R.Results.size(), 1u);
+ EXPECT_FALSE(R.Results[0].Range.isValid());
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/SourceTransformation/RegistryTest.cpp b/clang/unittests/ScalableStaticAnalysis/SourceTransformation/RegistryTest.cpp
new file mode 100644
index 0000000000000..3fa24920c20a4
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/SourceTransformation/RegistryTest.cpp
@@ -0,0 +1,78 @@
+//===- RegistryTest.cpp ---------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestFixture.h"
+#include "clang/ScalableStaticAnalysis/SourceTransformation/Transformation.h"
+#include "clang/ScalableStaticAnalysis/SourceTransformation/TransformationRegistry.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace llvm;
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+
+class StubEditEmitter : public SourceEditEmitter {
+public:
+ void addReplacement(clang::tooling::Replacement) override {}
+};
+
+class StubReportEmitter : public TransformationReportEmitter {
+public:
+ void addResult(StringRef, clang::SarifResultLevel, clang::CharSourceRange,
+ StringRef) override {}
+};
+
+class StubTransformation : public Transformation {
+public:
+ using Transformation::Transformation;
+};
+
+} // namespace
+
+static TransformationRegistry::Add<StubTransformation>
+ RegisterStubTransformation("stub-transformation",
+ "A transformation for testing");
+
+namespace {
+
+class TransformationRegistryTest : public TestFixture {};
+
+TEST_F(TransformationRegistryTest, isTransformationRegistered) {
+ EXPECT_FALSE(isTransformationRegistered("not-a-transformation"));
+ EXPECT_TRUE(isTransformationRegistered("stub-transformation"));
+}
+
+TEST_F(TransformationRegistryTest, makeTransformation) {
+ WPASuite Suite = makeWPASuite();
+ StubEditEmitter Edits;
+ StubReportEmitter Report;
+ std::unique_ptr<Transformation> T =
+ makeTransformation("stub-transformation", Suite, Edits, Report);
+ EXPECT_NE(T, nullptr);
+}
+
+TEST_F(TransformationRegistryTest, EnumeratingRegistryEntries) {
+ auto Entries = TransformationRegistry::entries();
+ EXPECT_TRUE(llvm::any_of(Entries, [](const auto &Entry) {
+ return StringRef(Entry.getName()) == "stub-transformation";
+ }));
+}
+
+TEST_F(TransformationRegistryTest, PrintAvailableTransformations) {
+ std::string Buffer;
+ raw_string_ostream OS(Buffer);
+ printAvailableTransformations(OS);
+ EXPECT_NE(StringRef(Buffer).find("stub-transformation"), StringRef::npos);
+ EXPECT_NE(StringRef(Buffer).find("A transformation for testing"),
+ StringRef::npos);
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/SummaryData/SummaryDataTest.cpp b/clang/unittests/ScalableStaticAnalysis/SummaryData/SummaryDataTest.cpp
new file mode 100644
index 0000000000000..e8137f3bac308
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/SummaryData/SummaryDataTest.cpp
@@ -0,0 +1,398 @@
+//===- SummaryDataTest.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../TestFixture.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/LUSummaryConsumer.h"
+#include "clang/ScalableStaticAnalysis/Core/SummaryData/SummaryDataBuilderRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+#include <memory>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+
+// ---------------------------------------------------------------------------
+// Instance counter
+// ---------------------------------------------------------------------------
+
+static int NextSummaryInstanceId = 0;
+
+// ---------------------------------------------------------------------------
+// Entity summaries
+// ---------------------------------------------------------------------------
+
+class Analysis1EntitySummary final : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis1");
+ }
+};
+
+class Analysis2EntitySummary final : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis2");
+ }
+};
+
+class Analysis3EntitySummary final : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis3");
+ }
+};
+
+class Analysis4EntitySummary final : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis4");
+ }
+};
+
+// ---------------------------------------------------------------------------
+// Data
+// ---------------------------------------------------------------------------
+
+class Analysis1Data final : public SummaryData {
+public:
+ static SummaryName summaryName() { return SummaryName("Analysis1"); }
+ std::vector<std::pair<EntityId, int>> Entries;
+ bool WasFinalized = false;
+};
+
+class Analysis2Data final : public SummaryData {
+public:
+ static SummaryName summaryName() { return SummaryName("Analysis2"); }
+ std::vector<std::pair<EntityId, int>> Entries;
+ bool WasFinalized = false;
+};
+
+// No builder or registration for Analysis3. Data for Analysis3 is inserted
+// into the LUSummary to verify the consumer silently skips it.
+class Analysis3Data final : public SummaryData {
+public:
+ static SummaryName summaryName() { return SummaryName("Analysis3"); }
+};
+
+// Analysis4 has a registered builder but no data is inserted into the
+// LUSummary, so the builder is never invoked and getData returns nullptr.
+class Analysis4Data final : public SummaryData {
+public:
+ static SummaryName summaryName() { return SummaryName("Analysis4"); }
+ std::vector<std::pair<EntityId, int>> Entries;
+ bool WasFinalized = false;
+};
+
+// ---------------------------------------------------------------------------
+// Builder destruction flags (reset in SetUp)
+// ---------------------------------------------------------------------------
+
+static bool Analysis1BuilderWasDestroyed = false;
+static bool Analysis2BuilderWasDestroyed = false;
+static bool Analysis4BuilderWasDestroyed = false;
+
+// ---------------------------------------------------------------------------
+// Builders
+// ---------------------------------------------------------------------------
+
+class Analysis1Builder final
+ : public SummaryDataBuilder<Analysis1Data, Analysis1EntitySummary> {
+public:
+ ~Analysis1Builder() { Analysis1BuilderWasDestroyed = true; }
+
+ void addSummary(EntityId Id,
+ std::unique_ptr<Analysis1EntitySummary> S) override {
+ getData().Entries.push_back({Id, S->InstanceId});
+ }
+
+ void finalize() override { getData().WasFinalized = true; }
+};
+
+static SummaryDataBuilderRegistry::Add<Analysis1Builder>
+ RegAnalysis1("Builder for Analysis1");
+
+class Analysis2Builder final
+ : public SummaryDataBuilder<Analysis2Data, Analysis2EntitySummary> {
+public:
+ ~Analysis2Builder() { Analysis2BuilderWasDestroyed = true; }
+
+ void addSummary(EntityId Id,
+ std::unique_ptr<Analysis2EntitySummary> S) override {
+ getData().Entries.push_back({Id, S->InstanceId});
+ }
+
+ void finalize() override { getData().WasFinalized = true; }
+};
+
+static SummaryDataBuilderRegistry::Add<Analysis2Builder>
+ RegAnalysis2("Builder for Analysis2");
+
+class Analysis4Builder final
+ : public SummaryDataBuilder<Analysis4Data, Analysis4EntitySummary> {
+public:
+ ~Analysis4Builder() { Analysis4BuilderWasDestroyed = true; }
+
+ void addSummary(EntityId Id,
+ std::unique_ptr<Analysis4EntitySummary> S) override {
+ getData().Entries.push_back({Id, S->InstanceId});
+ }
+
+ void finalize() override { getData().WasFinalized = true; }
+};
+
+static SummaryDataBuilderRegistry::Add<Analysis4Builder>
+ RegAnalysis4("Builder for Analysis4");
+
+// ---------------------------------------------------------------------------
+// Fixture
+// ---------------------------------------------------------------------------
+
+class LUSummaryConsumerTest : public TestFixture {
+protected:
+ static constexpr EntityLinkage ExternalLinkage =
+ EntityLinkage(EntityLinkageType::External);
+
+ void SetUp() override {
+ NextSummaryInstanceId = 0;
+ Analysis1BuilderWasDestroyed = false;
+ Analysis2BuilderWasDestroyed = false;
+ Analysis4BuilderWasDestroyed = false;
+ }
+
+ std::unique_ptr<LUSummary> makeLUSummary() {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ return std::make_unique<LUSummary>(llvm::Triple("arm64-apple-macosx"),
+ std::move(NS));
+ }
+
+ EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ EntityName Name(USR.str(), "", NS);
+ EntityId Id = getIdTable(LU).getId(Name);
+ getLinkageTable(LU).insert({Id, ExternalLinkage});
+ return Id;
+ }
+
+ static bool hasEntry(const std::vector<std::pair<EntityId, int>> &Entries,
+ EntityId Id, int InstanceId) {
+ return llvm::is_contained(Entries, std::make_pair(Id, InstanceId));
+ }
+
+ /// Inserts a freshly constructed SummaryT for the given entity and returns
+ /// the summary's InstanceId so the test can verify delivery later.
+ template <typename SummaryT>
+ int insertSummary(LUSummary &LU, llvm::StringRef SN, EntityId Id) {
+ auto S = std::make_unique<SummaryT>();
+ int InstanceId = S->InstanceId;
+ getData(LU)[SummaryName(SN.str())][Id] = std::move(S);
+ return InstanceId;
+ }
+};
+
+// ---------------------------------------------------------------------------
+// Tests
+// ---------------------------------------------------------------------------
+
+TEST(SummaryDataBuilderRegistryTest, BuilderIsRegistered) {
+ EXPECT_FALSE(SummaryDataBuilderRegistry::contains("AnalysisNonExisting"));
+ EXPECT_TRUE(SummaryDataBuilderRegistry::contains("Analysis1"));
+ EXPECT_TRUE(SummaryDataBuilderRegistry::contains("Analysis2"));
+ EXPECT_TRUE(SummaryDataBuilderRegistry::contains("Analysis4"));
+}
+
+TEST(SummaryDataBuilderRegistryTest, BuilderCanBeInstantiated) {
+ EXPECT_EQ(SummaryDataBuilderRegistry::instantiate("AnalysisNonExisting"),
+ nullptr);
+ EXPECT_NE(SummaryDataBuilderRegistry::instantiate("Analysis1"), nullptr);
+ EXPECT_NE(SummaryDataBuilderRegistry::instantiate("Analysis2"), nullptr);
+ EXPECT_NE(SummaryDataBuilderRegistry::instantiate("Analysis4"), nullptr);
+}
+
+// run() — processes all registered analyses present in the LUSummary.
+TEST_F(LUSummaryConsumerTest, RunAll) {
+ auto LU = makeLUSummary();
+ const auto E1 = addEntity(*LU, "Entity1");
+ const auto E2 = addEntity(*LU, "Entity2");
+ const auto E3 = addEntity(*LU, "Entity3");
+
+ int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
+ int s1b = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E2);
+ int s2a = insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
+ int s2b = insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E3);
+
+ // No registered builder — Analysis3 data silently skipped.
+ (void)insertSummary<Analysis3EntitySummary>(*LU, "Analysis3", E1);
+
+ LUSummaryConsumer Consumer(std::move(LU));
+ SummaryDataStore Store = std::move(Consumer).run();
+
+ {
+ auto Data1OrErr = Store.get<Analysis1Data>();
+ ASSERT_THAT_EXPECTED(Data1OrErr, llvm::Succeeded());
+ auto &Data1 = *Data1OrErr;
+
+ EXPECT_EQ(Data1.Entries.size(), 2u);
+ EXPECT_TRUE(hasEntry(Data1.Entries, E1, s1a));
+ EXPECT_TRUE(hasEntry(Data1.Entries, E2, s1b));
+ EXPECT_TRUE(Data1.WasFinalized);
+ EXPECT_TRUE(Analysis1BuilderWasDestroyed);
+
+ // take() transfers ownership — subsequent get() returns an error.
+ auto Take1OrErr = Store.take<Analysis1Data>();
+ ASSERT_THAT_EXPECTED(Take1OrErr, llvm::Succeeded());
+ EXPECT_NE(*Take1OrErr, nullptr);
+ EXPECT_THAT_EXPECTED(Store.get<Analysis1Data>(), llvm::Failed());
+ }
+
+ {
+ auto Data2OrErr = Store.get<Analysis2Data>();
+ ASSERT_THAT_EXPECTED(Data2OrErr, llvm::Succeeded());
+ auto &Data2 = *Data2OrErr;
+ EXPECT_EQ(Data2.Entries.size(), 2u);
+ EXPECT_TRUE(hasEntry(Data2.Entries, E2, s2a));
+ EXPECT_TRUE(hasEntry(Data2.Entries, E3, s2b));
+ EXPECT_TRUE(Data2.WasFinalized);
+ EXPECT_TRUE(Analysis2BuilderWasDestroyed);
+
+ auto Take2OrErr = Store.take<Analysis2Data>();
+ ASSERT_THAT_EXPECTED(Take2OrErr, llvm::Succeeded());
+ EXPECT_NE(*Take2OrErr, nullptr);
+ EXPECT_THAT_EXPECTED(Store.get<Analysis2Data>(), llvm::Failed());
+ }
+
+ // Unregistered — not present in store.
+ EXPECT_THAT_EXPECTED(Store.get<Analysis3Data>(), llvm::Failed());
+
+ // Registered builder but no data in LUSummary — not present in store.
+ EXPECT_THAT_EXPECTED(Store.get<Analysis4Data>(), llvm::Failed());
+ EXPECT_FALSE(Analysis4BuilderWasDestroyed);
+}
+
+// run(names) — processes only the analyses for the given names.
+TEST_F(LUSummaryConsumerTest, RunByName) {
+ auto LU = makeLUSummary();
+ const auto E1 = addEntity(*LU, "Entity1");
+ const auto E2 = addEntity(*LU, "Entity2");
+
+ int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
+ insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
+
+ LUSummaryConsumer Consumer(std::move(LU));
+ auto StoreOrErr = Consumer.run({SummaryName("Analysis1")});
+ ASSERT_THAT_EXPECTED(StoreOrErr, llvm::Succeeded());
+
+ // Analysis1 was requested and has data — present.
+ auto Data1OrErr = StoreOrErr->get<Analysis1Data>();
+ ASSERT_THAT_EXPECTED(Data1OrErr, llvm::Succeeded());
+ auto &Data1 = *Data1OrErr;
+ EXPECT_EQ(Data1.Entries.size(), 1u);
+ EXPECT_TRUE(hasEntry(Data1.Entries, E1, s1a));
+ EXPECT_TRUE(Data1.WasFinalized);
+
+ // Analysis2 was not requested — not present even though data exists.
+ EXPECT_THAT_EXPECTED(StoreOrErr->get<Analysis2Data>(), llvm::Failed());
+}
+
+// run(names) — error when a requested name has no data in LUSummary.
+TEST_F(LUSummaryConsumerTest, RunByNameErrorMissingData) {
+ auto LU = makeLUSummary();
+ LUSummaryConsumer Consumer(std::move(LU));
+
+ EXPECT_THAT_EXPECTED(Consumer.run({SummaryName("Analysis1")}),
+ llvm::Failed());
+}
+
+// run(names) — error when a requested name has no registered builder.
+TEST_F(LUSummaryConsumerTest, RunByNameErrorMissingBuilder) {
+ auto LU = makeLUSummary();
+ const auto E1 = addEntity(*LU, "Entity1");
+ insertSummary<Analysis3EntitySummary>(*LU, "Analysis3", E1);
+
+ LUSummaryConsumer Consumer(std::move(LU));
+
+ // Analysis3 has data but no registered builder.
+ EXPECT_THAT_EXPECTED(Consumer.run({SummaryName("Analysis3")}),
+ llvm::Failed());
+}
+
+// run<DataTs...>() — type-safe subset.
+TEST_F(LUSummaryConsumerTest, RunByType) {
+ auto LU = makeLUSummary();
+ const auto E1 = addEntity(*LU, "Entity1");
+ const auto E2 = addEntity(*LU, "Entity2");
+
+ int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
+ insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
+
+ LUSummaryConsumer Consumer(std::move(LU));
+ auto StoreOrErr = Consumer.run<Analysis1Data>();
+ ASSERT_THAT_EXPECTED(StoreOrErr, llvm::Succeeded());
+
+ // Analysis1 was requested — present.
+ auto Data1OrErr = StoreOrErr->get<Analysis1Data>();
+ ASSERT_THAT_EXPECTED(Data1OrErr, llvm::Succeeded());
+ auto &Data1 = *Data1OrErr;
+ EXPECT_EQ(Data1.Entries.size(), 1u);
+ EXPECT_TRUE(hasEntry(Data1.Entries, E1, s1a));
+ EXPECT_TRUE(Data1.WasFinalized);
+
+ // Analysis2 was not requested — not present even though data exists.
+ EXPECT_THAT_EXPECTED(StoreOrErr->get<Analysis2Data>(), llvm::Failed());
+}
+
+// run<DataTs...>() — error when a requested type has no data in LUSummary.
+TEST_F(LUSummaryConsumerTest, RunByTypeErrorMissingData) {
+ auto LU = makeLUSummary();
+ LUSummaryConsumer Consumer(std::move(LU));
+
+ EXPECT_THAT_EXPECTED(Consumer.run<Analysis1Data>(), llvm::Failed());
+}
+
+// contains() — present entries return true; absent entries return false.
+TEST_F(LUSummaryConsumerTest, Contains) {
+ auto LU = makeLUSummary();
+ const auto E1 = addEntity(*LU, "Entity1");
+ insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
+
+ LUSummaryConsumer Consumer(std::move(LU));
+ SummaryDataStore Store = std::move(Consumer).run();
+
+ // Type-safe variant.
+ EXPECT_TRUE(Store.contains<Analysis1Data>());
+ EXPECT_FALSE(Store.contains<Analysis2Data>());
+
+ // Name-based variant.
+ EXPECT_TRUE(Store.contains(SummaryName("Analysis1")));
+ EXPECT_FALSE(Store.contains(SummaryName("Analysis2")));
+
+ // After take(), contains() returns false.
+ ASSERT_THAT_EXPECTED(Store.take<Analysis1Data>(), llvm::Succeeded());
+ EXPECT_FALSE(Store.contains<Analysis1Data>());
+ EXPECT_FALSE(Store.contains(SummaryName("Analysis1")));
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/SummaryNameTest.cpp b/clang/unittests/ScalableStaticAnalysis/SummaryNameTest.cpp
new file mode 100644
index 0000000000000..c88071491a953
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/SummaryNameTest.cpp
@@ -0,0 +1,67 @@
+//===- SummaryNameTest.cpp ------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/Support/FormatProviders.h"
+#include "llvm/Support/FormatVariadic.h"
+#include "llvm/Support/raw_ostream.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+
+TEST(SummaryNameTest, Equality) {
+ const auto TestAnalysis1 = SummaryName("TestAnalysis1");
+ const auto Alternative1 = SummaryName("TestAnalysis1");
+ const auto TestAnalysis2 = SummaryName("TestAnalysis2");
+
+ EXPECT_EQ(TestAnalysis1, Alternative1); // Idempotency.
+ EXPECT_NE(Alternative1, TestAnalysis2); // Inequality.
+}
+
+TEST(SummaryNameTest, LessThan) {
+ const auto TestAnalysis1 = SummaryName("TestAnalysis1");
+ const auto Alternative1 = SummaryName("TestAnalysis1");
+
+ const auto TestAnalysis2 = SummaryName("TestAnalysis2");
+ const auto TestAnalysis3 = SummaryName("TestAnalysis3");
+
+ // Equivalency.
+ EXPECT_FALSE(TestAnalysis1 < Alternative1);
+ EXPECT_FALSE(Alternative1 < TestAnalysis1);
+
+ // Transitivity.
+ EXPECT_LT(TestAnalysis1, TestAnalysis2);
+ EXPECT_LT(TestAnalysis2, TestAnalysis3);
+ EXPECT_LT(TestAnalysis1, TestAnalysis3);
+}
+
+TEST(SummaryNameTest, Str) {
+ const auto Handle1 = SummaryName("TestAnalysis1");
+ const auto Handle2 = SummaryName("TestAnalysis1");
+ const auto Handle3 = SummaryName("TestAnalysis2");
+
+ EXPECT_EQ(Handle1.str(), "TestAnalysis1");
+ EXPECT_EQ(Handle2.str(), "TestAnalysis1");
+ EXPECT_EQ(Handle3.str(), "TestAnalysis2");
+}
+
+TEST(SummaryNameTest, FormatProvider) {
+ EXPECT_EQ(llvm::formatv("{0}", SummaryName("MyAnalysis")).str(),
+ "SummaryName(MyAnalysis)");
+}
+
+TEST(SummaryNameTest, StreamOutput) {
+ std::string S;
+ llvm::raw_string_ostream(S) << SummaryName("MyAnalysis");
+ EXPECT_EQ(S, "SummaryName(MyAnalysis)");
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/TUSummaryBuilderTest.cpp b/clang/unittests/ScalableStaticAnalysis/TUSummaryBuilderTest.cpp
new file mode 100644
index 0000000000000..c6a7a7b531be3
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/TUSummaryBuilderTest.cpp
@@ -0,0 +1,404 @@
+//===- TUSummaryBuilderTest.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
+#include "FindDecl.h"
+#include "TestFixture.h"
+#include "clang/Frontend/SSAFOptions.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/EntitySummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
+#include "clang/Tooling/Tooling.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "gmock/gmock.h"
+#include "gtest/gtest.h"
+#include <memory>
+#include <type_traits>
+
+using namespace clang;
+using namespace ssaf;
+
+using llvm::SmallVector;
+using testing::Field;
+using testing::Optional;
+using testing::UnorderedElementsAre;
+
+struct SummaryResult {
+ EntitySummary *Summary;
+ bool Inserted;
+};
+
+template <class ConcreteEntitySummary>
+[[nodiscard]]
+static auto addSummaryTo(TUSummaryBuilder &Builder, EntityId ID,
+ ConcreteEntitySummary Summary) {
+ static_assert(std::is_base_of_v<EntitySummary, ConcreteEntitySummary>);
+ auto NewSummary = std::make_unique<ConcreteEntitySummary>(std::move(Summary));
+ SummaryName Name = NewSummary->getSummaryName();
+ auto [Place, Inserted] = Builder.addSummary(ID, std::move(NewSummary));
+ return std::pair{Name, SummaryResult{Place, Inserted}};
+}
+
+namespace {
+
+// Mock EntitySummary classes for testing
+struct MockSummaryData1 final : public EntitySummary {
+ explicit MockSummaryData1(int Value) : Value(Value) {}
+ SummaryName getSummaryName() const override {
+ return SummaryName("MockSummary1");
+ }
+ int Value;
+};
+
+struct MockSummaryData2 final : public EntitySummary {
+ explicit MockSummaryData2(std::string Text) : Text(std::move(Text)) {}
+ SummaryName getSummaryName() const override {
+ return SummaryName("MockSummary2");
+ }
+ std::string Text;
+};
+
+struct MockSummaryData3 final : public EntitySummary {
+ explicit MockSummaryData3(bool Flag) : Flag(Flag) {}
+ SummaryName getSummaryName() const override {
+ return SummaryName("MockSummary3");
+ }
+ bool Flag;
+};
+
+void PrintTo(const MockSummaryData1 &S, std::ostream *OS) {
+ *OS << "MockSummaryData1(" << S.getSummaryName().str().str() << ")";
+}
+void PrintTo(const MockSummaryData2 &S, std::ostream *OS) {
+ *OS << "MockSummaryData2(" << S.getSummaryName().str().str() << ")";
+}
+void PrintTo(const MockSummaryData3 &S, std::ostream *OS) {
+ *OS << "MockSummaryData3(" << S.getSummaryName().str().str() << ")";
+}
+
+struct TUSummaryBuilderTest : ssaf::TestFixture {
+ SSAFOptions Opts;
+ TUSummary Summary{
+ llvm::Triple("arm64-apple-macosx"),
+ BuildNamespace(BuildNamespaceKind::CompilationUnit, "Mock.cpp")};
+ TUSummaryBuilder Builder{Summary, Opts};
+ TUSummaryExtractor Extractor{Builder};
+
+ [[nodiscard]] EntityId addTestEntity(llvm::StringRef USR) {
+ return getIdTable(Summary).getId(
+ EntityName(USR, /*Suffix=*/"", /*Namespace=*/{}));
+ }
+
+ [[nodiscard]] static SmallVector<SummaryName>
+ summaryNames(const TUSummary &Summary) {
+ return llvm::to_vector(llvm::make_first_range(getData(Summary)));
+ }
+
+ [[nodiscard]] static SmallVector<EntityId>
+ entitiesOfSummary(const TUSummary &Summary, const SummaryName &Name) {
+ const auto &MappingIt = getData(Summary).find(Name);
+ if (MappingIt == getData(Summary).end())
+ return {};
+ return llvm::to_vector(llvm::make_first_range(MappingIt->second));
+ }
+
+ template <class ConcreteSummaryData>
+ [[nodiscard]] static std::optional<ConcreteSummaryData>
+ getAsEntitySummary(const TUSummary &Summary, const SummaryName &Name,
+ EntityId E) {
+ static_assert(std::is_base_of_v<EntitySummary, ConcreteSummaryData>);
+ const auto &MappingIt = getData(Summary).find(Name);
+ if (MappingIt == getData(Summary).end())
+ return std::nullopt;
+ auto SummaryIt = MappingIt->second.find(E);
+ if (SummaryIt == MappingIt->second.end())
+ return std::nullopt;
+ assert(Name == SummaryIt->second->getSummaryName());
+ return static_cast<const ConcreteSummaryData &>(*SummaryIt->second);
+ }
+};
+
+TEST_F(TUSummaryBuilderTest, AddEntity) {
+ EntityName EN1("c:@F at foo", "", /*Namespace=*/{});
+ EntityName EN2("c:@F at bar", "", /*Namespace=*/{});
+
+ EntityIdTable &IdTable = getIdTable(Summary);
+
+ EntityId ID = IdTable.getId(EN1);
+ EntityId IDAlias = IdTable.getId(EN1);
+ EXPECT_EQ(ID, IDAlias); // Idenpotency
+
+ EntityId ID2 = IdTable.getId(EN2);
+ EXPECT_NE(ID, ID2);
+ EXPECT_NE(IDAlias, ID2);
+
+ EXPECT_EQ(IdTable.count(), 2U);
+ EXPECT_TRUE(IdTable.contains(EN1));
+ EXPECT_TRUE(IdTable.contains(EN2));
+}
+
+TEST_F(TUSummaryBuilderTest, TUSummaryBuilderAddSingleSummary) {
+ EntityId ID = addTestEntity("c:@F at foo");
+ auto [Name, Res] = addSummaryTo(Builder, ID, MockSummaryData1(10));
+ ASSERT_TRUE(Res.Inserted);
+ ASSERT_TRUE(Res.Summary);
+
+ // Should have a summary type with an entity.
+ EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name));
+ EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID));
+
+ EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID),
+ Optional(Field(&MockSummaryData1::Value, 10)));
+}
+
+TEST_F(TUSummaryBuilderTest, AddMultipleSummariesToSameEntity) {
+ EntityId ID = addTestEntity("c:@F at foo");
+
+ // Add different summary types to the same entity.
+ auto [Name1, Res1] = addSummaryTo(Builder, ID, MockSummaryData1(42));
+ auto [Name2, Res2] = addSummaryTo(Builder, ID, MockSummaryData2("test data"));
+ auto [Name3, Res3] = addSummaryTo(Builder, ID, MockSummaryData3(true));
+ ASSERT_TRUE(Res1.Inserted);
+ ASSERT_TRUE(Res2.Inserted);
+ ASSERT_TRUE(Res3.Inserted);
+ ASSERT_TRUE(Res1.Summary);
+ ASSERT_TRUE(Res2.Summary);
+ ASSERT_TRUE(Res3.Summary);
+
+ // All Names must be unique
+ EXPECT_EQ((std::set<SummaryName>{Name1, Name2, Name3}.size()), 3U);
+
+ // Should have 3 summary type with the same entity.
+ EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name1, Name2, Name3));
+ EXPECT_THAT(entitiesOfSummary(Summary, Name1), UnorderedElementsAre(ID));
+ EXPECT_THAT(entitiesOfSummary(Summary, Name2), UnorderedElementsAre(ID));
+ EXPECT_THAT(entitiesOfSummary(Summary, Name3), UnorderedElementsAre(ID));
+
+ EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name1, ID),
+ Optional(Field(&MockSummaryData1::Value, 42)));
+ EXPECT_THAT(getAsEntitySummary<MockSummaryData2>(Summary, Name2, ID),
+ Optional(Field(&MockSummaryData2::Text, "test data")));
+ EXPECT_THAT(getAsEntitySummary<MockSummaryData3>(Summary, Name3, ID),
+ Optional(Field(&MockSummaryData3::Flag, true)));
+}
+
+TEST_F(TUSummaryBuilderTest, AddSameSummaryTypeToMultipleEntities) {
+ EntityId ID1 = addTestEntity("c:@F at foo");
+ EntityId ID2 = addTestEntity("c:@F at bar");
+ EntityId ID3 = addTestEntity("c:@F at baz");
+
+ // Add the same summary type to different entities.
+ auto [Name1, Res1] = addSummaryTo(Builder, ID1, MockSummaryData1(1));
+ auto [Name2, Res2] = addSummaryTo(Builder, ID2, MockSummaryData1(2));
+ auto [Name3, Res3] = addSummaryTo(Builder, ID3, MockSummaryData1(3));
+ ASSERT_TRUE(Res1.Inserted);
+ ASSERT_TRUE(Res2.Inserted);
+ ASSERT_TRUE(Res3.Inserted);
+ ASSERT_TRUE(Res1.Summary);
+ ASSERT_TRUE(Res2.Summary);
+ ASSERT_TRUE(Res3.Summary);
+
+ // All 3 should be the same summary type.
+ EXPECT_THAT((llvm::ArrayRef{Name1, Name2, Name3}), testing::Each(Name1));
+
+ // Should have only 1 summary type with 3 entities.
+ EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name1));
+ EXPECT_THAT(entitiesOfSummary(Summary, Name1),
+ UnorderedElementsAre(ID1, ID2, ID3));
+
+ EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name1, ID1),
+ Optional(Field(&MockSummaryData1::Value, 1)));
+ EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name2, ID2),
+ Optional(Field(&MockSummaryData1::Value, 2)));
+ EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name3, ID3),
+ Optional(Field(&MockSummaryData1::Value, 3)));
+}
+
+TEST_F(TUSummaryBuilderTest, AddConflictingSummaryToSameEntity) {
+ EntityId ID = addTestEntity("c:@F at foo");
+
+ auto [Name, Res] = addSummaryTo(Builder, ID, MockSummaryData1(10));
+ ASSERT_TRUE(Res.Inserted);
+ ASSERT_TRUE(Res.Summary);
+
+ // Check the initial value.
+ EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name));
+ EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID));
+ EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID),
+ Optional(Field(&MockSummaryData1::Value, 10)));
+
+ // This is a different summary of the same kind.
+ auto NewSummary = std::make_unique<MockSummaryData1>(20);
+ ASSERT_EQ(NewSummary->getSummaryName(), Name);
+
+ // Let's add this different summary.
+ // This should keep the map intact and give us the existing entity summary.
+ auto [Slot, Inserted] = Builder.addSummary(ID, std::move(NewSummary));
+ ASSERT_FALSE(Inserted);
+ ASSERT_TRUE(Slot);
+
+ // Check that the summary object is not consumed and remained the same.
+ ASSERT_TRUE(NewSummary);
+ ASSERT_EQ(static_cast<MockSummaryData1 *>(NewSummary.get())->Value, 20);
+
+ // Check that the Slot refers to the existing entity summary.
+ ASSERT_EQ(Slot->getSummaryName(), Name);
+ ASSERT_EQ(static_cast<MockSummaryData1 *>(Slot)->Value, 10);
+
+ // Check that the values remained the same.
+ EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name));
+ EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID));
+ EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID),
+ Optional(Field(&MockSummaryData1::Value, 10)));
+
+ // We can update the existing summary.
+ static_cast<MockSummaryData1 *>(Res.Summary)->Value = 30;
+
+ // Check that the values remained the same except what we updated.
+ EXPECT_THAT(summaryNames(Summary), UnorderedElementsAre(Name));
+ EXPECT_THAT(entitiesOfSummary(Summary, Name), UnorderedElementsAre(ID));
+ EXPECT_THAT(getAsEntitySummary<MockSummaryData1>(Summary, Name, ID),
+ Optional(Field(&MockSummaryData1::Value, 30)));
+}
+
+struct TUSummaryBuilderLinkageTest : TUSummaryBuilderTest {
+ std::unique_ptr<ASTUnit> AST;
+ static constexpr auto Internal = EntityLinkageType::Internal;
+ static constexpr auto External = EntityLinkageType::External;
+
+ const FunctionDecl *findFnByName(StringRef Name) {
+ return ssaf::findFnByName(Name, AST->getASTContext());
+ }
+
+ std::optional<EntityLinkageType> getLinkageFor(std::optional<EntityId> ID) {
+ if (!ID)
+ return std::nullopt;
+ if (auto It = getLinkageTable(Summary).find(*ID);
+ It != getLinkageTable(Summary).end())
+ return It->second.getLinkage();
+ return std::nullopt;
+ }
+};
+
+TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkage) {
+ AST = tooling::buildASTFromCode("static void target() {}");
+ const FunctionDecl *Fn = findFnByName("target");
+ ASSERT_TRUE(Fn);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), Internal);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, HasExternalLinkage) {
+ AST = tooling::buildASTFromCode("void target() {}");
+ const FunctionDecl *Fn = findFnByName("target");
+ ASSERT_TRUE(Fn);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, HasExternalLinkageWithInline) {
+ AST = tooling::buildASTFromCode("inline void target() {}");
+ const FunctionDecl *Fn = findFnByName("target");
+ ASSERT_TRUE(Fn);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, HasInternalLinkageWithStaticInline) {
+ AST = tooling::buildASTFromCode("static inline void target() {}");
+ const FunctionDecl *Fn = findFnByName("target");
+ ASSERT_TRUE(Fn);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(Fn)), Internal);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, ConstVolatileGlobalHasExternalLinkage) {
+ AST = tooling::buildASTFromCode("namespace ns {\n"
+ " const volatile int glob = 0;\n"
+ "}");
+ const auto *VD = findDeclByName<VarDecl>("glob", AST->getASTContext());
+ ASSERT_TRUE(VD);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(VD)), External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, ConstGlobalHasInternalLinkage) {
+ AST = tooling::buildASTFromCode("namespace ns {\n"
+ " const int glob = 0;\n"
+ "}");
+ const auto *VD = findDeclByName<VarDecl>("glob", AST->getASTContext());
+ ASSERT_TRUE(VD);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(VD)), Internal);
+}
+
+// See 'getLinkageForDecl' in
+// ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.cpp
+
+TEST_F(TUSummaryBuilderLinkageTest, ParamOfExternalFunctionIsExternal) {
+ AST = tooling::buildASTFromCode("void target(int *ptr) {}");
+ const auto *PVD = findDeclByName<ParmVarDecl>("ptr", AST->getASTContext());
+ ASSERT_TRUE(PVD);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(PVD)), External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, ParamOfInlineFunctionIsExternal) {
+ AST = tooling::buildASTFromCode("inline void target(int *ptr) {}");
+ const auto *PVD = findDeclByName<ParmVarDecl>("ptr", AST->getASTContext());
+ ASSERT_TRUE(PVD);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(PVD)), External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, ParamOfStaticFunctionIsInternal) {
+ AST = tooling::buildASTFromCode("static void target(int *ptr) {}");
+ const auto *PVD = findDeclByName<ParmVarDecl>("ptr", AST->getASTContext());
+ ASSERT_TRUE(PVD);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(PVD)), Internal);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, ParamOfAnonNamespaceFunctionIsInternal) {
+ AST = tooling::buildASTFromCode("namespace {\n"
+ " void target(int *ptr) {}\n"
+ "}");
+ const auto *PVD = findDeclByName<ParmVarDecl>("ptr", AST->getASTContext());
+ ASSERT_TRUE(PVD);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(PVD)), Internal);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, ParamOfClassMemberFunctionIsExternal) {
+ AST = tooling::buildASTFromCode(
+ "class C { public: void target(int *ptr) {} };");
+ const auto *PVD = findDeclByName<ParmVarDecl>("ptr", AST->getASTContext());
+ ASSERT_TRUE(PVD);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(PVD)), External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, FieldOfExternalClassIsExternal) {
+ AST = tooling::buildASTFromCode("struct S { int *p; };");
+ const auto *FD = findDeclByName<FieldDecl>("p", AST->getASTContext());
+ ASSERT_TRUE(FD);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntity(FD)), External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, ReturnSlotInheritsParentLinkage) {
+ AST = tooling::buildASTFromCode("int *target() { return nullptr; }");
+ const FunctionDecl *Fn = findFnByName("target");
+ ASSERT_TRUE(Fn);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntityForReturn(Fn)), External);
+}
+
+TEST_F(TUSummaryBuilderLinkageTest, ReturnSlotInheritsParentLinkageInternal) {
+ AST = tooling::buildASTFromCode("static int *target() { return nullptr; }");
+ const FunctionDecl *Fn = findFnByName("target");
+ ASSERT_TRUE(Fn);
+ EXPECT_EQ(getLinkageFor(Extractor.addEntityForReturn(Fn)), Internal);
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/TestFixture.cpp b/clang/unittests/ScalableStaticAnalysis/TestFixture.cpp
new file mode 100644
index 0000000000000..45e3c693a26fe
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/TestFixture.cpp
@@ -0,0 +1,42 @@
+//===- TestFixture.cpp ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestFixture.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include <ostream>
+#include <string>
+
+namespace clang::ssaf {
+
+template <class T> static std::string asString(const T &Obj) {
+ std::string S;
+ llvm::raw_string_ostream(S) << Obj;
+ return S;
+}
+
+void PrintTo(const BuildNamespace &BN, std::ostream *OS) {
+ *OS << asString(BN);
+}
+
+void PrintTo(const EntityId &EI, std::ostream *OS) { *OS << asString(EI); }
+
+void PrintTo(const EntityLinkage &EL, std::ostream *OS) { *OS << asString(EL); }
+
+void PrintTo(const EntityName &EN, std::ostream *OS) { *OS << asString(EN); }
+
+void PrintTo(const NestedBuildNamespace &NBN, std::ostream *OS) {
+ *OS << asString(NBN);
+}
+
+void PrintTo(const SummaryName &SN, std::ostream *OS) { *OS << asString(SN); }
+
+} // namespace clang::ssaf
diff --git a/clang/unittests/ScalableStaticAnalysis/TestFixture.h b/clang/unittests/ScalableStaticAnalysis/TestFixture.h
new file mode 100644
index 0000000000000..22fbff754fb37
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/TestFixture.h
@@ -0,0 +1,47 @@
+//===- TestFixture.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_TESTFIXTURE_H
+#define LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_TESTFIXTURE_H
+
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/TUSummaryEncoding.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityIdTable.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "gtest/gtest.h"
+#include <iosfwd>
+
+namespace clang::ssaf {
+
+class TestFixture : public ::testing::Test {
+protected:
+ static WPASuite makeWPASuite() { return WPASuite(); }
+
+#define FIELD(CLASS, FIELD_NAME) \
+ static const auto &get##FIELD_NAME(const CLASS &X) { return X.FIELD_NAME; } \
+ static auto &get##FIELD_NAME(CLASS &X) { return X.FIELD_NAME; }
+#include "clang/ScalableStaticAnalysis/Core/Model/PrivateFieldNames.def"
+};
+
+void PrintTo(const BuildNamespace &BN, std::ostream *OS);
+void PrintTo(const EntityId &E, std::ostream *OS);
+void PrintTo(const EntityLinkage &EL, std::ostream *OS);
+void PrintTo(const EntityName &EN, std::ostream *OS);
+void PrintTo(const NestedBuildNamespace &NBN, std::ostream *OS);
+void PrintTo(const SummaryName &N, std::ostream *OS);
+
+} // namespace clang::ssaf
+
+#endif // LLVM_CLANG_UNITTESTS_SCALABLESTATICANALYSIS_TESTFIXTURE_H
diff --git a/clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/AnalysisDriverTest.cpp b/clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/AnalysisDriverTest.cpp
new file mode 100644
index 0000000000000..95077675fb2ec
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/AnalysisDriverTest.cpp
@@ -0,0 +1,563 @@
+//===- AnalysisDriverTest.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "../TestFixture.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/SummaryName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisRegistry.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisResult.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/DerivedAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/SummaryAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Testing/Support/Error.h"
+#include "gtest/gtest.h"
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace {
+
+// ---------------------------------------------------------------------------
+// Instance counter
+// ---------------------------------------------------------------------------
+
+static int NextSummaryInstanceId = 0;
+
+// ---------------------------------------------------------------------------
+// Entity summaries
+// ---------------------------------------------------------------------------
+
+class Analysis1EntitySummary final : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ static SummaryName summaryName() { return SummaryName("Analysis1"); }
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis1");
+ }
+};
+
+class Analysis2EntitySummary final : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ static SummaryName summaryName() { return SummaryName("Analysis2"); }
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis2");
+ }
+};
+
+class Analysis3EntitySummary final : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ static SummaryName summaryName() { return SummaryName("Analysis3"); }
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis3");
+ }
+};
+
+class Analysis4EntitySummary final : public EntitySummary {
+public:
+ int InstanceId = NextSummaryInstanceId++;
+ static SummaryName summaryName() { return SummaryName("Analysis4"); }
+ SummaryName getSummaryName() const override {
+ return SummaryName("Analysis4");
+ }
+};
+
+// ---------------------------------------------------------------------------
+// Analysis names
+// ---------------------------------------------------------------------------
+
+const AnalysisName Analysis1Name("Analysis1");
+const AnalysisName Analysis2Name("Analysis2");
+const AnalysisName Analysis3Name("Analysis3");
+const AnalysisName Analysis4Name("Analysis4");
+const AnalysisName Analysis5Name("Analysis5");
+const AnalysisName CycleAName("CycleA");
+const AnalysisName CycleBName("CycleB");
+
+// ---------------------------------------------------------------------------
+// Results
+// ---------------------------------------------------------------------------
+
+class Analysis1Result final : public AnalysisResult {
+public:
+ static AnalysisName analysisName() { return Analysis1Name; }
+ std::vector<std::pair<EntityId, int>> Entries;
+ bool WasInitialized = false;
+ bool WasFinalized = false;
+};
+
+class Analysis2Result final : public AnalysisResult {
+public:
+ static AnalysisName analysisName() { return Analysis2Name; }
+ std::vector<std::pair<EntityId, int>> Entries;
+ bool WasInitialized = false;
+ bool WasFinalized = false;
+};
+
+// No analysis or registration for Analysis3. Data for Analysis3 is inserted
+// into the LUSummary to verify the driver silently skips it.
+class Analysis3Result final : public AnalysisResult {
+public:
+ static AnalysisName analysisName() { return Analysis3Name; }
+};
+
+// Analysis4 has a registered analysis but no data is inserted into the
+// LUSummary, so it is skipped and get() returns nullptr.
+class Analysis4Result final : public AnalysisResult {
+public:
+ static AnalysisName analysisName() { return Analysis4Name; }
+ std::vector<std::pair<EntityId, int>> Entries;
+ bool WasInitialized = false;
+ bool WasFinalized = false;
+};
+
+// Analysis5 is a derived analysis that depends on Analysis1, Analysis2, and
+// Analysis4. It verifies that the driver passes dependency results to
+// initialize() and that the initialize/step/finalize lifecycle is respected.
+class Analysis5Result final : public AnalysisResult {
+public:
+ static AnalysisName analysisName() { return Analysis5Name; }
+ std::vector<std::string> CallSequence;
+ std::vector<std::pair<EntityId, int>> Analysis1Entries;
+ std::vector<std::pair<EntityId, int>> Analysis2Entries;
+ std::vector<std::pair<EntityId, int>> Analysis4Entries;
+};
+
+// CycleA and CycleB form a dependency cycle (CycleA → CycleB → CycleA).
+// Registered solely to exercise cycle detection in AnalysisDriver::toposort().
+// initialize() and step() are unreachable stubs - the cycle is caught before
+// any analysis executes.
+class CycleAResult final : public AnalysisResult {
+public:
+ static AnalysisName analysisName() { return CycleAName; }
+};
+
+class CycleBResult final : public AnalysisResult {
+public:
+ static AnalysisName analysisName() { return CycleBName; }
+};
+
+// ---------------------------------------------------------------------------
+// Analyses
+// ---------------------------------------------------------------------------
+
+class Analysis1 final
+ : public SummaryAnalysis<Analysis1Result, Analysis1EntitySummary> {
+public:
+ inline static bool WasDestroyed = false;
+ ~Analysis1() { WasDestroyed = true; }
+
+ llvm::Error initialize() override {
+ getResult().WasInitialized = true;
+ return llvm::Error::success();
+ }
+
+ llvm::Error add(EntityId Id, const Analysis1EntitySummary &S) override {
+ getResult().Entries.push_back({Id, S.InstanceId});
+ return llvm::Error::success();
+ }
+
+ llvm::Error finalize() override {
+ getResult().WasFinalized = true;
+ return llvm::Error::success();
+ }
+};
+
+static AnalysisRegistry::Add<Analysis1> RegAnalysis1("Analysis for Analysis1");
+
+class Analysis2 final
+ : public SummaryAnalysis<Analysis2Result, Analysis2EntitySummary> {
+public:
+ inline static bool WasDestroyed = false;
+ ~Analysis2() { WasDestroyed = true; }
+
+ llvm::Error initialize() override {
+ getResult().WasInitialized = true;
+ return llvm::Error::success();
+ }
+
+ llvm::Error add(EntityId Id, const Analysis2EntitySummary &S) override {
+ getResult().Entries.push_back({Id, S.InstanceId});
+ return llvm::Error::success();
+ }
+
+ llvm::Error finalize() override {
+ getResult().WasFinalized = true;
+ return llvm::Error::success();
+ }
+};
+
+static AnalysisRegistry::Add<Analysis2> RegAnalysis2("Analysis for Analysis2");
+
+// No Analysis3 or registration for Analysis3.
+
+class Analysis4 final
+ : public SummaryAnalysis<Analysis4Result, Analysis4EntitySummary> {
+public:
+ inline static bool WasDestroyed = false;
+ ~Analysis4() { WasDestroyed = true; }
+
+ llvm::Error initialize() override {
+ getResult().WasInitialized = true;
+ return llvm::Error::success();
+ }
+
+ llvm::Error add(EntityId Id, const Analysis4EntitySummary &S) override {
+ getResult().Entries.push_back({Id, S.InstanceId});
+ return llvm::Error::success();
+ }
+
+ llvm::Error finalize() override {
+ getResult().WasFinalized = true;
+ return llvm::Error::success();
+ }
+};
+
+static AnalysisRegistry::Add<Analysis4> RegAnalysis4("Analysis for Analysis4");
+
+class Analysis5 final
+ : public DerivedAnalysis<Analysis5Result, Analysis1Result, Analysis2Result,
+ Analysis4Result> {
+ int StepCount = 0;
+
+public:
+ inline static bool WasDestroyed = false;
+ ~Analysis5() { WasDestroyed = true; }
+
+ llvm::Error initialize(const Analysis1Result &R1, const Analysis2Result &R2,
+ const Analysis4Result &R4) override {
+ getResult().CallSequence.push_back("initialize");
+ getResult().Analysis1Entries = R1.Entries;
+ getResult().Analysis2Entries = R2.Entries;
+ getResult().Analysis4Entries = R4.Entries;
+ return llvm::Error::success();
+ }
+
+ llvm::Expected<bool> step() override {
+ getResult().CallSequence.push_back("step");
+ return ++StepCount < 2;
+ }
+
+ llvm::Error finalize() override {
+ getResult().CallSequence.push_back("finalize");
+ return llvm::Error::success();
+ }
+};
+
+static AnalysisRegistry::Add<Analysis5> RegAnalysis5("Analysis for Analysis5");
+
+class CycleA final : public DerivedAnalysis<CycleAResult, CycleBResult> {
+public:
+ llvm::Error initialize(const CycleBResult &) override {
+ return llvm::Error::success();
+ }
+ llvm::Expected<bool> step() override { return false; }
+};
+
+static AnalysisRegistry::Add<CycleA> RegCycleA("Cyclic analysis A (test only)");
+
+class CycleB final : public DerivedAnalysis<CycleBResult, CycleAResult> {
+public:
+ llvm::Error initialize(const CycleAResult &) override {
+ return llvm::Error::success();
+ }
+ llvm::Expected<bool> step() override { return false; }
+};
+
+static AnalysisRegistry::Add<CycleB> RegCycleB("Cyclic analysis B (test only)");
+
+// ---------------------------------------------------------------------------
+// Fixture
+// ---------------------------------------------------------------------------
+
+class AnalysisDriverTest : public TestFixture {
+protected:
+ static constexpr EntityLinkage ExternalLinkage =
+ EntityLinkage(EntityLinkageType::External);
+
+ void SetUp() override {
+ NextSummaryInstanceId = 0;
+ Analysis1::WasDestroyed = false;
+ Analysis2::WasDestroyed = false;
+ // No Analysis3 - not registered, so no WasDestroyed flag.
+ Analysis4::WasDestroyed = false;
+ Analysis5::WasDestroyed = false;
+ }
+
+ std::unique_ptr<LUSummary> makeLUSummary() {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ return std::make_unique<LUSummary>(llvm::Triple("arm64-apple-macosx"),
+ std::move(NS));
+ }
+
+ EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ EntityName Name(USR.str(), "", NS);
+ EntityId Id = getIdTable(LU).getId(Name);
+ getLinkageTable(LU).insert({Id, ExternalLinkage});
+ return Id;
+ }
+
+ static bool hasEntry(const std::vector<std::pair<EntityId, int>> &Entries,
+ EntityId Id, int InstanceId) {
+ return llvm::is_contained(Entries, std::make_pair(Id, InstanceId));
+ }
+
+ template <typename SummaryT>
+ int insertSummary(LUSummary &LU, llvm::StringRef SN, EntityId Id) {
+ auto S = std::make_unique<SummaryT>();
+ int InstanceId = S->InstanceId;
+ getData(LU)[SummaryName(SN.str())][Id] = std::move(S);
+ return InstanceId;
+ }
+};
+
+// ---------------------------------------------------------------------------
+// Tests
+// ---------------------------------------------------------------------------
+
+TEST(AnalysisRegistryTest, AnalysisIsRegistered) {
+ EXPECT_TRUE(AnalysisRegistry::contains(Analysis1Name));
+ EXPECT_TRUE(AnalysisRegistry::contains(Analysis2Name));
+ EXPECT_FALSE(AnalysisRegistry::contains(Analysis3Name));
+ EXPECT_TRUE(AnalysisRegistry::contains(Analysis4Name));
+ EXPECT_TRUE(AnalysisRegistry::contains(Analysis5Name));
+ EXPECT_TRUE(AnalysisRegistry::contains(CycleAName));
+ EXPECT_TRUE(AnalysisRegistry::contains(CycleBName));
+}
+
+TEST(AnalysisRegistryTest, AnalysisCanBeInstantiated) {
+ constexpr auto instantiate = AnalysisRegistry::instantiate;
+ EXPECT_THAT_EXPECTED(
+ instantiate(AnalysisName("AnalysisNonExisting")),
+ llvm::FailedWithMessage(
+ "no analysis registered for 'AnalysisName(AnalysisNonExisting)'"));
+ EXPECT_THAT_EXPECTED(instantiate(Analysis1Name), llvm::Succeeded());
+ EXPECT_THAT_EXPECTED(instantiate(Analysis2Name), llvm::Succeeded());
+ // No Analysis3 - not registered, so instantiate() would fail.
+ EXPECT_THAT_EXPECTED(instantiate(Analysis4Name), llvm::Succeeded());
+ EXPECT_THAT_EXPECTED(instantiate(Analysis5Name), llvm::Succeeded());
+ EXPECT_THAT_EXPECTED(instantiate(CycleAName), llvm::Succeeded());
+ EXPECT_THAT_EXPECTED(instantiate(CycleBName), llvm::Succeeded());
+}
+
+// run<T...>() — processes the non-cyclic analyses in topological order.
+// CycleA and CycleB are excluded because they form a cycle; run() && would
+// error on them, so the type-safe subset overload is used here instead.
+TEST_F(AnalysisDriverTest, RunAll) {
+ auto LU = makeLUSummary();
+ const auto E1 = addEntity(*LU, "Entity1");
+ const auto E2 = addEntity(*LU, "Entity2");
+ const auto E3 = addEntity(*LU, "Entity3");
+ const auto E4 = addEntity(*LU, "Entity4");
+
+ int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
+ int s1b = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E2);
+ int s2a = insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
+ int s2b = insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E3);
+ int s4a = insertSummary<Analysis4EntitySummary>(*LU, "Analysis4", E4);
+
+ // No registered analysis — Analysis3 data silently skipped.
+ (void)insertSummary<Analysis3EntitySummary>(*LU, "Analysis3", E1);
+
+ AnalysisDriver Driver(std::move(LU));
+ auto WPAOrErr = Driver.run<Analysis1Result, Analysis2Result, Analysis4Result,
+ Analysis5Result>();
+ ASSERT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
+
+ {
+ auto R1OrErr = WPAOrErr->get<Analysis1Result>();
+ ASSERT_THAT_EXPECTED(R1OrErr, llvm::Succeeded());
+ EXPECT_EQ(R1OrErr->Entries.size(), 2u);
+ EXPECT_TRUE(hasEntry(R1OrErr->Entries, E1, s1a));
+ EXPECT_TRUE(hasEntry(R1OrErr->Entries, E2, s1b));
+ EXPECT_TRUE(R1OrErr->WasInitialized);
+ EXPECT_TRUE(R1OrErr->WasFinalized);
+ EXPECT_TRUE(Analysis1::WasDestroyed);
+ }
+
+ {
+ auto R2OrErr = WPAOrErr->get<Analysis2Result>();
+ ASSERT_THAT_EXPECTED(R2OrErr, llvm::Succeeded());
+ EXPECT_EQ(R2OrErr->Entries.size(), 2u);
+ EXPECT_TRUE(hasEntry(R2OrErr->Entries, E2, s2a));
+ EXPECT_TRUE(hasEntry(R2OrErr->Entries, E3, s2b));
+ EXPECT_TRUE(R2OrErr->WasInitialized);
+ EXPECT_TRUE(R2OrErr->WasFinalized);
+ EXPECT_TRUE(Analysis2::WasDestroyed);
+ }
+
+ {
+ auto R4OrErr = WPAOrErr->get<Analysis4Result>();
+ ASSERT_THAT_EXPECTED(R4OrErr, llvm::Succeeded());
+ EXPECT_EQ(R4OrErr->Entries.size(), 1u);
+ EXPECT_TRUE(hasEntry(R4OrErr->Entries, E4, s4a));
+ EXPECT_TRUE(R4OrErr->WasInitialized);
+ EXPECT_TRUE(R4OrErr->WasFinalized);
+ EXPECT_TRUE(Analysis4::WasDestroyed);
+ }
+
+ {
+ auto R5OrErr = WPAOrErr->get<Analysis5Result>();
+ ASSERT_THAT_EXPECTED(R5OrErr, llvm::Succeeded());
+ EXPECT_EQ(
+ R5OrErr->CallSequence,
+ (std::vector<std::string>{"initialize", "step", "step", "finalize"}));
+ EXPECT_EQ(R5OrErr->Analysis1Entries.size(), 2u);
+ EXPECT_TRUE(hasEntry(R5OrErr->Analysis1Entries, E1, s1a));
+ EXPECT_TRUE(hasEntry(R5OrErr->Analysis1Entries, E2, s1b));
+ EXPECT_EQ(R5OrErr->Analysis2Entries.size(), 2u);
+ EXPECT_TRUE(hasEntry(R5OrErr->Analysis2Entries, E2, s2a));
+ EXPECT_TRUE(hasEntry(R5OrErr->Analysis2Entries, E3, s2b));
+ EXPECT_EQ(R5OrErr->Analysis4Entries.size(), 1u);
+ EXPECT_TRUE(hasEntry(R5OrErr->Analysis4Entries, E4, s4a));
+ EXPECT_TRUE(Analysis5::WasDestroyed);
+ }
+
+ // Unregistered analysis — not present in WPA.
+ EXPECT_THAT_EXPECTED(
+ WPAOrErr->get<Analysis3Result>(),
+ llvm::FailedWithMessage(
+ "no result for 'AnalysisName(Analysis3)' in WPASuite"));
+}
+
+// run(names) — processes only the analyses for the given names.
+TEST_F(AnalysisDriverTest, RunByName) {
+ auto LU = makeLUSummary();
+ const auto E1 = addEntity(*LU, "Entity1");
+ const auto E2 = addEntity(*LU, "Entity2");
+
+ int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
+ insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
+
+ AnalysisDriver Driver(std::move(LU));
+ auto WPAOrErr = Driver.run({AnalysisName("Analysis1")});
+ ASSERT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
+
+ // Analysis1 was requested and has data — present.
+ auto R1OrErr = WPAOrErr->get<Analysis1Result>();
+ ASSERT_THAT_EXPECTED(R1OrErr, llvm::Succeeded());
+ EXPECT_EQ(R1OrErr->Entries.size(), 1u);
+ EXPECT_TRUE(hasEntry(R1OrErr->Entries, E1, s1a));
+ EXPECT_TRUE(R1OrErr->WasInitialized);
+ EXPECT_TRUE(R1OrErr->WasFinalized);
+
+ // Analysis2 was not requested — not present even though data exists.
+ EXPECT_THAT_EXPECTED(
+ WPAOrErr->get<Analysis2Result>(),
+ llvm::FailedWithMessage(
+ "no result for 'AnalysisName(Analysis2)' in WPASuite"));
+}
+
+// run(names) — error when a requested name has no data in LUSummary.
+TEST_F(AnalysisDriverTest, RunByNameErrorMissingData) {
+ auto LU = makeLUSummary();
+ AnalysisDriver Driver(std::move(LU));
+
+ EXPECT_THAT_EXPECTED(
+ Driver.run({AnalysisName("Analysis1")}),
+ llvm::FailedWithMessage(
+ "no data for analysis 'AnalysisName(Analysis1)' in LUSummary"));
+}
+
+// run(names) — error when a requested name has no registered analysis.
+TEST_F(AnalysisDriverTest, RunByNameErrorMissingAnalysis) {
+ auto LU = makeLUSummary();
+ const auto E1 = addEntity(*LU, "Entity1");
+ insertSummary<Analysis3EntitySummary>(*LU, "Analysis3", E1);
+
+ AnalysisDriver Driver(std::move(LU));
+
+ // Analysis3 has data but no registered analysis.
+ EXPECT_THAT_EXPECTED(
+ Driver.run({AnalysisName("Analysis3")}),
+ llvm::FailedWithMessage(
+ "no analysis registered for 'AnalysisName(Analysis3)'"));
+}
+
+// run<ResultTs...>() — type-safe subset.
+TEST_F(AnalysisDriverTest, RunByType) {
+ auto LU = makeLUSummary();
+ const auto E1 = addEntity(*LU, "Entity1");
+ const auto E2 = addEntity(*LU, "Entity2");
+
+ int s1a = insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
+ insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E2);
+
+ AnalysisDriver Driver(std::move(LU));
+ auto WPAOrErr = Driver.run<Analysis1Result>();
+ ASSERT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
+
+ // Analysis1 was requested — present.
+ auto R1OrErr = WPAOrErr->get<Analysis1Result>();
+ ASSERT_THAT_EXPECTED(R1OrErr, llvm::Succeeded());
+ EXPECT_EQ(R1OrErr->Entries.size(), 1u);
+ EXPECT_TRUE(hasEntry(R1OrErr->Entries, E1, s1a));
+ EXPECT_TRUE(R1OrErr->WasInitialized);
+ EXPECT_TRUE(R1OrErr->WasFinalized);
+
+ // Analysis2 was not requested — not present even though data exists.
+ EXPECT_THAT_EXPECTED(
+ WPAOrErr->get<Analysis2Result>(),
+ llvm::FailedWithMessage(
+ "no result for 'AnalysisName(Analysis2)' in WPASuite"));
+}
+
+// run<ResultTs...>() — error when a requested type has no data in LUSummary.
+TEST_F(AnalysisDriverTest, RunByTypeErrorMissingData) {
+ auto LU = makeLUSummary();
+ AnalysisDriver Driver(std::move(LU));
+
+ EXPECT_THAT_EXPECTED(
+ Driver.run<Analysis1Result>(),
+ llvm::FailedWithMessage(
+ "no data for analysis 'AnalysisName(Analysis1)' in LUSummary"));
+}
+
+// contains() — present entries return true; absent entries return false.
+TEST_F(AnalysisDriverTest, Contains) {
+ auto LU = makeLUSummary();
+ const auto E1 = addEntity(*LU, "Entity1");
+ insertSummary<Analysis1EntitySummary>(*LU, "Analysis1", E1);
+ insertSummary<Analysis2EntitySummary>(*LU, "Analysis2", E1);
+ insertSummary<Analysis4EntitySummary>(*LU, "Analysis4", E1);
+
+ AnalysisDriver Driver(std::move(LU));
+ auto WPAOrErr = Driver.run<Analysis1Result, Analysis2Result, Analysis4Result,
+ Analysis5Result>();
+ ASSERT_THAT_EXPECTED(WPAOrErr, llvm::Succeeded());
+ EXPECT_TRUE(WPAOrErr->contains<Analysis1Result>());
+ // Analysis3 has no registered analysis — never present in WPA.
+ EXPECT_FALSE(WPAOrErr->contains<Analysis3Result>());
+}
+
+// run() && — errors when the registry contains a dependency cycle.
+TEST_F(AnalysisDriverTest, CycleDetected) {
+ auto LU = makeLUSummary();
+ AnalysisDriver Driver(std::move(LU));
+ EXPECT_THAT_EXPECTED(
+ std::move(Driver).run(),
+ llvm::FailedWithMessage("cycle detected: AnalysisName(CycleA) -> "
+ "AnalysisName(CycleB) -> AnalysisName(CycleA)"));
+}
+
+} // namespace
diff --git a/clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp b/clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp
new file mode 100644
index 0000000000000..cf5420b35e7dc
--- /dev/null
+++ b/clang/unittests/ScalableStaticAnalysis/WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp
@@ -0,0 +1,582 @@
+//===- UnsafeBufferReachableAnalysisTest.cpp ------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "../TestFixture.h"
+#include "clang/ScalableStaticAnalysis/Analyses/EntityPointerLevel/EntityPointerLevel.h"
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlow.h"
+#include "clang/ScalableStaticAnalysis/Analyses/PointerFlow/PointerFlowAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsage.h"
+#include "clang/ScalableStaticAnalysis/Analyses/UnsafeBufferUsage/UnsafeBufferUsageAnalysis.h"
+#include "clang/ScalableStaticAnalysis/Core/EntityLinker/LUSummary.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/BuildNamespace.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityId.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityLinkage.h"
+#include "clang/ScalableStaticAnalysis/Core/Model/EntityName.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/AnalysisDriver.h"
+#include "clang/ScalableStaticAnalysis/Core/WholeProgramAnalysis/WPASuite.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "gtest/gtest.h"
+#include <map>
+#include <memory>
+#include <optional>
+
+using namespace clang;
+using namespace ssaf;
+
+namespace clang::ssaf {
+extern PointerFlowEntitySummary buildPointerFlowEntitySummary(EdgeSet Edges);
+extern UnsafeBufferUsageEntitySummary
+ buildUnsafeBufferUsageEntitySummary(EntityPointerLevelSet);
+} // namespace clang::ssaf
+
+namespace {
+
+class UnsafeBufferReachableAnalysisTest : public TestFixture {
+protected:
+ using EPLEdge = std::pair<EntityPointerLevel, EntityPointerLevel>;
+
+ static constexpr EntityLinkage ExternalLinkage =
+ EntityLinkage(EntityLinkageType::External);
+
+ std::unique_ptr<LUSummary> makeLUSummary() {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ return std::make_unique<LUSummary>(llvm::Triple("arm64-apple-macosx"),
+ std::move(NS));
+ }
+
+ EntityId addEntity(LUSummary &LU, llvm::StringRef USR) {
+ NestedBuildNamespace NS(
+ {BuildNamespace(BuildNamespaceKind::LinkUnit, "TestLU")});
+ EntityName Name(USR.str(), "", NS);
+ EntityId Id = getIdTable(LU).getId(Name);
+ getLinkageTable(LU).insert({Id, ExternalLinkage});
+ return Id;
+ }
+
+ /// Insert a PointerFlowEntitySummary for an entity.
+ void insertPointerFlowSummary(LUSummary &LU, EntityId Id, EdgeSet Edges) {
+ getData(LU)[PointerFlowEntitySummary::summaryName()][Id] =
+ std::make_unique<PointerFlowEntitySummary>(
+ buildPointerFlowEntitySummary(std::move(Edges)));
+ }
+
+ /// Insert an UnsafeBufferUsageEntitySummary for an entity.
+ void insertUnsafeBufferUsageSummary(LUSummary &LU, EntityId Id,
+ EntityPointerLevelSet UnsafeBuffers) {
+ getData(LU)[UnsafeBufferUsageEntitySummary::summaryName()][Id] =
+ std::make_unique<UnsafeBufferUsageEntitySummary>(
+ buildUnsafeBufferUsageEntitySummary(std::move(UnsafeBuffers)));
+ }
+
+ class LetterEntityBiMap {
+ std::map<char, EntityId> Forward;
+ std::map<EntityId, char> Reverse;
+
+ public:
+ void insert(char C, EntityId Id) {
+ Forward.try_emplace(C, Id);
+ Reverse[Id] = C;
+ }
+
+ EntityId operator[](char C) const { return Forward.at(C); }
+ char operator[](EntityId Id) const { return Reverse.at(Id); }
+ size_t size() const { return Forward.size(); }
+ };
+
+ /// Create entities for the entity domain \p EntDom in \p LU. For simplicity,
+ /// entities are given by letters in \p EntDom. Return a "bi-directional map"
+ /// between letters and EntityIds.
+ LetterEntityBiMap createEntities(LUSummary &LU, llvm::ArrayRef<char> EntDom) {
+ LetterEntityBiMap Result;
+ for (char Name : EntDom)
+ Result.insert(Name, addEntity(LU, ("E" + llvm::Twine(Name)).str()));
+ return Result;
+ }
+
+ /// Insert both PointerFlow and UnsafeBufferUsage summaries for an entity
+ /// from a list of edges and a list of starter EPLs.
+ void insertSummaries(LUSummary &LU, EntityId Id,
+ llvm::ArrayRef<EPLEdge> EdgeList,
+ llvm::ArrayRef<EntityPointerLevel> StarterList) {
+ EdgeSet Edges;
+ for (const auto &[From, To] : EdgeList)
+ Edges[From].insert(To);
+ insertPointerFlowSummary(LU, Id, std::move(Edges));
+
+ EntityPointerLevelSet Starters;
+ for (const auto &EPL : StarterList)
+ Starters.insert(EPL);
+ insertUnsafeBufferUsageSummary(LU, Id, std::move(Starters));
+ }
+
+ /// Run the driver and return the flattened reachable EPL set.
+ std::optional<EntityPointerLevelSet>
+ computeReachables(std::unique_ptr<LUSummary> LU, unsigned Line) {
+ AnalysisDriver Driver(std::move(LU));
+ auto WPAOrErr =
+ Driver.run<PointerFlowAnalysisResult, UnsafeBufferUsageAnalysisResult,
+ UnsafeBufferReachableAnalysisResult>();
+ if (!WPAOrErr) {
+ ADD_FAILURE_AT(__FILE__, Line) << llvm::toString(WPAOrErr.takeError());
+ return std::nullopt;
+ }
+ auto ROrErr = WPAOrErr->get<UnsafeBufferReachableAnalysisResult>();
+ if (!ROrErr) {
+ ADD_FAILURE_AT(__FILE__, Line) << llvm::toString(ROrErr.takeError());
+ return std::nullopt;
+ }
+ EntityPointerLevelSet Result;
+ for (const auto &[Id, EPLs] : ROrErr->Reachables)
+ Result.insert(EPLs.begin(), EPLs.end());
+ return Result;
+ }
+
+ using Node = std::pair<char, unsigned>;
+ using Edge = std::pair<Node, Node>;
+
+ // FIXME: When we use more advanced search algorithms, it may involve
+ // a divide-and-conquer approach on sub-graphs organized by contributors.
+ // In that case, we may want to enumerate all possible partitions of
+ // how edges are distributed among contributors. For now we use
+ // `singlePartition`.
+
+ /// Compute reachables from \p StarterLayout in the graph defined by \p
+ /// EdgeLayout. Edges and starters are all belong to one contributor.
+ std::set<Node> singlePartition(llvm::ArrayRef<char> EntityDomain,
+ llvm::ArrayRef<Edge> EdgeLayout,
+ llvm::ArrayRef<Node> StarterLayout,
+ unsigned Line) {
+ auto LU = makeLUSummary();
+ auto Entities = createEntities(*LU, EntityDomain);
+ auto GetEPL = [&Entities](const Node &N) -> EntityPointerLevel {
+ return buildEntityPointerLevel(Entities[N.first], N.second);
+ };
+ auto GetNode = [&Entities](const EntityPointerLevel &N) -> Node {
+ return {Entities[N.getEntity()], N.getPointerLevel()};
+ };
+
+ std::vector<EPLEdge> Edges;
+ for (const auto &[F, T] : EdgeLayout)
+ Edges.push_back({GetEPL(F), GetEPL(T)});
+
+ std::vector<EntityPointerLevel> Starters;
+ for (const Node &N : StarterLayout)
+ Starters.push_back(GetEPL(N));
+
+ insertSummaries(*LU, Entities[EntityDomain[0]], Edges, Starters);
+ for (size_t Idx = 1; Idx < EntityDomain.size(); ++Idx)
+ insertSummaries(*LU, Entities[EntityDomain[Idx]], {}, {});
+
+ auto Reachables = computeReachables(std::move(LU), Line);
+ if (!Reachables)
+ return {};
+
+ std::set<Node> Result;
+ for (auto &EPL : *Reachables)
+ Result.insert(GetNode(EPL));
+
+ return Result;
+ }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// Tests below focus on pointer flow graph topology and the starter set.
+// Letters represent distinct entities; numbers represent pointer levels.
+//
+// For example, `LinearChain` tests a graph forming a linear chain with 3
+// edges: (a,1) -> (b,1) -> (c,1) -> (d,1) with starter {(a,1)}. Thus, {(a,1),
+// (b,1), (c,1), (d,1)} is the expected reachable set.
+////////////////////////////////////////////////////////////////////////////////
+
+// Linear chain: (a,1) -> (b,1) -> (c,1) -> (d,1).
+// Start from {(a,1)} => {(a,1), (b,1), (c,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, LinearChain) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}}, {{'b', 1}, {'c', 1}}, {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'a', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 4u);
+}
+
+// Linear chain: (a,1) -> (b,2), (b,1) -> (c,2), (c,1) -> (d,2).
+// Start from {(a,2)} => {(a,2), (b,3), (c,4), (d,5)}
+TEST_F(UnsafeBufferReachableAnalysisTest, LinearChain2) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 2}}, {{'b', 1}, {'c', 2}}, {{'c', 1}, {'d', 2}}},
+ /* StarterLayout */ {{'a', 2}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 4u);
+ EXPECT_EQ(Reachables,
+ (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 4}, {'d', 5}}));
+}
+
+// Linear chain: (a,1) -> (b,2), (b,4) -> (c,1) -> (d,1).
+// Start from {(a,2)} => {(a,2), (b,3)} (halted at (b,3) — no key (b,j<=3))
+TEST_F(UnsafeBufferReachableAnalysisTest, LinearChain3) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 2}}, {{'b', 4}, {'c', 1}}, {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'a', 2}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 2u);
+ EXPECT_EQ(Reachables, (std::set<Node>{{'a', 2}, {'b', 3}}));
+}
+
+// Linear chain: (a,1) -> (b,1) -> (c,1) -> (d,1).
+// Start from mid-chain {(c,1)} => {(c,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, LinearChainFromMiddle) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}}, {{'b', 1}, {'c', 1}}, {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'c', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 2u);
+ EXPECT_TRUE(Reachables.count({'c', 1}));
+ EXPECT_TRUE(Reachables.count({'d', 1}));
+}
+
+// Diamond: (a,1) -> (b,1), (a,1) -> (c,1), (b,1) -> (d,1), (c,1) -> (d,1).
+// Start from {(a,1)} => {(a,1), (b,1), (c,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, Diamond) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}},
+ {{'a', 1}, {'c', 1}},
+ {{'b', 1}, {'d', 1}},
+ {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'a', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 4u);
+}
+
+// Diamond: (a,1) -> (b,2), (a,1) -> (c,2), (b,1) -> (d,2), (c,1) -> (d,2).
+// Start from {(a,2)} => {(a,2), (b,3), (c,3), (d,4)}
+TEST_F(UnsafeBufferReachableAnalysisTest, Diamond2) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 2}},
+ {{'a', 1}, {'c', 2}},
+ {{'b', 1}, {'d', 2}},
+ {{'c', 1}, {'d', 2}}},
+ /* StarterLayout */ {{'a', 2}}, __LINE__);
+ EXPECT_EQ(Reachables,
+ (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 3}, {'d', 4}}));
+}
+
+// DisconnectedDiamond: (a,1) -> (b,2), (a,1) -> (c,2), (b,5) -> (d,1), (c,5) ->
+// (d,1). Start from {(a,2)} => {(a,2), (b,3), (c,3)}
+TEST_F(UnsafeBufferReachableAnalysisTest, DisconnectedDiamond) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 2}},
+ {{'a', 1}, {'c', 2}},
+ {{'b', 5}, {'d', 1}},
+ {{'c', 5}, {'d', 1}}},
+ /* StarterLayout */ {{'a', 2}}, __LINE__);
+ EXPECT_EQ(Reachables, (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 3}}));
+}
+
+// Diamond: (a,1) -> (b,1), (a,1) -> (c,1), (b,1) -> (d,1), (c,1) -> (d,1).
+// Start from one branch {(b,1)} => {(b,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, DiamondFromBranch) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}},
+ {{'a', 1}, {'c', 1}},
+ {{'b', 1}, {'d', 1}},
+ {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'b', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 2u);
+ EXPECT_TRUE(Reachables.count({'b', 1}));
+ EXPECT_TRUE(Reachables.count({'d', 1}));
+}
+
+// Disconnected subgraphs: (a,1) -> (b,1), (c,1) -> (d,1).
+// Start from {(a,1)} => {(a,1), (b,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, DisconnectedSubgraphs) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */ {{{'a', 1}, {'b', 1}}, {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'a', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 2u);
+ EXPECT_TRUE(Reachables.count({'a', 1}));
+ EXPECT_TRUE(Reachables.count({'b', 1}));
+}
+
+// Disconnected subgraphs: (a,1) -> (b,1), (c,1) -> (d,1).
+// Start from tail {(b,1)} => {(b,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, DisconnectedSubgraphs2) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */ {{{'a', 1}, {'b', 1}}, {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'b', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 1u);
+ EXPECT_TRUE(Reachables.count({'b', 1}));
+}
+
+// Cycle: (a,1) -> (b,1) -> (c,1) -> (d,1) -> (a,1).
+// Start from {(c,1)} => {(a,1), (b,1), (c,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, Cycle) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}},
+ {{'b', 1}, {'c', 1}},
+ {{'c', 1}, {'d', 1}},
+ {{'d', 1}, {'a', 1}}},
+ /* StarterLayout */ {{'c', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 4u);
+ EXPECT_TRUE(Reachables.count({'a', 1}));
+ EXPECT_TRUE(Reachables.count({'b', 1}));
+ EXPECT_TRUE(Reachables.count({'c', 1}));
+ EXPECT_TRUE(Reachables.count({'d', 1}));
+}
+
+// Cycle: (a,1) -> (b,1) -> (c,1) -> (d,1) -> (a,1).
+// Start from {(c,2)} => {(a,2), (b,2), (c,2), (d,2)}
+TEST_F(UnsafeBufferReachableAnalysisTest, Cycle2) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}},
+ {{'b', 1}, {'c', 1}},
+ {{'c', 1}, {'d', 1}},
+ {{'d', 1}, {'a', 1}}},
+ /* StarterLayout */ {{'c', 2}}, __LINE__);
+ EXPECT_EQ(Reachables,
+ (std::set<Node>{{'a', 2}, {'b', 2}, {'c', 2}, {'d', 2}}));
+}
+
+// Cycle: (a,1) -> (b,2) -> (c,3) -> (d,4) -> (a,1).
+// Start from {(a,2)} => {(a,2), (b,3), (c,4), (d,5)}
+TEST_F(UnsafeBufferReachableAnalysisTest, Cycle3) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 2}},
+ {{'b', 2}, {'c', 3}},
+ {{'c', 3}, {'d', 4}},
+ {{'d', 4}, {'a', 1}}},
+ /* StarterLayout */ {{'a', 2}}, __LINE__);
+ EXPECT_EQ(Reachables,
+ (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 4}, {'d', 5}}));
+}
+
+// Empty graph: no edges, start from {(a,1)} => {(a,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, EmptyGraph) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a'},
+ /* EdgeLayout */ {},
+ /* StarterLayout */ {{'a', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 1u);
+ EXPECT_TRUE(Reachables.count({'a', 1}));
+}
+
+// Star: (a,1) -> (b,1), (a,1) -> (c,1), (a,1) -> (d,1).
+// Start from {(a,1)} => {(a,1), (b,1), (c,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, StarFromHub) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}}, {{'a', 1}, {'c', 1}}, {{'a', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'a', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 4u);
+}
+
+// Star: (a,1) -> (b,2), (a,1) -> (c,2), (a,1) -> (d,2).
+// Start from {(a,2)} => {(a,2), (b,3), (c,3), (d,3)}
+TEST_F(UnsafeBufferReachableAnalysisTest, StarFromHub2) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 2}}, {{'a', 1}, {'c', 2}}, {{'a', 1}, {'d', 2}}},
+ /* StarterLayout */ {{'a', 2}}, __LINE__);
+ EXPECT_EQ(Reachables,
+ (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 3}, {'d', 3}}));
+}
+
+// Star: (a,2) -> (b,1), (a,2) -> (c,1), (a,2) -> (d,1).
+// Start from {(a,1)} => {(a,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, StarFromHub3) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 2}, {'b', 1}}, {{'a', 2}, {'c', 1}}, {{'a', 2}, {'d', 1}}},
+ /* StarterLayout */ {{'a', 1}}, __LINE__);
+ EXPECT_EQ(Reachables, (std::set<Node>{{'a', 1}}));
+}
+
+// Star: (a,1) -> (b,1), (a,1) -> (c,1), (a,1) -> (d,1).
+// Start from leaf {(c,1)} => {(c,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, StarFromLeaf) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}}, {{'a', 1}, {'c', 1}}, {{'a', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'c', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 1u);
+ EXPECT_TRUE(Reachables.count({'c', 1}));
+}
+
+// Reverse star: (a,1) -> (d,1), (b,1) -> (d,1), (c,1) -> (d,1).
+// Start from {(a,1)} => {(a,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, ReverseStarFromSource) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'d', 1}}, {{'b', 1}, {'d', 1}}, {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'a', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 2u);
+ EXPECT_TRUE(Reachables.count({'a', 1}));
+ EXPECT_TRUE(Reachables.count({'d', 1}));
+}
+
+// Reverse star: (a,1) -> (d,2), (b,1) -> (d,2), (c,1) -> (d,2).
+// Start from {(a,2)} => {(a,2), (d,3)}
+TEST_F(UnsafeBufferReachableAnalysisTest, ReverseStarFromSource2) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'d', 2}}, {{'b', 1}, {'d', 2}}, {{'c', 1}, {'d', 2}}},
+ /* StarterLayout */ {{'a', 2}}, __LINE__);
+ EXPECT_EQ(Reachables, (std::set<Node>{{'a', 2}, {'d', 3}}));
+}
+
+// Reverse star: (a,1) -> (d,1), (b,1) -> (d,1), (c,1) -> (d,1).
+// Start from sink {(d,1)} => {(d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, ReverseStarFromSink) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'d', 1}}, {{'b', 1}, {'d', 1}}, {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'d', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 1u);
+ EXPECT_TRUE(Reachables.count({'d', 1}));
+}
+
+// Reverse star: (a,1) -> (d,1), (b,1) -> (d,1), (c,1) -> (d,1).
+// Start from sink {(d,2)} => {(d,2)}
+TEST_F(UnsafeBufferReachableAnalysisTest, ReverseStarFromSink2) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'d', 1}}, {{'b', 1}, {'d', 1}}, {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'d', 2}}, __LINE__);
+ EXPECT_EQ(Reachables, (std::set<Node>{{'d', 2}}));
+}
+
+// Self-loop: (a,1) -> (b,1) -> (b,1) -> (c,1) -> (d,1).
+// Start from {(a,1)} => {(a,1), (b,1), (c,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, SelfLoopFromRoot) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}},
+ {{'b', 1}, {'b', 1}},
+ {{'b', 1}, {'c', 1}},
+ {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'a', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 4u);
+}
+
+// Self-loop: (a,1) -> (b,1) -> (b,1) -> (c,2) -> (d,2).
+// Start from {(a,2)} => {(a,2), (b,2), (c,3), (d,4)}
+TEST_F(UnsafeBufferReachableAnalysisTest, SelfLoopFromRoot2) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}},
+ {{'b', 1}, {'b', 1}},
+ {{'b', 1}, {'c', 2}},
+ {{'c', 1}, {'d', 2}}},
+ /* StarterLayout */ {{'a', 2}}, __LINE__);
+ EXPECT_EQ(Reachables,
+ (std::set<Node>{{'a', 2}, {'b', 2}, {'c', 3}, {'d', 4}}));
+}
+
+// Self-loop: (a,1) -> (b,1) -> (b,1) -> (c,1) -> (d,1).
+// Start from {(b,1)} => {(b,1), (c,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, SelfLoopFromLoopNode) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}},
+ {{'b', 1}, {'b', 1}},
+ {{'b', 1}, {'c', 1}},
+ {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'b', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 3u);
+ EXPECT_TRUE(Reachables.count({'b', 1}));
+ EXPECT_TRUE(Reachables.count({'c', 1}));
+ EXPECT_TRUE(Reachables.count({'d', 1}));
+}
+
+// Self-loop: (a,1) -> (b,1) -> (b,1) -> (c,2) -> (d,2).
+// Start from {(b,2)} => {(b,2), (c,3), (d,4)}
+TEST_F(UnsafeBufferReachableAnalysisTest, SelfLoopFromLoopNode2) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */
+ {{{'a', 1}, {'b', 1}},
+ {{'b', 1}, {'b', 1}},
+ {{'b', 1}, {'c', 2}},
+ {{'c', 1}, {'d', 2}}},
+ /* StarterLayout */ {{'b', 2}}, __LINE__);
+ EXPECT_EQ(Reachables, (std::set<Node>{{'b', 2}, {'c', 3}, {'d', 4}}));
+}
+
+// Multiple starters: (a,1) -> (b,1), (c,1) -> (d,1) (disconnected).
+// Start from {(a,1), (c,1)} => {(a,1), (b,1), (c,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, MultipleStartersBothChains) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */ {{{'a', 1}, {'b', 1}}, {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'a', 1}, {'c', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 4u);
+}
+
+// Multiple starters: (a,1) -> (b,2), (c,1) -> (d,2).
+// Start from {(a,2), (c,2)} => {(a,2), (b,3), (c,2), (d,3)}
+TEST_F(UnsafeBufferReachableAnalysisTest, MultipleStartersBothChains2) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */ {{{'a', 1}, {'b', 2}}, {{'c', 1}, {'d', 2}}},
+ /* StarterLayout */ {{'a', 2}, {'c', 2}}, __LINE__);
+ EXPECT_EQ(Reachables,
+ (std::set<Node>{{'a', 2}, {'b', 3}, {'c', 2}, {'d', 3}}));
+}
+
+// Multiple starters: (a,1) -> (b,1), (c,1) -> (d,1) (disconnected).
+// Start from leaves {(b,1), (d,1)} => {(b,1), (d,1)}
+TEST_F(UnsafeBufferReachableAnalysisTest, MultipleStartersLeaves) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c', 'd'},
+ /* EdgeLayout */ {{{'a', 1}, {'b', 1}}, {{'c', 1}, {'d', 1}}},
+ /* StarterLayout */ {{'b', 1}, {'d', 1}}, __LINE__);
+ EXPECT_EQ(Reachables.size(), 2u);
+ EXPECT_TRUE(Reachables.count({'b', 1}));
+ EXPECT_TRUE(Reachables.count({'d', 1}));
+}
+
+// Multi-key, same source entity: (a,1) -> (b,1), (a,2) -> (c,1).
+// Start from {(a,3)} => {(a,3), (b,3), (c,2)}
+TEST_F(UnsafeBufferReachableAnalysisTest, MultipleKeysSameEntity) {
+ auto Reachables = singlePartition(
+ /* EntityDomain */ {'a', 'b', 'c'},
+ /* EdgeLayout */ {{{'a', 1}, {'b', 1}}, {{'a', 2}, {'c', 1}}},
+ /* StarterLayout */ {{'a', 3}}, __LINE__);
+ EXPECT_EQ(Reachables, (std::set<Node>{{'a', 3}, {'b', 3}, {'c', 2}}));
+}
+
+} // namespace
>From 8d5a9885e12e8c89965f2719f42746d35f3c2cfc Mon Sep 17 00:00:00 2001
From: Aviral Goel <goel.aviral at gmail.com>
Date: Wed, 24 Jun 2026 09:44:01 -0700
Subject: [PATCH 5/6] Add
---
.../ScalableStaticAnalysis/Analyses/BUILD.gn | 27 +++++++++
.../lib/ScalableStaticAnalysis/Core/BUILD.gn | 37 ++++++++++++
.../ScalableStaticAnalysis/Frontend/BUILD.gn | 13 +++++
.../SourceTransformation/BUILD.gn | 12 ++++
.../lib/ScalableStaticAnalysis/Tool/BUILD.gn | 10 ++++
.../unittests/ScalableStaticAnalysis/BUILD.gn | 57 +++++++++++++++++++
6 files changed, 156 insertions(+)
create mode 100644 llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Analyses/BUILD.gn
create mode 100644 llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Core/BUILD.gn
create mode 100644 llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Frontend/BUILD.gn
create mode 100644 llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/SourceTransformation/BUILD.gn
create mode 100644 llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Tool/BUILD.gn
create mode 100644 llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysis/BUILD.gn
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Analyses/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Analyses/BUILD.gn
new file mode 100644
index 0000000000000..baf37a8328a18
--- /dev/null
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Analyses/BUILD.gn
@@ -0,0 +1,27 @@
+static_library("Analyses") {
+ output_name = "clangScalableStaticAnalysisAnalyses"
+ configs += [ "//llvm/utils/gn/build:clang_code" ]
+ deps = [
+ "//clang/lib/AST",
+ "//clang/lib/Analysis",
+ "//clang/lib/Basic",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//llvm/lib/Support",
+ ]
+ include_dirs = [ "." ]
+ sources = [
+ "CallGraph/CallGraphExtractor.cpp",
+ "CallGraph/CallGraphJSONFormat.cpp",
+ "EntityPointerLevel/EntityPointerLevel.cpp",
+ "EntityPointerLevel/EntityPointerLevelFormat.cpp",
+ "PointerFlow/PointerFlow.cpp",
+ "PointerFlow/PointerFlowAnalysis.cpp",
+ "PointerFlow/PointerFlowExtractor.cpp",
+ "PointerFlow/PointerFlowFormat.cpp",
+ "SSAFAnalysesCommon.cpp",
+ "UnsafeBufferUsage/UnsafeBufferUsage.cpp",
+ "UnsafeBufferUsage/UnsafeBufferUsageAnalysis.cpp",
+ "UnsafeBufferUsage/UnsafeBufferUsageExtractor.cpp",
+ "UnsafeBufferUsage/UnsafeBufferUsageFormat.cpp",
+ ]
+}
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Core/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Core/BUILD.gn
new file mode 100644
index 0000000000000..b0c1f30b769b1
--- /dev/null
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Core/BUILD.gn
@@ -0,0 +1,37 @@
+static_library("Core") {
+ output_name = "clangScalableStaticAnalysisCore"
+ configs += [ "//llvm/utils/gn/build:clang_code" ]
+ deps = [
+ "//clang/lib/AST",
+ "//clang/lib/UnifiedSymbolResolution",
+ "//llvm/lib/Support",
+ ]
+ sources = [
+ "ASTEntityMapping.cpp",
+ "EntityLinker/EntityLinker.cpp",
+ "Model/BuildNamespace.cpp",
+ "Model/EntityId.cpp",
+ "Model/EntityIdTable.cpp",
+ "Model/EntityLinkage.cpp",
+ "Model/EntityName.cpp",
+ "Model/SummaryName.cpp",
+ "Serialization/JSONFormat/Artifact.cpp",
+ "Serialization/JSONFormat/JSONEntitySummaryEncoding.cpp",
+ "Serialization/JSONFormat/JSONFormatImpl.cpp",
+ "Serialization/JSONFormat/LUSummary.cpp",
+ "Serialization/JSONFormat/LUSummaryEncoding.cpp",
+ "Serialization/JSONFormat/TUSummary.cpp",
+ "Serialization/JSONFormat/TUSummaryEncoding.cpp",
+ "Serialization/JSONFormat/WPASuite.cpp",
+ "Serialization/SerializationFormatRegistry.cpp",
+ "SummaryData/LUSummaryConsumer.cpp",
+ "SummaryData/SummaryDataBuilderRegistry.cpp",
+ "Support/ErrorBuilder.cpp",
+ "TUSummary/ExtractorRegistry.cpp",
+ "TUSummary/TUSummaryBuilder.cpp",
+ "TUSummary/TUSummaryExtractor.cpp",
+ "WholeProgramAnalysis/AnalysisDriver.cpp",
+ "WholeProgramAnalysis/AnalysisName.cpp",
+ "WholeProgramAnalysis/AnalysisRegistry.cpp",
+ ]
+}
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Frontend/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Frontend/BUILD.gn
new file mode 100644
index 0000000000000..bfdae02cbe65b
--- /dev/null
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Frontend/BUILD.gn
@@ -0,0 +1,13 @@
+static_library("Frontend") {
+ output_name = "clangScalableStaticAnalysisFrontend"
+ configs += [ "//llvm/utils/gn/build:clang_code" ]
+ deps = [
+ "//clang/lib/AST",
+ "//clang/lib/Basic",
+ "//clang/lib/Frontend",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/Sema",
+ "//llvm/lib/Support",
+ ]
+ sources = [ "TUSummaryExtractorFrontendAction.cpp" ]
+}
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/SourceTransformation/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/SourceTransformation/BUILD.gn
new file mode 100644
index 0000000000000..b6c57d82bbaea
--- /dev/null
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/SourceTransformation/BUILD.gn
@@ -0,0 +1,12 @@
+static_library("SourceTransformation") {
+ output_name = "clangScalableStaticAnalysisSourceTransformation"
+ configs += [ "//llvm/utils/gn/build:clang_code" ]
+ deps = [
+ "//clang/lib/AST",
+ "//clang/lib/Basic",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/Tooling/Core",
+ "//llvm/lib/Support",
+ ]
+ sources = [ "TransformationRegistry.cpp" ]
+}
diff --git a/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Tool/BUILD.gn b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Tool/BUILD.gn
new file mode 100644
index 0000000000000..874d1d3da17af
--- /dev/null
+++ b/llvm/utils/gn/secondary/clang/lib/ScalableStaticAnalysis/Tool/BUILD.gn
@@ -0,0 +1,10 @@
+static_library("Tool") {
+ output_name = "clangScalableStaticAnalysisTool"
+ configs += [ "//llvm/utils/gn/build:clang_code" ]
+ deps = [
+ "//clang/lib/Basic",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//llvm/lib/Support",
+ ]
+ sources = [ "Utils.cpp" ]
+}
diff --git a/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysis/BUILD.gn b/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysis/BUILD.gn
new file mode 100644
index 0000000000000..6d15d08e1e679
--- /dev/null
+++ b/llvm/utils/gn/secondary/clang/unittests/ScalableStaticAnalysis/BUILD.gn
@@ -0,0 +1,57 @@
+import("//third-party/unittest/unittest.gni")
+
+unittest("ClangScalableAnalysisTests") {
+ configs += [ "//llvm/utils/gn/build:clang_code" ]
+ deps = [
+ "//clang/lib/AST",
+ "//clang/lib/ASTMatchers",
+ "//clang/lib/Basic",
+ "//clang/lib/Frontend",
+ "//clang/lib/ScalableStaticAnalysis/Analyses",
+ "//clang/lib/ScalableStaticAnalysis/Core",
+ "//clang/lib/ScalableStaticAnalysis/Frontend",
+ "//clang/lib/ScalableStaticAnalysis/SourceTransformation",
+ "//clang/lib/Serialization",
+ "//clang/lib/Tooling",
+ "//clang/lib/Tooling/Core",
+ "//llvm/lib/Frontend/OpenMP",
+ "//llvm/lib/Support",
+ "//llvm/lib/Testing/Support",
+ ]
+ include_dirs = [ "." ]
+ sources = [
+ "ASTEntityMappingTest.cpp",
+ "Analyses/CallGraph/CallGraphExtractorTest.cpp",
+ "Analyses/PointerFlow/PointerFlowTest.cpp",
+ "Analyses/PointerFlow/PointerFlowWPATest.cpp",
+ "Analyses/UnsafeBufferUsage/UnsafeBufferUsageTest.cpp",
+ "Analyses/UnsafeBufferUsage/UnsafeBufferUsageWPATest.cpp",
+ "BuildNamespaceTest.cpp",
+ "EntityIdTableTest.cpp",
+ "EntityIdTest.cpp",
+ "EntityLinkageTest.cpp",
+ "EntityLinkerTest.cpp",
+ "EntityNameTest.cpp",
+ "ErrorBuilderTest.cpp",
+ "Frontend/TUSummaryExtractorFrontendActionTest.cpp",
+ "LUSummaryTest.cpp",
+ "ModelStringConversionsTest.cpp",
+ "Registries/FancyAnalysisData.cpp",
+ "Registries/MockSerializationFormat.cpp",
+ "Registries/MockSummaryExtractor1.cpp",
+ "Registries/MockSummaryExtractor2.cpp",
+ "Registries/SerializationFormatRegistryTest.cpp",
+ "Registries/SummaryExtractorRegistryTest.cpp",
+ "Serialization/JSONFormatTest/JSONFormatTest.cpp",
+ "Serialization/JSONFormatTest/LUSummaryTest.cpp",
+ "Serialization/JSONFormatTest/TUSummaryTest.cpp",
+ "SourceTransformation/EmitterTest.cpp",
+ "SourceTransformation/RegistryTest.cpp",
+ "SummaryData/SummaryDataTest.cpp",
+ "SummaryNameTest.cpp",
+ "TUSummaryBuilderTest.cpp",
+ "TestFixture.cpp",
+ "WholeProgramAnalysis/AnalysisDriverTest.cpp",
+ "WholeProgramAnalysis/UnsafeBufferReachableAnalysisTest.cpp",
+ ]
+}
>From 29b3629ee347d8d792bb902bade4ba1dee1334a6 Mon Sep 17 00:00:00 2001
From: Aviral Goel <goel.aviral at gmail.com>
Date: Wed, 24 Jun 2026 09:49:04 -0700
Subject: [PATCH 6/6] Remove bad file
---
.../Frontend/#%2Aediff-merge%2A#zEv5rY# | 198 ------------------
1 file changed, 198 deletions(-)
delete mode 100644 clang/lib/ScalableStaticAnalysis/Frontend/#%2Aediff-merge%2A#zEv5rY#
diff --git a/clang/lib/ScalableStaticAnalysis/Frontend/#%2Aediff-merge%2A#zEv5rY# b/clang/lib/ScalableStaticAnalysis/Frontend/#%2Aediff-merge%2A#zEv5rY#
deleted file mode 100644
index aa3351738c268..0000000000000
--- a/clang/lib/ScalableStaticAnalysis/Frontend/#%2Aediff-merge%2A#zEv5rY#
+++ /dev/null
@@ -1,198 +0,0 @@
-//===- TUSummaryExtractorFrontendAction.cpp -------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/ScalableStaticAnalysis/Frontend/TUSummaryExtractorFrontendAction.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/Basic/DiagnosticFrontend.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Frontend/MultiplexConsumer.h"
-#include "clang/ScalableStaticAnalysis/Core/Serialization/SerializationFormatRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/ExtractorRegistry.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummary.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryBuilder.h"
-#include "clang/ScalableStaticAnalysis/Core/TUSummary/TUSummaryExtractor.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/IOSandbox.h"
-#include "llvm/Support/Path.h"
-#include "llvm/TargetParser/Triple.h"
-#include <memory>
-#include <string>
-#include <vector>
-
-using namespace clang;
-using namespace ssaf;
-
-static std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
-parseOutputFileFormatAndPathOrReportError(DiagnosticsEngine &Diags,
- StringRef SSAFTUSummaryFile) {
-
- StringRef Ext = llvm::sys::path::extension(SSAFTUSummaryFile);
- StringRef FilePath = SSAFTUSummaryFile.drop_back(Ext.size());
-
- if (!Ext.consume_front(".") || FilePath.empty()) {
- Diags.Report(diag::warn_ssaf_extract_tu_summary_file_unknown_format)
- << SSAFTUSummaryFile;
- return std::nullopt;
- }
-
- if (!isFormatRegistered(Ext)) {
- Diags.Report(diag::warn_ssaf_extract_tu_summary_file_unknown_output_format)
- << Ext << SSAFTUSummaryFile;
- return std::nullopt;
- }
-
- return std::pair{Ext, FilePath};
-}
-
-/// Return \c true if reported unrecognized extractors.
-static bool
-reportUnrecognizedExtractorNames(DiagnosticsEngine &Diags,
- ArrayRef<std::string> SSAFExtractSummaries) {
- if (SSAFExtractSummaries.empty()) {
- Diags.Report(diag::warn_ssaf_must_enable_summary_extractors);
- return true;
- }
-
- std::vector<StringRef> UnrecognizedExtractorNames;
- for (StringRef Name : SSAFExtractSummaries)
- if (!isTUSummaryExtractorRegistered(Name))
- UnrecognizedExtractorNames.push_back(Name);
-
- if (!UnrecognizedExtractorNames.empty()) {
- Diags.Report(diag::warn_ssaf_extract_summary_unknown_extractor_name)
- << UnrecognizedExtractorNames.size()
- << llvm::join(UnrecognizedExtractorNames, ", ");
- return true;
- }
-
- return false;
-}
-
-static std::vector<std::unique_ptr<ASTConsumer>>
-makeTUSummaryExtractors(TUSummaryBuilder &Builder,
- ArrayRef<std::string> SSAFExtractSummaries) {
- std::vector<std::unique_ptr<ASTConsumer>> Extractors;
- Extractors.reserve(SSAFExtractSummaries.size());
- for (StringRef Name : SSAFExtractSummaries) {
- assert(isTUSummaryExtractorRegistered(Name));
- Extractors.push_back(makeTUSummaryExtractor(Name, Builder));
- }
- return Extractors;
-}
-
-namespace {
-
-/// Drives all extractor \c ASTConsumers and serializes the completed
-/// \c TUSummary.
-///
-/// Derives from \c MultiplexConsumer so every \c ASTConsumer virtual method is
-/// automatically forwarded to each extractor.
-class TUSummaryRunner final : public MultiplexConsumer {
-public:
- static std::unique_ptr<TUSummaryRunner> create(CompilerInstance &CI);
-
-private:
- TUSummaryRunner(llvm::Triple TargetTriple,
- std::unique_ptr<SerializationFormat> Format,
- const FrontendOptions &Opts);
-
- void HandleTranslationUnit(ASTContext &Ctx) override;
-
- TUSummary Summary;
- TUSummaryBuilder Builder = TUSummaryBuilder(Summary);
- std::unique_ptr<SerializationFormat> Format;
- const FrontendOptions &Opts;
-};
-} // namespace
-
-std::unique_ptr<TUSummaryRunner> TUSummaryRunner::create(CompilerInstance &CI) {
- const FrontendOptions &Opts = CI.getFrontendOpts();
- DiagnosticsEngine &Diags = CI.getDiagnostics();
-
- if (Opts.SSAFCompilationUnitId.empty()) {
- Diags.Report(diag::warn_ssaf_tu_summary_requires_compilation_unit_id);
- return nullptr;
- }
-
- auto MaybePair =
- parseOutputFileFormatAndPathOrReportError(Diags, Opts.SSAFTUSummaryFile);
- if (!MaybePair.has_value())
- return nullptr;
- auto [FormatName, OutputPath] = MaybePair.value();
-
- if (reportUnrecognizedExtractorNames(Diags, Opts.SSAFExtractSummaries))
- return nullptr;
-
- return std::unique_ptr<TUSummaryRunner>{
- new TUSummaryRunner{CI.getTarget().getTriple(), makeFormat(FormatName), Opts}};
-}
-
-TUSummaryRunner::TUSummaryRunner(llvm::Triple TargetTriple, std::unique_ptr<SerializationFormat> Format,
- const FrontendOptions &Opts)
- : MultiplexConsumer(std::vector<std::unique_ptr<ASTConsumer>>{}),
-<<<<<<< variant A
- Summary(std::move(TargetTriple),
- BuildNamespace(BuildNamespaceKind::CompilationUnit, InFile)),
->>>>>>> variant B
- Summary(BuildNamespace(BuildNamespaceKind::CompilationUnit,
- Opts.SSAFCompilationUnitId)),
-======= end
- Format(std::move(Format)), Opts(Opts) {
- assert(this->Format);
- assert(!Opts.SSAFCompilationUnitId.empty());
-
- // Now the Summary and the builders are constructed, we can also construct the
- // extractors.
- auto Extractors = makeTUSummaryExtractors(Builder, Opts.SSAFExtractSummaries);
- assert(!Extractors.empty());
-
- // We must initialize the Consumers here because our extractors need a
- // Builder that holds a reference to the TUSummary, which would be only
- // initialized after the MultiplexConsumer ctor. This is the only way we can
- // avoid the use of the TUSummary before it starts its lifetime.
- MultiplexConsumer::Consumers = std::move(Extractors);
-}
-
-void TUSummaryRunner::HandleTranslationUnit(ASTContext &Ctx) {
- // First, invoke the Summary Extractors.
- MultiplexConsumer::HandleTranslationUnit(Ctx);
-
- // FIXME(sandboxing): Remove this by adopting `llvm::vfs::OutputBackend`.
- llvm::sys::sandbox::ScopedSetting Guard = llvm::sys::sandbox::scopedDisable();
-
- // Then serialize the result.
- if (auto Err = Format->writeTUSummary(Summary, Opts.SSAFTUSummaryFile)) {
- Ctx.getDiagnostics().Report(diag::warn_ssaf_write_tu_summary_failed)
- << Opts.SSAFTUSummaryFile << llvm::toString(std::move(Err));
- }
-}
-
-TUSummaryExtractorFrontendAction::~TUSummaryExtractorFrontendAction() = default;
-
-TUSummaryExtractorFrontendAction::TUSummaryExtractorFrontendAction(
- std::unique_ptr<FrontendAction> WrappedAction)
- : WrapperFrontendAction(std::move(WrappedAction)) {}
-
-std::unique_ptr<ASTConsumer>
-TUSummaryExtractorFrontendAction::CreateASTConsumer(CompilerInstance &CI,
- StringRef InFile) {
- auto WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
- if (!WrappedConsumer)
- return nullptr;
-
- if (auto Runner = TUSummaryRunner::create(CI)) {
- CI.getCodeGenOpts().ClearASTBeforeBackend = false;
- std::vector<std::unique_ptr<ASTConsumer>> Consumers;
- Consumers.reserve(2);
- Consumers.push_back(std::move(WrappedConsumer));
- Consumers.push_back(std::move(Runner));
- return std::make_unique<MultiplexConsumer>(std::move(Consumers));
- }
- return WrappedConsumer;
-}
More information about the cfe-commits
mailing list