clang 23.0.0git
WPASuite.cpp
Go to the documentation of this file.
1//===- WPASuite.cpp -------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "JSONFormatImpl.h"
10
12
13namespace clang::ssaf {
14
15//----------------------------------------------------------------------------
16// AnalysisResultMapEntry
17//----------------------------------------------------------------------------
18
19llvm::Expected<std::pair<AnalysisName, std::unique_ptr<AnalysisResult>>>
20JSONFormat::analysisResultMapEntryFromJSON(const Object &Entry) const {
21 auto OptName = Entry.getString("analysis_name");
22 if (!OptName) {
23 return ErrorBuilder::create(std::errc::invalid_argument,
25 "AnalysisName", "analysis_name", "string")
26 .build();
27 }
28
29 AnalysisName Name = analysisNameFromJSON(*OptName);
30
31 auto ExpectedCodec = AnalysisResultRegistry::instantiate(Name);
32 if (!ExpectedCodec) {
33 return ExpectedCodec.takeError();
34 }
35
36 const Object *ResultObj = Entry.getObject("result");
37 if (!ResultObj) {
38 return ErrorBuilder::create(std::errc::invalid_argument,
40 "AnalysisResult", "result", "object")
41 .build();
42 }
43
44 auto ExpectedResult =
45 (*ExpectedCodec)->deserialize(*ResultObj, &entityIdFromJSONObject);
46 if (!ExpectedResult) {
47 return ExpectedResult.takeError();
48 }
49
50 return std::make_pair(std::move(Name), std::move(*ExpectedResult));
51}
52
53llvm::Expected<Object> JSONFormat::analysisResultMapEntryToJSON(
54 const AnalysisName &Name,
55 const std::unique_ptr<AnalysisResult> &Result) const {
56 auto ExpectedCodec = AnalysisResultRegistry::instantiate(Name);
57 if (!ExpectedCodec) {
58 return ExpectedCodec.takeError();
59 }
60
61 Object Entry;
62 Entry["analysis_name"] = analysisNameToJSON(Name);
63 Entry["result"] = (*ExpectedCodec)->serialize(*Result, &entityIdToJSONObject);
64 return Entry;
65}
66
67//----------------------------------------------------------------------------
68// AnalysisResultMap
69//----------------------------------------------------------------------------
70
71llvm::Expected<std::map<AnalysisName, std::unique_ptr<AnalysisResult>>>
72JSONFormat::analysisResultMapFromJSON(const Array &ResultsArray) const {
73 std::map<AnalysisName, std::unique_ptr<AnalysisResult>> Results;
74
75 auto AsObject = [](const Value &V) { return V.getAsObject(); };
76 auto ObjectsRange = llvm::map_range(ResultsArray, AsObject);
77
78 for (auto [I, Entry] : enumerate(ObjectsRange)) {
79 if (!Entry) {
80 return ErrorBuilder::create(std::errc::invalid_argument,
82 "WPA result entry", I, "object")
83 .build();
84 }
85
86 auto ExpectedPair = analysisResultMapEntryFromJSON(*Entry);
87 if (!ExpectedPair) {
88 return ErrorBuilder::wrap(ExpectedPair.takeError())
89 .context(ErrorMessages::ReadingFromIndex, "WPA result entry", I)
90 .build();
91 }
92
93 auto [Name, Result] = std::move(*ExpectedPair);
94 bool Inserted = Results.try_emplace(Name, std::move(Result)).second;
95 if (!Inserted) {
96 return ErrorBuilder::create(std::errc::invalid_argument,
98 "WPA result", I, Name)
99 .build();
100 }
101 }
102 return std::move(Results);
103}
104
105llvm::Expected<Array> JSONFormat::analysisResultMapToJSON(
106 const std::map<AnalysisName, std::unique_ptr<AnalysisResult>> &Data) const {
107 Array Results;
108 for (const auto &[Name, Result] : Data) {
109 auto ExpectedEntry = analysisResultMapEntryToJSON(Name, Result);
110 if (!ExpectedEntry) {
111 return ExpectedEntry.takeError();
112 }
113 Results.push_back(std::move(*ExpectedEntry));
114 }
115 return Results;
116}
117
118//----------------------------------------------------------------------------
119// WPASuite
120//----------------------------------------------------------------------------
121
123 auto ExpectedJSON = readJSON(Path);
124 if (!ExpectedJSON) {
125 return ErrorBuilder::wrap(ExpectedJSON.takeError())
126 .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
127 .build();
128 }
129
130 Object *RootObjectPtr = ExpectedJSON->getAsObject();
131 if (!RootObjectPtr) {
132 return ErrorBuilder::create(std::errc::invalid_argument,
134 "object")
135 .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
136 .build();
137 }
138
139 const Object &RootObject = *RootObjectPtr;
140
141 WPASuite Suite = makeWPASuite();
142
143 {
144 const Array *IdTableArray = RootObject.getArray("id_table");
145 if (!IdTableArray) {
146 return ErrorBuilder::create(std::errc::invalid_argument,
148 "IdTable", "id_table", "array")
149 .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
150 .build();
151 }
152
153 auto ExpectedIdTable = entityIdTableFromJSON(*IdTableArray);
154 if (!ExpectedIdTable) {
155 return ErrorBuilder::wrap(ExpectedIdTable.takeError())
156 .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
157 .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
158 .build();
159 }
160
161 getIdTable(Suite) = std::move(*ExpectedIdTable);
162 }
163
164 {
165 const Array *ResultsArray = RootObject.getArray("results");
166 if (!ResultsArray) {
167 return ErrorBuilder::create(std::errc::invalid_argument,
169 "WPA results", "results", "array")
170 .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
171 .build();
172 }
173
174 auto ExpectedResultsMap = analysisResultMapFromJSON(*ResultsArray);
175 if (!ExpectedResultsMap) {
176 return ErrorBuilder::wrap(ExpectedResultsMap.takeError())
177 .context(ErrorMessages::ReadingFromField, "WPA results", "results")
178 .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
179 .build();
180 }
181
182 getData(Suite) = std::move(*ExpectedResultsMap);
183 }
184
185 return std::move(Suite);
186}
187
188llvm::Error JSONFormat::writeWPASuite(const WPASuite &Suite,
189 llvm::StringRef Path) {
190 Object RootObject;
191
192 RootObject["id_table"] = entityIdTableToJSON(getIdTable(Suite));
193
194 auto ExpectedResults = analysisResultMapToJSON(getData(Suite));
195 if (!ExpectedResults) {
196 return ErrorBuilder::wrap(ExpectedResults.takeError())
197 .context(ErrorMessages::WritingToFile, "WPASuite", Path)
198 .build();
199 }
200
201 RootObject["results"] = std::move(*ExpectedResults);
202
203 if (auto Error = writeJSON(std::move(RootObject), Path)) {
204 return ErrorBuilder::wrap(std::move(Error))
205 .context(ErrorMessages::WritingToFile, "WPASuite", Path)
206 .build();
207 }
208
209 return llvm::Error::success();
210}
211
212} // namespace clang::ssaf
#define V(N, I)
Uniquely identifies a whole-program analysis and the AnalysisResult it produces.
static ErrorBuilder create(std::error_code EC, const char *Fmt, Args &&...ArgVals)
Create an ErrorBuilder with an error code and formatted message.
ErrorBuilder & context(const char *Msg)
Add context information as a plain string.
llvm::Error build() const
Build and return the final error.
static ErrorBuilder wrap(llvm::Error E)
Wrap an existing error and optionally add context.
llvm::Expected< WPASuite > readWPASuite(llvm::StringRef Path) override
Definition WPASuite.cpp:122
llvm::Error writeWPASuite(const WPASuite &Suite, llvm::StringRef Path) override
Definition WPASuite.cpp:188
static WPASuite makeWPASuite()
Constructs an empty WPASuite.
Bundles the EntityIdTable (moved from the LUSummary) and the analysis results produced by one Analysi...
Definition WPASuite.h:37
constexpr const char * ReadingFromFile
constexpr const char * ReadingFromField
constexpr const char * FailedToReadObjectAtIndex
constexpr const char * FailedToReadObjectAtField
constexpr const char * WritingToFile
constexpr const char * ReadingFromIndex
constexpr const char * FailedInsertionOnDuplication
constexpr const char * FailedToReadObject
llvm::json::Array Array
llvm::StringRef analysisNameToJSON(const AnalysisName &AN)
AnalysisName analysisNameFromJSON(llvm::StringRef AnalysisNameStr)
llvm::json::Object Object
llvm::Expected< Value > readJSON(llvm::StringRef Path)
llvm::Error writeJSON(Value &&V, llvm::StringRef Path)
@ Result
The result type of a method or function.
Definition TypeBase.h:905