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

Reply via email to