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 if (auto Err = checkSummaryType(*RootObjectPtr, JSONTypeValueWPASuite)) {
140 return ErrorBuilder::wrap(std::move(Err))
141 .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
142 .build();
143 }
144
145 auto ExpectedSuite = readWPASuiteFromObject(*RootObjectPtr);
146 if (!ExpectedSuite) {
147 return ErrorBuilder::wrap(ExpectedSuite.takeError())
148 .context(ErrorMessages::ReadingFromFile, "WPASuite", Path)
149 .build();
150 }
151
152 return std::move(*ExpectedSuite);
153}
154
156JSONFormat::readWPASuiteFromObject(const Object &RootObject) {
157 WPASuite Suite = makeWPASuite();
158
159 {
160 const Array *IdTableArray = RootObject.getArray("id_table");
161 if (!IdTableArray) {
162 return ErrorBuilder::create(std::errc::invalid_argument,
164 "IdTable", "id_table", "array")
165 .build();
166 }
167
168 auto ExpectedIdTable = luEntityIdTableFromJSON(*IdTableArray);
169 if (!ExpectedIdTable) {
170 return ErrorBuilder::wrap(ExpectedIdTable.takeError())
171 .context(ErrorMessages::ReadingFromField, "IdTable", "id_table")
172 .build();
173 }
174
175 getIdTable(Suite) = std::move(*ExpectedIdTable);
176 }
177
178 {
179 const Array *ResultsArray = RootObject.getArray("results");
180 if (!ResultsArray) {
181 return ErrorBuilder::create(std::errc::invalid_argument,
183 "WPA results", "results", "array")
184 .build();
185 }
186
187 auto ExpectedResultsMap = analysisResultMapFromJSON(*ResultsArray);
188 if (!ExpectedResultsMap) {
189 return ErrorBuilder::wrap(ExpectedResultsMap.takeError())
190 .context(ErrorMessages::ReadingFromField, "WPA results", "results")
191 .build();
192 }
193
194 getData(Suite) = std::move(*ExpectedResultsMap);
195 }
196
197 return std::move(Suite);
198}
199
200llvm::Error JSONFormat::writeWPASuite(const WPASuite &Suite,
201 llvm::StringRef Path) {
202 Object RootObject;
203
205
206 RootObject["id_table"] = luEntityIdTableToJSON(getIdTable(Suite));
207
208 auto ExpectedResults = analysisResultMapToJSON(getData(Suite));
209 if (!ExpectedResults) {
210 return ErrorBuilder::wrap(ExpectedResults.takeError())
211 .context(ErrorMessages::WritingToFile, "WPASuite", Path)
212 .build();
213 }
214
215 RootObject["results"] = std::move(*ExpectedResults);
216
217 if (auto Error = writeJSON(std::move(RootObject), Path)) {
218 return ErrorBuilder::wrap(std::move(Error))
219 .context(ErrorMessages::WritingToFile, "WPASuite", Path)
220 .build();
221 }
222
223 return llvm::Error::success();
224}
225
226} // 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:200
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
constexpr const char * JSONTypeKey
Root-object key naming the summary kind so files are self-describing.
constexpr const char * JSONTypeValueWPASuite
Value written to JSONTypeKey for serialized WPASuite files.
llvm::StringRef analysisNameToJSON(const AnalysisName &AN)
AnalysisName analysisNameFromJSON(llvm::StringRef AnalysisNameStr)
llvm::json::Object Object
llvm::Expected< Value > readJSON(llvm::StringRef Path)
llvm::Error checkSummaryType(const Object &RootObject, llvm::StringRef ExpectedType)
Reads the JSONTypeKey field from the root object and verifies it equals ExpectedType.
llvm::Error writeJSON(Value &&V, llvm::StringRef Path)
@ Result
The result type of a method or function.
Definition TypeBase.h:905