1//===- LUSummaryConsumer.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 "clang/ScalableStaticAnalysisFramework/Core/SummaryData/LUSummaryConsumer.h"
10#include "clang/ScalableStaticAnalysisFramework/Core/SummaryData/SummaryDataBuilderRegistry.h"
11#include "clang/ScalableStaticAnalysisFramework/Core/Support/ErrorBuilder.h"
12
13using namespace clang;
14using namespace ssaf;
15
16llvm::Expected<std::unique_ptr<SummaryData>>
17LUSummaryConsumer::build(LUDataIterator LUIt) {
18 const SummaryName SN = LUIt->first;
19 auto Builder = SummaryDataBuilderRegistry::instantiate(Name: SN.str());
20 if (!Builder) {
21 return ErrorBuilder::create(EC: std::errc::invalid_argument,
22 Fmt: "no builder registered for analysis '{0}'",
23 ArgVals: SN.str())
24 .build();
25 }
26
27 for (auto &[Id, Summary] : LUIt->second) {
28 Builder->addSummary(Id, Summary: std::move(Summary));
29 }
30 Builder->finalize();
31 LU->Data.erase(position: LUIt);
32
33 return std::move(*Builder).getData();
34}
35
36llvm::Expected<std::unique_ptr<SummaryData>>
37LUSummaryConsumer::build(const SummaryName &SN) {
38 auto LUIt = LU->Data.find(x: SN);
39 if (LUIt == LU->Data.end()) {
40 return ErrorBuilder::create(EC: std::errc::invalid_argument,
41 Fmt: "no data for analysis '{0}' in LUSummary",
42 ArgVals: SN.str())
43 .build();
44 }
45 return build(LUIt);
46}
47
48llvm::Expected<SummaryDataStore>
49LUSummaryConsumer::run(llvm::ArrayRef<SummaryName> Names) {
50 SummaryDataStore Store;
51 for (const auto &SN : Names) {
52 auto Result = build(SN);
53 if (!Result) {
54 return Result.takeError();
55 }
56 Store.Data.emplace(args: SN, args: std::move(*Result));
57 }
58 return std::move(Store);
59}
60
61SummaryDataStore LUSummaryConsumer::run() && {
62 SummaryDataStore Store;
63 // Advance the iterator before calling build(): build() erases the current
64 // element on success, but std::map only invalidates iterators to the erased
65 // element, so the pre-advanced iterator remains valid in all cases.
66 auto It = LU->Data.begin();
67 while (It != LU->Data.end()) {
68 auto Current = It++; // Read the comment above!
69 SummaryName SN = Current->first; // copy before build() potentially erases
70 auto Result = build(LUIt: Current);
71 if (!Result) {
72 llvm::consumeError(Err: Result.takeError());
73 continue;
74 }
75 Store.Data.emplace(args: std::move(SN), args: std::move(*Result));
76 }
77 return Store;
78}
79