1#include "clang/Analysis/Scalable/Serialization/JSONFormat.h"
2#include "clang/Analysis/Scalable/Model/EntityLinkage.h"
3#include "clang/Analysis/Scalable/Support/ErrorBuilder.h"
4#include "clang/Analysis/Scalable/TUSummary/TUSummary.h"
5
6#include "llvm/ADT/STLExtras.h"
7#include "llvm/ADT/StringExtras.h"
8#include "llvm/Support/ErrorHandling.h"
9#include "llvm/Support/FileSystem.h"
10#include "llvm/Support/FormatVariadic.h"
11#include "llvm/Support/JSON.h"
12#include "llvm/Support/MemoryBuffer.h"
13#include "llvm/Support/Path.h"
14#include "llvm/Support/Registry.h"
15
16using namespace clang::ssaf;
17
18using Array = llvm::json::Array;
19using Object = llvm::json::Object;
20using Value = llvm::json::Value;
21
22LLVM_INSTANTIATE_REGISTRY(llvm::Registry<JSONFormat::FormatInfo>)
23
24//----------------------------------------------------------------------------
25// File Format Constant
26//----------------------------------------------------------------------------
27
28namespace {
29
30constexpr const char *JSONFormatFileExtension = ".json";
31
32}
33
34//----------------------------------------------------------------------------
35// Error Message Constants
36//----------------------------------------------------------------------------
37
38namespace {
39
40namespace ErrorMessages {
41
42constexpr const char *FailedToReadFile = "failed to read file '{0}': {1}";
43constexpr const char *FailedToWriteFile = "failed to write file '{0}': {1}";
44constexpr const char *FileNotFound = "file does not exist";
45constexpr const char *FileIsDirectory = "path is a directory, not a file";
46constexpr const char *FileIsNotJSON = "file does not end with '{0}' extension";
47constexpr const char *FileExists = "file already exists";
48constexpr const char *ParentDirectoryNotFound =
49 "parent directory does not exist";
50
51constexpr const char *ReadingFromField = "reading {0} from field '{1}'";
52constexpr const char *WritingToField = "writing {0} to field '{1}'";
53constexpr const char *ReadingFromIndex = "reading {0} from index '{1}'";
54constexpr const char *WritingToIndex = "writing {0} to index '{1}'";
55constexpr const char *ReadingFromFile = "reading {0} from file '{1}'";
56constexpr const char *WritingToFile = "writing {0} to file '{1}'";
57
58constexpr const char *FailedInsertionOnDuplication =
59 "failed to insert {0} at index '{1}': encountered duplicate {2} '{3}'";
60
61constexpr const char *FailedToReadObject =
62 "failed to read {0}: expected JSON {1}";
63constexpr const char *FailedToReadObjectAtField =
64 "failed to read {0} from field '{1}': expected JSON {2}";
65constexpr const char *FailedToReadObjectAtIndex =
66 "failed to read {0} from index '{1}': expected JSON {2}";
67
68constexpr const char *FailedToDeserializeEntitySummary =
69 "failed to deserialize EntitySummary: no FormatInfo registered for summary "
70 "'{0}'";
71constexpr const char *FailedToSerializeEntitySummary =
72 "failed to serialize EntitySummary: no FormatInfo registered for summary "
73 "'{0}'";
74
75constexpr const char *InvalidBuildNamespaceKind =
76 "invalid 'kind' BuildNamespaceKind value '{0}'";
77
78constexpr const char *InvalidEntityLinkageType =
79 "invalid 'type' EntityLinkageType value '{0}'";
80
81constexpr const char *FailedToDeserializeLinkageTableExtraId =
82 "failed to deserialize LinkageTable: extra EntityId '{0}' not present in "
83 "IdTable";
84
85constexpr const char *FailedToDeserializeLinkageTableMissingId =
86 "failed to deserialize LinkageTable: missing EntityId '{0}' present in "
87 "IdTable";
88
89} // namespace ErrorMessages
90
91} // namespace
92
93//----------------------------------------------------------------------------
94// JSON Reader and Writer
95//----------------------------------------------------------------------------
96
97namespace {
98
99llvm::Expected<Value> readJSON(llvm::StringRef Path) {
100 if (!llvm::sys::fs::exists(Path)) {
101 return ErrorBuilder::create(EC: std::errc::no_such_file_or_directory,
102 Fmt: ErrorMessages::FailedToReadFile, ArgVals&: Path,
103 ArgVals: ErrorMessages::FileNotFound)
104 .build();
105 }
106
107 if (llvm::sys::fs::is_directory(Path)) {
108 return ErrorBuilder::create(EC: std::errc::is_a_directory,
109 Fmt: ErrorMessages::FailedToReadFile, ArgVals&: Path,
110 ArgVals: ErrorMessages::FileIsDirectory)
111 .build();
112 }
113
114 if (!Path.ends_with_insensitive(Suffix: JSONFormatFileExtension)) {
115 return ErrorBuilder::create(EC: std::errc::invalid_argument,
116 Fmt: ErrorMessages::FailedToReadFile, ArgVals&: Path,
117 ArgVals: llvm::formatv(Fmt: ErrorMessages::FileIsNotJSON,
118 Vals: JSONFormatFileExtension))
119 .build();
120 }
121
122 auto BufferOrError = llvm::MemoryBuffer::getFile(Filename: Path);
123 if (!BufferOrError) {
124 const std::error_code EC = BufferOrError.getError();
125 return ErrorBuilder::create(EC, Fmt: ErrorMessages::FailedToReadFile, ArgVals&: Path,
126 ArgVals: EC.message())
127 .build();
128 }
129
130 return llvm::json::parse(JSON: BufferOrError.get()->getBuffer());
131}
132
133llvm::Error writeJSON(Value &&Value, llvm::StringRef Path) {
134 if (llvm::sys::fs::exists(Path)) {
135 return ErrorBuilder::create(EC: std::errc::file_exists,
136 Fmt: ErrorMessages::FailedToWriteFile, ArgVals&: Path,
137 ArgVals: ErrorMessages::FileExists)
138 .build();
139 }
140
141 llvm::StringRef Dir = llvm::sys::path::parent_path(path: Path);
142 if (!Dir.empty() && !llvm::sys::fs::is_directory(Path: Dir)) {
143 return ErrorBuilder::create(EC: std::errc::no_such_file_or_directory,
144 Fmt: ErrorMessages::FailedToWriteFile, ArgVals&: Path,
145 ArgVals: ErrorMessages::ParentDirectoryNotFound)
146 .build();
147 }
148
149 if (!Path.ends_with_insensitive(Suffix: JSONFormatFileExtension)) {
150 return ErrorBuilder::create(EC: std::errc::invalid_argument,
151 Fmt: ErrorMessages::FailedToWriteFile, ArgVals&: Path,
152 ArgVals: llvm::formatv(Fmt: ErrorMessages::FileIsNotJSON,
153 Vals: JSONFormatFileExtension))
154 .build();
155 }
156
157 std::error_code EC;
158 llvm::raw_fd_ostream OutStream(Path, EC, llvm::sys::fs::OF_Text);
159
160 if (EC) {
161 return ErrorBuilder::create(EC, Fmt: ErrorMessages::FailedToWriteFile, ArgVals&: Path,
162 ArgVals: EC.message())
163 .build();
164 }
165
166 OutStream << llvm::formatv(Fmt: "{0:2}\n", Vals&: Value);
167 OutStream.flush();
168
169 if (OutStream.has_error()) {
170 return ErrorBuilder::create(EC: OutStream.error(),
171 Fmt: ErrorMessages::FailedToWriteFile, ArgVals&: Path,
172 ArgVals: OutStream.error().message())
173 .build();
174 }
175
176 return llvm::Error::success();
177}
178
179} // namespace
180
181//----------------------------------------------------------------------------
182// JSONFormat Static Methods
183//----------------------------------------------------------------------------
184
185std::map<SummaryName, JSONFormat::FormatInfo> JSONFormat::initFormatInfos() {
186 std::map<SummaryName, FormatInfo> FormatInfos;
187 for (const auto &FormatInfoEntry : llvm::Registry<FormatInfo>::entries()) {
188 std::unique_ptr<FormatInfo> Info = FormatInfoEntry.instantiate();
189 bool Inserted = FormatInfos.try_emplace(k: Info->ForSummary, args&: *Info).second;
190 if (!Inserted) {
191 llvm::report_fatal_error(
192 reason: "FormatInfo is already registered for summary: " +
193 Info->ForSummary.str());
194 }
195 }
196 return FormatInfos;
197}
198
199//----------------------------------------------------------------------------
200// SummaryName
201//----------------------------------------------------------------------------
202
203namespace {
204
205SummaryName summaryNameFromJSON(llvm::StringRef SummaryNameStr) {
206 return SummaryName(SummaryNameStr.str());
207}
208
209llvm::StringRef summaryNameToJSON(const SummaryName &SN) { return SN.str(); }
210
211} // namespace
212
213//----------------------------------------------------------------------------
214// EntityId
215//----------------------------------------------------------------------------
216
217EntityId JSONFormat::entityIdFromJSON(const uint64_t EntityIdIndex) const {
218 return makeEntityId(Index: static_cast<size_t>(EntityIdIndex));
219}
220
221uint64_t JSONFormat::entityIdToJSON(EntityId EI) const {
222 return static_cast<uint64_t>(getIndex(X&: EI));
223}
224
225//----------------------------------------------------------------------------
226// BuildNamespaceKind
227//----------------------------------------------------------------------------
228
229llvm::Expected<BuildNamespaceKind> JSONFormat::buildNamespaceKindFromJSON(
230 llvm::StringRef BuildNamespaceKindStr) const {
231 auto OptBuildNamespaceKind = parseBuildNamespaceKind(Str: BuildNamespaceKindStr);
232 if (!OptBuildNamespaceKind) {
233 return ErrorBuilder::create(EC: std::errc::invalid_argument,
234 Fmt: ErrorMessages::InvalidBuildNamespaceKind,
235 ArgVals&: BuildNamespaceKindStr)
236 .build();
237 }
238
239 return *OptBuildNamespaceKind;
240}
241
242namespace {
243
244llvm::StringRef buildNamespaceKindToJSON(BuildNamespaceKind BNK) {
245 return toString(BNK);
246}
247
248} // namespace
249
250//----------------------------------------------------------------------------
251// NestedBuildNamespace
252//----------------------------------------------------------------------------
253
254llvm::Expected<BuildNamespace>
255JSONFormat::buildNamespaceFromJSON(const Object &BuildNamespaceObject) const {
256 auto OptBuildNamespaceKindStr = BuildNamespaceObject.getString(K: "kind");
257 if (!OptBuildNamespaceKindStr) {
258 return ErrorBuilder::create(EC: std::errc::invalid_argument,
259 Fmt: ErrorMessages::FailedToReadObjectAtField,
260 ArgVals: "BuildNamespaceKind", ArgVals: "kind", ArgVals: "string")
261 .build();
262 }
263
264 auto ExpectedKind = buildNamespaceKindFromJSON(BuildNamespaceKindStr: *OptBuildNamespaceKindStr);
265 if (!ExpectedKind)
266 return ErrorBuilder::wrap(E: ExpectedKind.takeError())
267 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "BuildNamespaceKind", ArgVals: "kind")
268 .build();
269
270 auto OptNameStr = BuildNamespaceObject.getString(K: "name");
271 if (!OptNameStr) {
272 return ErrorBuilder::create(EC: std::errc::invalid_argument,
273 Fmt: ErrorMessages::FailedToReadObjectAtField,
274 ArgVals: "BuildNamespaceName", ArgVals: "name", ArgVals: "string")
275 .build();
276 }
277
278 return {BuildNamespace(*ExpectedKind, *OptNameStr)};
279}
280
281Object JSONFormat::buildNamespaceToJSON(const BuildNamespace &BN) const {
282 Object Result;
283 Result["kind"] = buildNamespaceKindToJSON(BNK: getKind(X: BN));
284 Result["name"] = getName(X: BN);
285 return Result;
286}
287
288//----------------------------------------------------------------------------
289// NestedBuildNamespace
290//----------------------------------------------------------------------------
291
292llvm::Expected<NestedBuildNamespace> JSONFormat::nestedBuildNamespaceFromJSON(
293 const Array &NestedBuildNamespaceArray) const {
294 std::vector<BuildNamespace> Namespaces;
295
296 size_t NamespaceCount = NestedBuildNamespaceArray.size();
297 Namespaces.reserve(n: NamespaceCount);
298
299 for (const auto &[Index, BuildNamespaceValue] :
300 llvm::enumerate(First: NestedBuildNamespaceArray)) {
301
302 const Object *BuildNamespaceObject = BuildNamespaceValue.getAsObject();
303 if (!BuildNamespaceObject) {
304 return ErrorBuilder::create(EC: std::errc::invalid_argument,
305 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
306 ArgVals: "BuildNamespace", ArgVals&: Index, ArgVals: "object")
307 .build();
308 }
309
310 auto ExpectedBuildNamespace = buildNamespaceFromJSON(BuildNamespaceObject: *BuildNamespaceObject);
311 if (!ExpectedBuildNamespace) {
312 return ErrorBuilder::wrap(E: ExpectedBuildNamespace.takeError())
313 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "BuildNamespace", ArgVals&: Index)
314 .build();
315 }
316
317 Namespaces.push_back(x: std::move(*ExpectedBuildNamespace));
318 }
319
320 return NestedBuildNamespace(std::move(Namespaces));
321}
322
323Array JSONFormat::nestedBuildNamespaceToJSON(
324 const NestedBuildNamespace &NBN) const {
325 Array Result;
326 const auto &Namespaces = getNamespaces(X: NBN);
327 Result.reserve(S: Namespaces.size());
328
329 for (const auto &BN : Namespaces) {
330 Result.push_back(E: buildNamespaceToJSON(BN));
331 }
332
333 return Result;
334}
335
336//----------------------------------------------------------------------------
337// EntityName
338//----------------------------------------------------------------------------
339
340llvm::Expected<EntityName>
341JSONFormat::entityNameFromJSON(const Object &EntityNameObject) const {
342 const auto OptUSR = EntityNameObject.getString(K: "usr");
343 if (!OptUSR) {
344 return ErrorBuilder::create(EC: std::errc::invalid_argument,
345 Fmt: ErrorMessages::FailedToReadObjectAtField, ArgVals: "USR",
346 ArgVals: "usr", ArgVals: "string")
347 .build();
348 }
349
350 const auto OptSuffix = EntityNameObject.getString(K: "suffix");
351 if (!OptSuffix) {
352 return ErrorBuilder::create(EC: std::errc::invalid_argument,
353 Fmt: ErrorMessages::FailedToReadObjectAtField,
354 ArgVals: "Suffix", ArgVals: "suffix", ArgVals: "string")
355 .build();
356 }
357
358 const Array *OptNamespaceArray = EntityNameObject.getArray(K: "namespace");
359 if (!OptNamespaceArray) {
360 return ErrorBuilder::create(EC: std::errc::invalid_argument,
361 Fmt: ErrorMessages::FailedToReadObjectAtField,
362 ArgVals: "NestedBuildNamespace", ArgVals: "namespace", ArgVals: "array")
363 .build();
364 }
365
366 auto ExpectedNamespace = nestedBuildNamespaceFromJSON(NestedBuildNamespaceArray: *OptNamespaceArray);
367 if (!ExpectedNamespace) {
368 return ErrorBuilder::wrap(E: ExpectedNamespace.takeError())
369 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "NestedBuildNamespace",
370 ArgVals: "namespace")
371 .build();
372 }
373
374 return EntityName{*OptUSR, *OptSuffix, std::move(*ExpectedNamespace)};
375}
376
377Object JSONFormat::entityNameToJSON(const EntityName &EN) const {
378 Object Result;
379 Result["usr"] = getUSR(X: EN);
380 Result["suffix"] = getSuffix(X: EN);
381 Result["namespace"] = nestedBuildNamespaceToJSON(NBN: getNamespace(X: EN));
382 return Result;
383}
384
385//----------------------------------------------------------------------------
386// EntityLinkageType
387//----------------------------------------------------------------------------
388
389namespace {
390
391std::optional<EntityLinkage::LinkageType>
392parseEntityLinkageType(llvm::StringRef S) {
393 if (S == "none")
394 return EntityLinkage::LinkageType::None;
395 if (S == "internal")
396 return EntityLinkage::LinkageType::Internal;
397 if (S == "external")
398 return EntityLinkage::LinkageType::External;
399 return std::nullopt;
400}
401
402llvm::StringRef entityLinkageTypeToJSON(EntityLinkage::LinkageType LT) {
403 switch (LT) {
404 case EntityLinkage::LinkageType::None:
405 return "none";
406 case EntityLinkage::LinkageType::Internal:
407 return "internal";
408 case EntityLinkage::LinkageType::External:
409 return "external";
410 }
411 llvm_unreachable("Unhandled EntityLinkage::LinkageType variant");
412}
413
414} // namespace
415
416//----------------------------------------------------------------------------
417// EntityLinkage
418//----------------------------------------------------------------------------
419
420llvm::Expected<EntityLinkage>
421JSONFormat::entityLinkageFromJSON(const Object &EntityLinkageObject) const {
422 auto OptLinkageStr = EntityLinkageObject.getString(K: "type");
423 if (!OptLinkageStr) {
424 return ErrorBuilder::create(EC: std::errc::invalid_argument,
425 Fmt: ErrorMessages::FailedToReadObjectAtField,
426 ArgVals: "EntityLinkageType", ArgVals: "type", ArgVals: "string")
427 .build();
428 }
429
430 auto OptLinkageType = parseEntityLinkageType(S: *OptLinkageStr);
431 if (!OptLinkageType) {
432 return ErrorBuilder::create(EC: std::errc::invalid_argument,
433 Fmt: ErrorMessages::InvalidEntityLinkageType,
434 ArgVals&: *OptLinkageStr)
435 .build();
436 }
437
438 return EntityLinkage(*OptLinkageType);
439}
440
441Object JSONFormat::entityLinkageToJSON(const EntityLinkage &EL) const {
442 Object Result;
443 Result["type"] = entityLinkageTypeToJSON(LT: getLinkage(X: EL));
444 return Result;
445}
446
447//----------------------------------------------------------------------------
448// EntityIdTableEntry
449//----------------------------------------------------------------------------
450
451llvm::Expected<std::pair<EntityName, EntityId>>
452JSONFormat::entityIdTableEntryFromJSON(
453 const Object &EntityIdTableEntryObject) const {
454
455 const Object *OptEntityNameObject =
456 EntityIdTableEntryObject.getObject(K: "name");
457 if (!OptEntityNameObject) {
458 return ErrorBuilder::create(EC: std::errc::invalid_argument,
459 Fmt: ErrorMessages::FailedToReadObjectAtField,
460 ArgVals: "EntityName", ArgVals: "name", ArgVals: "object")
461 .build();
462 }
463
464 auto ExpectedEntityName = entityNameFromJSON(EntityNameObject: *OptEntityNameObject);
465 if (!ExpectedEntityName) {
466 return ErrorBuilder::wrap(E: ExpectedEntityName.takeError())
467 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntityName", ArgVals: "name")
468 .build();
469 }
470
471 const Value *EntityIdIntValue = EntityIdTableEntryObject.get(K: "id");
472 if (!EntityIdIntValue) {
473 return ErrorBuilder::create(EC: std::errc::invalid_argument,
474 Fmt: ErrorMessages::FailedToReadObjectAtField,
475 ArgVals: "EntityId", ArgVals: "id",
476 ArgVals: "number (unsigned 64-bit integer)")
477 .build();
478 }
479
480 const std::optional<uint64_t> OptEntityIdInt =
481 EntityIdIntValue->getAsUINT64();
482 if (!OptEntityIdInt) {
483 return ErrorBuilder::create(EC: std::errc::invalid_argument,
484 Fmt: ErrorMessages::FailedToReadObjectAtField,
485 ArgVals: "EntityId", ArgVals: "id",
486 ArgVals: "number (unsigned 64-bit integer)")
487 .build();
488 }
489
490 EntityId EI = entityIdFromJSON(EntityIdIndex: *OptEntityIdInt);
491
492 return std::make_pair(x: std::move(*ExpectedEntityName), y: std::move(EI));
493}
494
495Object JSONFormat::entityIdTableEntryToJSON(const EntityName &EN,
496 EntityId EI) const {
497 Object Entry;
498 Entry["id"] = entityIdToJSON(EI);
499 Entry["name"] = entityNameToJSON(EN);
500 return Entry;
501}
502
503//----------------------------------------------------------------------------
504// EntityIdTable
505//----------------------------------------------------------------------------
506
507llvm::Expected<EntityIdTable>
508JSONFormat::entityIdTableFromJSON(const Array &EntityIdTableArray) const {
509 EntityIdTable IdTable;
510 std::map<EntityName, EntityId> &Entities = getEntities(X&: IdTable);
511
512 for (const auto &[Index, EntityIdTableEntryValue] :
513 llvm::enumerate(First: EntityIdTableArray)) {
514
515 const Object *OptEntityIdTableEntryObject =
516 EntityIdTableEntryValue.getAsObject();
517 if (!OptEntityIdTableEntryObject) {
518 return ErrorBuilder::create(EC: std::errc::invalid_argument,
519 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
520 ArgVals: "EntityIdTable entry", ArgVals&: Index, ArgVals: "object")
521 .build();
522 }
523
524 auto ExpectedEntityIdTableEntry =
525 entityIdTableEntryFromJSON(EntityIdTableEntryObject: *OptEntityIdTableEntryObject);
526 if (!ExpectedEntityIdTableEntry)
527 return ErrorBuilder::wrap(E: ExpectedEntityIdTableEntry.takeError())
528 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "EntityIdTable entry",
529 ArgVals&: Index)
530 .build();
531
532 auto [EntityIt, EntityInserted] =
533 Entities.emplace(args: std::move(*ExpectedEntityIdTableEntry));
534 if (!EntityInserted) {
535 return ErrorBuilder::create(EC: std::errc::invalid_argument,
536 Fmt: ErrorMessages::FailedInsertionOnDuplication,
537 ArgVals: "EntityIdTable entry", ArgVals&: Index, ArgVals: "EntityId",
538 ArgVals&: getIndex(X&: EntityIt->second))
539 .build();
540 }
541 }
542
543 return IdTable;
544}
545
546Array JSONFormat::entityIdTableToJSON(const EntityIdTable &IdTable) const {
547 Array EntityIdTableArray;
548 const auto &Entities = getEntities(X: IdTable);
549 EntityIdTableArray.reserve(S: Entities.size());
550
551 for (const auto &[EntityName, EntityId] : Entities) {
552 EntityIdTableArray.push_back(
553 E: entityIdTableEntryToJSON(EN: EntityName, EI: EntityId));
554 }
555
556 return EntityIdTableArray;
557}
558
559//----------------------------------------------------------------------------
560// LinkageTableEntry
561//----------------------------------------------------------------------------
562
563llvm::Expected<std::pair<EntityId, EntityLinkage>>
564JSONFormat::linkageTableEntryFromJSON(
565 const Object &LinkageTableEntryObject) const {
566 const Value *EntityIdIntValue = LinkageTableEntryObject.get(K: "id");
567 if (!EntityIdIntValue) {
568 return ErrorBuilder::create(EC: std::errc::invalid_argument,
569 Fmt: ErrorMessages::FailedToReadObjectAtField,
570 ArgVals: "EntityId", ArgVals: "id",
571 ArgVals: "number (unsigned 64-bit integer)")
572 .build();
573 }
574
575 const std::optional<uint64_t> OptEntityIdInt =
576 EntityIdIntValue->getAsUINT64();
577 if (!OptEntityIdInt) {
578 return ErrorBuilder::create(EC: std::errc::invalid_argument,
579 Fmt: ErrorMessages::FailedToReadObjectAtField,
580 ArgVals: "EntityId", ArgVals: "id",
581 ArgVals: "number (unsigned 64-bit integer)")
582 .build();
583 }
584
585 EntityId EI = entityIdFromJSON(EntityIdIndex: *OptEntityIdInt);
586
587 const Object *OptEntityLinkageObject =
588 LinkageTableEntryObject.getObject(K: "linkage");
589 if (!OptEntityLinkageObject) {
590 return ErrorBuilder::create(EC: std::errc::invalid_argument,
591 Fmt: ErrorMessages::FailedToReadObjectAtField,
592 ArgVals: "EntityLinkage", ArgVals: "linkage", ArgVals: "object")
593 .build();
594 }
595
596 auto ExpectedEntityLinkage = entityLinkageFromJSON(EntityLinkageObject: *OptEntityLinkageObject);
597 if (!ExpectedEntityLinkage) {
598 return ErrorBuilder::wrap(E: ExpectedEntityLinkage.takeError())
599 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntityLinkage", ArgVals: "linkage")
600 .build();
601 }
602
603 return std::make_pair(x: std::move(EI), y: std::move(*ExpectedEntityLinkage));
604}
605
606Object JSONFormat::linkageTableEntryToJSON(EntityId EI,
607 const EntityLinkage &EL) const {
608 Object Entry;
609 Entry["id"] = entityIdToJSON(EI);
610 Entry["linkage"] = entityLinkageToJSON(EL);
611 return Entry;
612}
613
614//----------------------------------------------------------------------------
615// LinkageTable
616//----------------------------------------------------------------------------
617
618// ExpectedIds is the set of EntityIds from the IdTable that must appear in the
619// linkage table—no more, no fewer. It is taken by value because it is consumed
620// during parsing: each successfully matched id is erased from the set, and any
621// ids remaining at the end are reported as missing.
622llvm::Expected<std::map<EntityId, EntityLinkage>>
623JSONFormat::linkageTableFromJSON(const Array &LinkageTableArray,
624 std::set<EntityId> ExpectedIds) const {
625 std::map<EntityId, EntityLinkage> LinkageTable;
626
627 for (const auto &[Index, LinkageTableEntryValue] :
628 llvm::enumerate(First: LinkageTableArray)) {
629 const Object *OptLinkageTableEntryObject =
630 LinkageTableEntryValue.getAsObject();
631 if (!OptLinkageTableEntryObject) {
632 return ErrorBuilder::create(EC: std::errc::invalid_argument,
633 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
634 ArgVals: "LinkageTable entry", ArgVals&: Index, ArgVals: "object")
635 .build();
636 }
637
638 auto ExpectedLinkageTableEntry =
639 linkageTableEntryFromJSON(LinkageTableEntryObject: *OptLinkageTableEntryObject);
640 if (!ExpectedLinkageTableEntry) {
641 return ErrorBuilder::wrap(E: ExpectedLinkageTableEntry.takeError())
642 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "LinkageTable entry", ArgVals&: Index)
643 .build();
644 }
645
646 const EntityId EI = ExpectedLinkageTableEntry->first;
647
648 auto [It, Inserted] =
649 LinkageTable.insert(x: std::move(*ExpectedLinkageTableEntry));
650 if (!Inserted) {
651 return ErrorBuilder::create(EC: std::errc::invalid_argument,
652 Fmt: ErrorMessages::FailedInsertionOnDuplication,
653 ArgVals: "LinkageTable entry", ArgVals&: Index, ArgVals: "EntityId",
654 ArgVals: getIndex(X: It->first))
655 .build();
656 }
657
658 if (ExpectedIds.erase(x: EI) == 0) {
659 return ErrorBuilder::create(
660 EC: std::errc::invalid_argument,
661 Fmt: ErrorMessages::FailedToDeserializeLinkageTableExtraId,
662 ArgVals: getIndex(X: EI))
663 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "LinkageTable entry", ArgVals&: Index)
664 .build();
665 }
666 }
667
668 if (!ExpectedIds.empty()) {
669 return ErrorBuilder::create(
670 EC: std::errc::invalid_argument,
671 Fmt: ErrorMessages::FailedToDeserializeLinkageTableMissingId,
672 ArgVals: getIndex(X: *ExpectedIds.begin()))
673 .build();
674 }
675
676 return LinkageTable;
677}
678
679Array JSONFormat::linkageTableToJSON(
680 const std::map<EntityId, EntityLinkage> &LinkageTable) const {
681 Array Result;
682 Result.reserve(S: LinkageTable.size());
683
684 for (const auto &[EI, EL] : LinkageTable) {
685 Result.push_back(E: linkageTableEntryToJSON(EI, EL));
686 }
687
688 return Result;
689}
690
691//----------------------------------------------------------------------------
692// EntitySummary
693//----------------------------------------------------------------------------
694
695llvm::Expected<std::unique_ptr<EntitySummary>>
696JSONFormat::entitySummaryFromJSON(const SummaryName &SN,
697 const Object &EntitySummaryObject,
698 EntityIdTable &IdTable) const {
699 auto InfoIt = FormatInfos.find(x: SN);
700 if (InfoIt == FormatInfos.end()) {
701 return ErrorBuilder::create(EC: std::errc::invalid_argument,
702 Fmt: ErrorMessages::FailedToDeserializeEntitySummary,
703 ArgVals: SN.str())
704 .build();
705 }
706
707 const auto &InfoEntry = InfoIt->second;
708 assert(InfoEntry.ForSummary == SN);
709
710 EntityIdConverter Converter(*this);
711 return InfoEntry.Deserialize(EntitySummaryObject, IdTable, Converter);
712}
713
714llvm::Expected<Object>
715JSONFormat::entitySummaryToJSON(const SummaryName &SN,
716 const EntitySummary &ES) const {
717 auto InfoIt = FormatInfos.find(x: SN);
718 if (InfoIt == FormatInfos.end()) {
719 return ErrorBuilder::create(EC: std::errc::invalid_argument,
720 Fmt: ErrorMessages::FailedToSerializeEntitySummary,
721 ArgVals: SN.str())
722 .build();
723 }
724
725 const auto &InfoEntry = InfoIt->second;
726 assert(InfoEntry.ForSummary == SN);
727
728 EntityIdConverter Converter(*this);
729 return InfoEntry.Serialize(ES, Converter);
730}
731
732//----------------------------------------------------------------------------
733// EntityDataMapEntry
734//----------------------------------------------------------------------------
735
736llvm::Expected<std::pair<EntityId, std::unique_ptr<EntitySummary>>>
737JSONFormat::entityDataMapEntryFromJSON(const Object &EntityDataMapEntryObject,
738 const SummaryName &SN,
739 EntityIdTable &IdTable) const {
740
741 const Value *EntityIdIntValue = EntityDataMapEntryObject.get(K: "entity_id");
742 if (!EntityIdIntValue) {
743 return ErrorBuilder::create(EC: std::errc::invalid_argument,
744 Fmt: ErrorMessages::FailedToReadObjectAtField,
745 ArgVals: "EntityId", ArgVals: "entity_id",
746 ArgVals: "number (unsigned 64-bit integer)")
747 .build();
748 }
749
750 const std::optional<uint64_t> OptEntityIdInt =
751 EntityIdIntValue->getAsUINT64();
752 if (!OptEntityIdInt) {
753 return ErrorBuilder::create(EC: std::errc::invalid_argument,
754 Fmt: ErrorMessages::FailedToReadObjectAtField,
755 ArgVals: "EntityId", ArgVals: "entity_id", ArgVals: "integer")
756 .build();
757 }
758
759 EntityId EI = entityIdFromJSON(EntityIdIndex: *OptEntityIdInt);
760
761 const Object *OptEntitySummaryObject =
762 EntityDataMapEntryObject.getObject(K: "entity_summary");
763 if (!OptEntitySummaryObject) {
764 return ErrorBuilder::create(EC: std::errc::invalid_argument,
765 Fmt: ErrorMessages::FailedToReadObjectAtField,
766 ArgVals: "EntitySummary", ArgVals: "entity_summary", ArgVals: "object")
767 .build();
768 }
769
770 auto ExpectedEntitySummary =
771 entitySummaryFromJSON(SN, EntitySummaryObject: *OptEntitySummaryObject, IdTable);
772 if (!ExpectedEntitySummary) {
773 return ErrorBuilder::wrap(E: ExpectedEntitySummary.takeError())
774 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntitySummary",
775 ArgVals: "entity_summary")
776 .build();
777 }
778
779 return std::make_pair(x: std::move(EI), y: std::move(*ExpectedEntitySummary));
780}
781
782//----------------------------------------------------------------------------
783// EntityDataMap
784//----------------------------------------------------------------------------
785
786llvm::Expected<std::map<EntityId, std::unique_ptr<EntitySummary>>>
787JSONFormat::entityDataMapFromJSON(const SummaryName &SN,
788 const Array &EntityDataArray,
789 EntityIdTable &IdTable) const {
790 std::map<EntityId, std::unique_ptr<EntitySummary>> EntityDataMap;
791
792 for (const auto &[Index, EntityDataMapEntryValue] :
793 llvm::enumerate(First: EntityDataArray)) {
794
795 const Object *OptEntityDataMapEntryObject =
796 EntityDataMapEntryValue.getAsObject();
797 if (!OptEntityDataMapEntryObject) {
798 return ErrorBuilder::create(EC: std::errc::invalid_argument,
799 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
800 ArgVals: "EntitySummary entry", ArgVals&: Index, ArgVals: "object")
801 .build();
802 }
803
804 auto ExpectedEntityDataMapEntry =
805 entityDataMapEntryFromJSON(EntityDataMapEntryObject: *OptEntityDataMapEntryObject, SN, IdTable);
806 if (!ExpectedEntityDataMapEntry)
807 return ErrorBuilder::wrap(E: ExpectedEntityDataMapEntry.takeError())
808 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "EntitySummary entry",
809 ArgVals&: Index)
810 .build();
811
812 auto [DataIt, DataInserted] =
813 EntityDataMap.insert(x: std::move(*ExpectedEntityDataMapEntry));
814 if (!DataInserted) {
815 return ErrorBuilder::create(EC: std::errc::invalid_argument,
816 Fmt: ErrorMessages::FailedInsertionOnDuplication,
817 ArgVals: "EntitySummary entry", ArgVals&: Index, ArgVals: "EntityId",
818 ArgVals: getIndex(X: DataIt->first))
819 .build();
820 }
821 }
822
823 return std::move(EntityDataMap);
824}
825
826llvm::Expected<Array> JSONFormat::entityDataMapToJSON(
827 const SummaryName &SN,
828 const std::map<EntityId, std::unique_ptr<EntitySummary>> &EntityDataMap)
829 const {
830 Array Result;
831 Result.reserve(S: EntityDataMap.size());
832
833 for (const auto &[Index, EntityDataMapEntry] :
834 llvm::enumerate(First: EntityDataMap)) {
835 const auto &[EntityId, EntitySummary] = EntityDataMapEntry;
836
837 Object Entry;
838
839 Entry["entity_id"] = entityIdToJSON(EI: EntityId);
840
841 auto ExpectedEntitySummaryObject = entitySummaryToJSON(SN, ES: *EntitySummary);
842 if (!ExpectedEntitySummaryObject) {
843 return ErrorBuilder::wrap(E: ExpectedEntitySummaryObject.takeError())
844 .context(Fmt: ErrorMessages::WritingToIndex, ArgVals: "EntitySummary entry", ArgVals&: Index)
845 .build();
846 }
847
848 Entry["entity_summary"] = std::move(*ExpectedEntitySummaryObject);
849
850 Result.push_back(E: std::move(Entry));
851 }
852
853 return Result;
854}
855
856//----------------------------------------------------------------------------
857// SummaryDataMapEntry
858//----------------------------------------------------------------------------
859
860llvm::Expected<
861 std::pair<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>>
862JSONFormat::summaryDataMapEntryFromJSON(const Object &SummaryDataMapEntryObject,
863 EntityIdTable &IdTable) const {
864
865 std::optional<llvm::StringRef> OptSummaryNameStr =
866 SummaryDataMapEntryObject.getString(K: "summary_name");
867 if (!OptSummaryNameStr) {
868 return ErrorBuilder::create(EC: std::errc::invalid_argument,
869 Fmt: ErrorMessages::FailedToReadObjectAtField,
870 ArgVals: "SummaryName", ArgVals: "summary_name", ArgVals: "string")
871 .build();
872 }
873
874 SummaryName SN = summaryNameFromJSON(SummaryNameStr: *OptSummaryNameStr);
875
876 const Array *OptEntityDataArray =
877 SummaryDataMapEntryObject.getArray(K: "summary_data");
878 if (!OptEntityDataArray) {
879 return ErrorBuilder::create(EC: std::errc::invalid_argument,
880 Fmt: ErrorMessages::FailedToReadObjectAtField,
881 ArgVals: "EntitySummary entries", ArgVals: "summary_data",
882 ArgVals: "array")
883 .build();
884 }
885
886 auto ExpectedEntityDataMap =
887 entityDataMapFromJSON(SN, EntityDataArray: *OptEntityDataArray, IdTable);
888 if (!ExpectedEntityDataMap)
889 return ErrorBuilder::wrap(E: ExpectedEntityDataMap.takeError())
890 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "EntitySummary entries",
891 ArgVals: "summary_data")
892 .build();
893
894 return std::make_pair(x: std::move(SN), y: std::move(*ExpectedEntityDataMap));
895}
896
897llvm::Expected<Object> JSONFormat::summaryDataMapEntryToJSON(
898 const SummaryName &SN,
899 const std::map<EntityId, std::unique_ptr<EntitySummary>> &SD) const {
900 Object Result;
901
902 Result["summary_name"] = summaryNameToJSON(SN);
903
904 auto ExpectedSummaryDataArray = entityDataMapToJSON(SN, EntityDataMap: SD);
905 if (!ExpectedSummaryDataArray) {
906 return ErrorBuilder::wrap(E: ExpectedSummaryDataArray.takeError())
907 .context(Fmt: ErrorMessages::WritingToField, ArgVals: "EntitySummary entries",
908 ArgVals: "summary_data")
909 .build();
910 }
911
912 Result["summary_data"] = std::move(*ExpectedSummaryDataArray);
913
914 return Result;
915}
916
917//----------------------------------------------------------------------------
918// SummaryDataMap
919//----------------------------------------------------------------------------
920
921llvm::Expected<
922 std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>>
923JSONFormat::summaryDataMapFromJSON(const Array &SummaryDataArray,
924 EntityIdTable &IdTable) const {
925 std::map<SummaryName, std::map<EntityId, std::unique_ptr<EntitySummary>>>
926 SummaryDataMap;
927
928 for (const auto &[Index, SummaryDataMapEntryValue] :
929 llvm::enumerate(First: SummaryDataArray)) {
930
931 const Object *OptSummaryDataMapEntryObject =
932 SummaryDataMapEntryValue.getAsObject();
933 if (!OptSummaryDataMapEntryObject) {
934 return ErrorBuilder::create(EC: std::errc::invalid_argument,
935 Fmt: ErrorMessages::FailedToReadObjectAtIndex,
936 ArgVals: "SummaryData entry", ArgVals&: Index, ArgVals: "object")
937 .build();
938 }
939
940 auto ExpectedSummaryDataMapEntry =
941 summaryDataMapEntryFromJSON(SummaryDataMapEntryObject: *OptSummaryDataMapEntryObject, IdTable);
942 if (!ExpectedSummaryDataMapEntry) {
943 return ErrorBuilder::wrap(E: ExpectedSummaryDataMapEntry.takeError())
944 .context(Fmt: ErrorMessages::ReadingFromIndex, ArgVals: "SummaryData entry", ArgVals&: Index)
945 .build();
946 }
947
948 auto [SummaryIt, SummaryInserted] =
949 SummaryDataMap.emplace(args: std::move(*ExpectedSummaryDataMapEntry));
950 if (!SummaryInserted) {
951 return ErrorBuilder::create(EC: std::errc::invalid_argument,
952 Fmt: ErrorMessages::FailedInsertionOnDuplication,
953 ArgVals: "SummaryData entry", ArgVals&: Index, ArgVals: "SummaryName",
954 ArgVals: SummaryIt->first.str())
955 .build();
956 }
957 }
958
959 return std::move(SummaryDataMap);
960}
961
962llvm::Expected<Array> JSONFormat::summaryDataMapToJSON(
963 const std::map<SummaryName,
964 std::map<EntityId, std::unique_ptr<EntitySummary>>>
965 &SummaryDataMap) const {
966 Array Result;
967 Result.reserve(S: SummaryDataMap.size());
968
969 for (const auto &[Index, SummaryDataMapEntry] :
970 llvm::enumerate(First: SummaryDataMap)) {
971 const auto &[SummaryName, DataMap] = SummaryDataMapEntry;
972
973 auto ExpectedSummaryDataMapObject =
974 summaryDataMapEntryToJSON(SN: SummaryName, SD: DataMap);
975 if (!ExpectedSummaryDataMapObject) {
976 return ErrorBuilder::wrap(E: ExpectedSummaryDataMapObject.takeError())
977 .context(Fmt: ErrorMessages::WritingToIndex, ArgVals: "SummaryData entry", ArgVals&: Index)
978 .build();
979 }
980
981 Result.push_back(E: std::move(*ExpectedSummaryDataMapObject));
982 }
983
984 return std::move(Result);
985}
986
987//----------------------------------------------------------------------------
988// TUSummary
989//----------------------------------------------------------------------------
990
991llvm::Expected<TUSummary> JSONFormat::readTUSummary(llvm::StringRef Path) {
992 auto ExpectedJSON = readJSON(Path);
993 if (!ExpectedJSON) {
994 return ErrorBuilder::wrap(E: ExpectedJSON.takeError())
995 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
996 .build();
997 }
998
999 Object *RootObjectPtr = ExpectedJSON->getAsObject();
1000 if (!RootObjectPtr) {
1001 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1002 Fmt: ErrorMessages::FailedToReadObject, ArgVals: "TUSummary",
1003 ArgVals: "object")
1004 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
1005 .build();
1006 }
1007
1008 const Object &RootObject = *RootObjectPtr;
1009
1010 const Object *TUNamespaceObject = RootObject.getObject(K: "tu_namespace");
1011 if (!TUNamespaceObject) {
1012 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1013 Fmt: ErrorMessages::FailedToReadObjectAtField,
1014 ArgVals: "BuildNamespace", ArgVals: "tu_namespace", ArgVals: "object")
1015 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
1016 .build();
1017 }
1018
1019 auto ExpectedTUNamespace = buildNamespaceFromJSON(BuildNamespaceObject: *TUNamespaceObject);
1020 if (!ExpectedTUNamespace) {
1021 return ErrorBuilder::wrap(E: ExpectedTUNamespace.takeError())
1022 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "BuildNamespace",
1023 ArgVals: "tu_namespace")
1024 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
1025 .build();
1026 }
1027
1028 TUSummary Summary(std::move(*ExpectedTUNamespace));
1029
1030 {
1031 const Array *IdTableArray = RootObject.getArray(K: "id_table");
1032 if (!IdTableArray) {
1033 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1034 Fmt: ErrorMessages::FailedToReadObjectAtField,
1035 ArgVals: "IdTable", ArgVals: "id_table", ArgVals: "array")
1036 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
1037 .build();
1038 }
1039
1040 auto ExpectedIdTable = entityIdTableFromJSON(EntityIdTableArray: *IdTableArray);
1041 if (!ExpectedIdTable) {
1042 return ErrorBuilder::wrap(E: ExpectedIdTable.takeError())
1043 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "IdTable", ArgVals: "id_table")
1044 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
1045 .build();
1046 }
1047
1048 getIdTable(X&: Summary) = std::move(*ExpectedIdTable);
1049 }
1050
1051 {
1052 const Array *LinkageTableArray = RootObject.getArray(K: "linkage_table");
1053 if (!LinkageTableArray) {
1054 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1055 Fmt: ErrorMessages::FailedToReadObjectAtField,
1056 ArgVals: "LinkageTable", ArgVals: "linkage_table", ArgVals: "array")
1057 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
1058 .build();
1059 }
1060
1061 auto ExpectedIdRange =
1062 llvm::make_second_range(c&: getEntities(X&: getIdTable(X&: Summary)));
1063 std::set<EntityId> ExpectedIds(ExpectedIdRange.begin(),
1064 ExpectedIdRange.end());
1065
1066 // Move ExpectedIds in since linkageTableFromJSON consumes it to verify
1067 // that the linkage table contains exactly the ids present in the IdTable.
1068 auto ExpectedLinkageTable =
1069 linkageTableFromJSON(LinkageTableArray: *LinkageTableArray, ExpectedIds: std::move(ExpectedIds));
1070 if (!ExpectedLinkageTable) {
1071 return ErrorBuilder::wrap(E: ExpectedLinkageTable.takeError())
1072 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "LinkageTable",
1073 ArgVals: "linkage_table")
1074 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
1075 .build();
1076 }
1077
1078 getLinkageTable(X&: Summary) = std::move(*ExpectedLinkageTable);
1079 }
1080
1081 {
1082 const Array *SummaryDataArray = RootObject.getArray(K: "data");
1083 if (!SummaryDataArray) {
1084 return ErrorBuilder::create(EC: std::errc::invalid_argument,
1085 Fmt: ErrorMessages::FailedToReadObjectAtField,
1086 ArgVals: "SummaryData entries", ArgVals: "data", ArgVals: "array")
1087 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
1088 .build();
1089 }
1090
1091 auto ExpectedSummaryDataMap =
1092 summaryDataMapFromJSON(SummaryDataArray: *SummaryDataArray, IdTable&: getIdTable(X&: Summary));
1093 if (!ExpectedSummaryDataMap) {
1094 return ErrorBuilder::wrap(E: ExpectedSummaryDataMap.takeError())
1095 .context(Fmt: ErrorMessages::ReadingFromField, ArgVals: "SummaryData entries",
1096 ArgVals: "data")
1097 .context(Fmt: ErrorMessages::ReadingFromFile, ArgVals: "TUSummary", ArgVals&: Path)
1098 .build();
1099 }
1100
1101 getData(X&: Summary) = std::move(*ExpectedSummaryDataMap);
1102 }
1103
1104 return std::move(Summary);
1105}
1106
1107llvm::Error JSONFormat::writeTUSummary(const TUSummary &S,
1108 llvm::StringRef Path) {
1109 Object RootObject;
1110
1111 RootObject["tu_namespace"] = buildNamespaceToJSON(BN: getTUNamespace(X: S));
1112
1113 RootObject["id_table"] = entityIdTableToJSON(IdTable: getIdTable(X: S));
1114
1115 RootObject["linkage_table"] = linkageTableToJSON(LinkageTable: getLinkageTable(X: S));
1116
1117 auto ExpectedDataObject = summaryDataMapToJSON(SummaryDataMap: getData(X: S));
1118 if (!ExpectedDataObject) {
1119 return ErrorBuilder::wrap(E: ExpectedDataObject.takeError())
1120 .context(Fmt: ErrorMessages::WritingToFile, ArgVals: "TUSummary", ArgVals&: Path)
1121 .build();
1122 }
1123
1124 RootObject["data"] = std::move(*ExpectedDataObject);
1125
1126 if (auto Error = writeJSON(Value: std::move(RootObject), Path)) {
1127 return ErrorBuilder::wrap(E: std::move(Error))
1128 .context(Fmt: ErrorMessages::WritingToFile, ArgVals: "TUSummary", ArgVals&: Path)
1129 .build();
1130 }
1131
1132 return llvm::Error::success();
1133}
1134