llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-ssaf Author: Aviral Goel (aviralg) <details> <summary>Changes</summary> This patch adds `JSONFormat` serialization support for `WPASuite`. - Adds `readWPASuite` / `writeWPASuite` to the `SerializationFormat` abstract interface and implements them in `JSONFormat`. - Introduces `AnalysisResultRegistryGenerator`, a per-format plugin registry template in `SerializationFormat`, allowing analysis authors to register (de)serializers for their `AnalysisResult` subtypes with a single static declaration. - Extends `PrivateFieldNames.def` with `WPASuite::Data` and `WPASuite::IdTable`, and adds a `makeWPASuite()` factory to `SerializationFormat`, so deserialization code can construct a `WPASuite` incrementally through the same access-controlled pattern used for all other SSAF data structures. --- Patch is 49.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/187403.diff 34 Files Affected: - (modified) clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def (+2) - (modified) clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h (+29) - (modified) clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h (+100) - (modified) clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h (+2-2) - (modified) clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h (+4) - (modified) clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt (+1) - (modified) clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt (+1) - (modified) clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp (+12) - (modified) clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h (+8) - (added) clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp (+209) - (added) clang/lib/ScalableStaticAnalysisFramework/Plugins/CMakeLists.txt (+12) - (added) clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/CMakeLists.txt (+21) - (added) clang/lib/ScalableStaticAnalysisFramework/Plugins/ExamplePlugin/ExamplePlugin.cpp (+151) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/duplicate-analysis-name.json (+7) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/missing-results.json (+1) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/result-entry-analysis-name-not-string.json (+1) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/result-entry-deserializer-error.json (+1) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/result-entry-missing-analysis-name.json (+1) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/result-entry-missing-result-field.json (+1) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/result-entry-no-format-info.json (+1) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/result-entry-not-object.json (+1) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/result-entry-result-not-object.json (+1) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/results-not-array.json (+1) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/rt-empty.json (+4) - (added) clang/test/Analysis/Scalable/ssaf-format/Inputs/rt-multiple-results.json (+40) - (added) clang/test/Analysis/Scalable/ssaf-format/lit.local.cfg (+4) - (added) clang/test/Analysis/Scalable/ssaf-format/wpa-suite.test (+98) - (modified) clang/test/CMakeLists.txt (+6) - (modified) clang/tools/clang-ssaf-format/CMakeLists.txt (+4) - (modified) clang/tools/clang-ssaf-format/SSAFFormat.cpp (+8-2) - (modified) clang/unittests/ScalableStaticAnalysisFramework/Frontend/TUSummaryExtractorFrontendActionTest.cpp (+9) - (modified) clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.cpp (+10) - (modified) clang/unittests/ScalableStaticAnalysisFramework/Registries/MockSerializationFormat.h (+5) - (modified) clang/unittests/ScalableStaticAnalysisFramework/TestFixture.h (+3) ``````````diff diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def index 1ee2a809430f4..1c75543062cbc 100644 --- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def +++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Model/PrivateFieldNames.def @@ -42,5 +42,7 @@ 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/Serialization/JSONFormat.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h index 47b46cbe42698..18dc71585b0fd 100644 --- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h +++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat.h @@ -58,6 +58,11 @@ class JSONFormat final : public SerializationFormat { 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; @@ -74,6 +79,16 @@ class JSONFormat final : public SerializationFormat { 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(); @@ -186,6 +201,18 @@ class JSONFormat final : public SerializationFormat { 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 @@ -193,6 +220,8 @@ class JSONFormat final : public SerializationFormat { namespace llvm { extern template class CLANG_TEMPLATE_ABI Registry<clang::ssaf::JSONFormat::FormatInfo>; +extern template class CLANG_TEMPLATE_ABI + Registry<clang::ssaf::JSONFormat::AnalysisResultRegistry::Entry>; } // namespace llvm #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 index 7aebf06a6368e..fe71e37f08878 100644 --- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h +++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/Serialization/SerializationFormat.h @@ -19,10 +19,13 @@ #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" namespace clang::ssaf { @@ -55,6 +58,11 @@ class SerializationFormat { 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( @@ -67,10 +75,102 @@ class SerializationFormat { 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: + /// + /// static MyFormat::AnalysisResultRegistry::Add<MyAnalysisResult> + /// Reg(serializeFn, deserializeFn); + /// + /// The serializer receives \c const MyAnalysisResult & directly — the + /// \c Add wrapper handles the downcast from \c AnalysisResult internally. + /// + /// \p FormatT is otherwise unused — it exists because \c llvm::Registry + /// is keyed on the \c Entry type, so two formats that happen to share the + /// same serializer/deserializer signatures would collide without a + /// disambiguating template parameter. + /// + /// \c function_ref is non-owning, but \c llvm::Registry only stores + /// nullary factories (no captured state). Function-local statics inside + /// \c Add<T>::Add(...) give each analysis's \c function_ref values a + /// stable, program-lifetime home, and a local \c ConcreteEntry struct + /// reads them back when the registry instantiates the factory. + template <class FormatT, class SerializerFn, class DeserializerFn> + class AnalysisResultRegistryGenerator { + public: + struct Entry { + explicit Entry(SerializerFn Serialize, DeserializerFn Deserialize) + : Serialize(Serialize), Deserialize(Deserialize) {} + virtual ~Entry() = default; + SerializerFn Serialize; + DeserializerFn Deserialize; + }; + + using RegistryT = llvm::Registry<Entry>; + + template <class AnalysisResultT> struct Add { + /// Extracts the typed serializer signature from \c SerializerFn. + /// Given \c function_ref<R(const AnalysisResult &, Args...)>, produces + /// a function-pointer type \c R(*)(const AnalysisResultT &, Args...) and + /// a static \c wrap() that downcasts and forwards. + template <class> struct SerializerAdapter; + template <class R, class... Args> + struct SerializerAdapter< + llvm::function_ref<R(const AnalysisResult &, Args...)>> { + using TypedFnPtr = R (*)(const AnalysisResultT &, Args...); + static inline TypedFnPtr Saved = nullptr; + static R wrap(const AnalysisResult &Base, Args... args) { + return Saved(static_cast<const AnalysisResultT &>(Base), args...); + } + }; + using SA = SerializerAdapter<SerializerFn>; + + Add(typename SA::TypedFnPtr TypedSerialize, DeserializerFn Deserialize) { + static bool Registered = false; + if (Registered) { + ErrorBuilder::fatal("support is already registered for analysis: {0}", + AnalysisResultT::analysisName()); + } + Registered = true; + SA::Saved = TypedSerialize; + static auto *SerializeWrap = &SA::wrap; + static SerializerFn SavedSerialize(SerializeWrap); + static DeserializerFn SavedDeserialize = Deserialize; + + struct ConcreteEntry : Entry { + ConcreteEntry() : Entry(SavedSerialize, SavedDeserialize) {} + }; + + static std::string NameStr = + AnalysisResultT::analysisName().str().str(); + static typename RegistryT::template Add<ConcreteEntry> Reg(NameStr, ""); + } + }; + + static llvm::Expected<std::pair<SerializerFn, DeserializerFn>> + lookup(const AnalysisName &Name) { + for (const auto &E : RegistryT::entries()) { + if (E.getName() == Name.str()) { + auto Entry = E.instantiate(); + return std::make_pair(Entry->Serialize, Entry->Deserialize); + } + } + return ErrorBuilder::create(std::errc::invalid_argument, + "no support registered for analysis: {0}", + Name) + .build(); + } + }; }; template <class SerializerFn, class DeserializerFn> struct FormatInfoEntry { diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h index 4eb35262d4625..0e1eb8e9b8b87 100644 --- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h +++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/DerivedAnalysis.h @@ -99,10 +99,10 @@ class DerivedAnalysis : public DerivedAnalysisBase { /// Performs one step. Returns true if another step is needed; false when /// converged. Single-step analyses always return false. - virtual llvm::Expected<bool> step() = 0; + virtual llvm::Expected<bool> step() override = 0; /// Called after the step() loop converges. Override for post-processing. - virtual llvm::Error finalize() { return llvm::Error::success(); } + virtual llvm::Error finalize() override { return llvm::Error::success(); } protected: /// Read-only access to the result being built. diff --git a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h index 5a0105fc1f4d9..52c6f9e46297d 100644 --- a/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h +++ b/clang/include/clang/ScalableStaticAnalysisFramework/Core/WholeProgramAnalysis/WPASuite.h @@ -26,6 +26,8 @@ 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. @@ -34,6 +36,8 @@ class AnalysisDriver; /// 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; diff --git a/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt index 3da5c8899ddb6..e09c44b7cfd52 100644 --- a/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt +++ b/clang/lib/ScalableStaticAnalysisFramework/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(Analyses) add_subdirectory(Core) add_subdirectory(Frontend) +add_subdirectory(Plugins) add_subdirectory(Tool) diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt b/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt index 8c306163df1a7..83772ceff58bf 100644 --- a/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt +++ b/clang/lib/ScalableStaticAnalysisFramework/Core/CMakeLists.txt @@ -17,6 +17,7 @@ add_clang_library(clangScalableStaticAnalysisFrameworkCore 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 diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp index 4072532d4972c..1238192628cb2 100644 --- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp +++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.cpp @@ -14,6 +14,8 @@ // NOLINTNEXTLINE(misc-use-internal-linkage) volatile int SSAFJSONFormatAnchorSource = 0; LLVM_INSTANTIATE_REGISTRY(llvm::Registry<clang::ssaf::JSONFormat::FormatInfo>) +LLVM_INSTANTIATE_REGISTRY( + llvm::Registry<clang::ssaf::JSONFormat::AnalysisResultRegistry::Entry>) static clang::ssaf::SerializationFormatRegistry::Add<clang::ssaf::JSONFormat> RegisterJSONFormat("json", "JSON serialization format"); @@ -141,6 +143,16 @@ SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr) { llvm::StringRef summaryNameToJSON(const SummaryName &SN) { return SN.str(); } +//---------------------------------------------------------------------------- +// AnalysisName +//---------------------------------------------------------------------------- + +AnalysisName analysisNameFromJSON(llvm::StringRef AnalysisNameStr) { + return AnalysisName(AnalysisNameStr.str()); +} + +llvm::StringRef analysisNameToJSON(const AnalysisName &AN) { return AN.str(); } + //---------------------------------------------------------------------------- // EntityId //---------------------------------------------------------------------------- diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h index 2ff1f2ae16192..31a605efe90a5 100644 --- a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h +++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/JSONFormatImpl.h @@ -21,6 +21,7 @@ #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" @@ -139,6 +140,13 @@ llvm::Error writeJSON(Value &&V, llvm::StringRef Path); 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 //---------------------------------------------------------------------------- diff --git a/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp new file mode 100644 index 0000000000000..1d1e442e63c92 --- /dev/null +++ b/clang/lib/ScalableStaticAnalysisFramework/Core/Serialization/JSONFormat/WPASuite.cpp @@ -0,0 +1,209 @@ +//===- 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 ExpectedFns = AnalysisResultRegistry::lookup(Name); + if (!ExpectedFns) { + return ExpectedFns.takeError(); + } + + const Object *ResultObj = Entry.getObject("result"); + if (!ResultObj) { + return ErrorBuilder::create(std::errc::invalid_argument, + ErrorMessages::FailedToReadObjectAtField, + "AnalysisResult", "result", "object") + .build(); + } + + auto ExpectedResult = + ExpectedFns->second(*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 ExpectedFns = AnalysisResultRegistry::lookup(Name); + if (!ExpectedFns) { + return ExpectedFns.takeError(); + } + + Object Entry; + Entry["analysis_name"] = analysisNameToJSON(Name); + Entry["result"] = ExpectedFns->first(*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; + for (size_t I = 0; I < ResultsArray.size(); ++I) { + const Object *Entry = ResultsArray[I].getAsObject(); + 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 Results; +} + +llvm::Expected<Array> JSONFormat::analysisR... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/187403 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
