clang 23.0.0git
PairsAnalysis.cpp
Go to the documentation of this file.
1//===- PairsAnalysis.cpp - Pairs analysis for ExamplePlugin ---------------===//
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 "AnalysisResults.h"
15#include "llvm/Support/Error.h"
16#include "llvm/Support/JSON.h"
17#include "llvm/Support/Registry.h"
18#include <memory>
19#include <utility>
20#include <vector>
21
22using namespace clang::ssaf;
23using namespace llvm;
25
26namespace {
27
28//===----------------------------------------------------------------------===//
29// PairsEntitySummary
30//
31// Per-entity data: a list of (EntityId, EntityId) pairs. Stored in the LU
32// data section under summary_name "PairsEntitySummary". Serialized as:
33// { "pairs": [{"first": {...}, "second": {...}}, ...] }
34//===----------------------------------------------------------------------===//
35
36struct PairsEntitySummary final : EntitySummary {
37 static SummaryName summaryName() { return SummaryName("PairsEntitySummary"); }
38
39 SummaryName getSummaryName() const override {
40 return SummaryName("PairsEntitySummary");
41 }
42
43 std::vector<std::pair<EntityId, EntityId>> Pairs;
44};
45
46json::Object serializePairsEntitySummary(const EntitySummary &ES,
48 const auto &S = static_cast<const PairsEntitySummary &>(ES);
49 json::Array PairsArray;
50 for (const auto &[First, Second] : S.Pairs) {
51 PairsArray.push_back(json::Object{
52 {"first", ToJSON(First)},
53 {"second", ToJSON(Second)},
54 });
55 }
56 return json::Object{{"pairs", std::move(PairsArray)}};
57}
58
60deserializePairsEntitySummary(const json::Object &Obj, EntityIdTable &,
62 auto Result = std::make_unique<PairsEntitySummary>();
63 const json::Array *PairsArray = Obj.getArray("pairs");
64 if (!PairsArray) {
65 return createStringError(inconvertibleErrorCode(),
66 "missing or invalid field 'pairs'");
67 }
68 for (const auto &[Index, Value] : llvm::enumerate(*PairsArray)) {
69 const json::Object *Pair = Value.getAsObject();
70 if (!Pair) {
71 return createStringError(
72 inconvertibleErrorCode(),
73 "pairs element at index %zu is not a JSON object", Index);
74 }
75 const json::Object *FirstObj = Pair->getObject("first");
76 if (!FirstObj) {
77 return createStringError(
78 inconvertibleErrorCode(),
79 "missing or invalid 'first' field at index '%zu'", Index);
80 }
81 const json::Object *SecondObj = Pair->getObject("second");
82 if (!SecondObj) {
83 return createStringError(
84 inconvertibleErrorCode(),
85 "missing or invalid 'second' field at index '%zu'", Index);
86 }
87 auto ExpectedFirst = FromJSON(*FirstObj);
88 if (!ExpectedFirst) {
89 return createStringError(inconvertibleErrorCode(),
90 "invalid 'first' entity id at index '%zu': %s",
91 Index,
92 toString(ExpectedFirst.takeError()).c_str());
93 }
94 auto ExpectedSecond = FromJSON(*SecondObj);
95 if (!ExpectedSecond) {
96 return createStringError(inconvertibleErrorCode(),
97 "invalid 'second' entity id at index '%zu': %s",
98 Index,
99 toString(ExpectedSecond.takeError()).c_str());
100 }
101 Result->Pairs.emplace_back(*ExpectedFirst, *ExpectedSecond);
102 }
103 return std::move(Result);
104}
105
106struct PairsEntitySummaryFormatInfo final : JSONFormat::FormatInfo {
107 PairsEntitySummaryFormatInfo()
108 : JSONFormat::FormatInfo(SummaryName("PairsEntitySummary"),
109 serializePairsEntitySummary,
110 deserializePairsEntitySummary) {}
111};
112
113llvm::Registry<JSONFormat::FormatInfo>::Add<PairsEntitySummaryFormatInfo>
114 RegisterPairsEntitySummaryForJSON(
115 "PairsEntitySummary", "JSON format info for PairsEntitySummary");
116
117//===----------------------------------------------------------------------===//
118// PairsAnalysisResult serialization
119//
120// Per-entity pair count. Serialized as:
121// { "pair_counts": [{"entity_id": {...}, "count": N}, ...] }
122//===----------------------------------------------------------------------===//
123
124json::Object serializePairsAnalysisResult(const PairsAnalysisResult &R,
126 json::Array Arr;
127 for (const auto &[EI, Count] : R.PairCounts) {
128 Arr.push_back(json::Object{{"entity_id", ToJSON(EI)}, {"count", Count}});
129 }
130 return json::Object{{"pair_counts", std::move(Arr)}};
131}
132
134deserializePairsAnalysisResult(const json::Object &Obj,
136 const json::Array *Arr = Obj.getArray("pair_counts");
137 if (!Arr) {
138 return createStringError(inconvertibleErrorCode(),
139 "missing or invalid field 'pair_counts'");
140 }
141
142 auto R = std::make_unique<PairsAnalysisResult>();
143 for (const auto &[Index, Val] : llvm::enumerate(*Arr)) {
144 const json::Object *Entry = Val.getAsObject();
145 if (!Entry) {
146 return createStringError(
147 inconvertibleErrorCode(),
148 "pair_counts element at index %zu is not an object", Index);
149 }
150 const json::Object *EIObj = Entry->getObject("entity_id");
151 if (!EIObj) {
152 return createStringError(
153 inconvertibleErrorCode(),
154 "missing or invalid 'entity_id' field at index %zu", Index);
155 }
156 auto ExpectedEI = FromJSON(*EIObj);
157 if (!ExpectedEI) {
158 return ExpectedEI.takeError();
159 }
160
161 auto CountVal = Entry->getInteger("count");
162 if (!CountVal) {
163 return createStringError(inconvertibleErrorCode(),
164 "missing or invalid 'count' field at index %zu",
165 Index);
166 }
167 R->PairCounts.emplace_back(*ExpectedEI, static_cast<int>(*CountVal));
168 }
169 return std::move(R);
170}
171
172JSONFormat::AnalysisResultRegistry::Add<PairsAnalysisResult>
173 RegisterPairsResultForJSON(serializePairsAnalysisResult,
174 deserializePairsAnalysisResult);
175
176//===----------------------------------------------------------------------===//
177// PairsAnalysis
178//
179// SummaryAnalysis that reads per-entity PairsEntitySummary data and counts
180// the number of pairs per entity, producing (EntityId, count) pairs.
181//===----------------------------------------------------------------------===//
182
183class PairsAnalysis final
184 : public SummaryAnalysis<PairsAnalysisResult, PairsEntitySummary> {
185public:
186 using ResultType = PairsAnalysisResult;
187
188 llvm::Error add(EntityId Id, const PairsEntitySummary &S) override {
189 result().PairCounts.emplace_back(Id, static_cast<int>(S.Pairs.size()));
190 return llvm::Error::success();
191 }
192};
193
195 RegisterPairsAnalysis("Counts pairs per entity");
196
197} // namespace
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
Manages entity name interning and provides efficient EntityId handles.
Base class for analysis-specific summary data.
llvm::function_ref< llvm::Expected< EntityId >(const Object &)> EntityIdFromJSONFn
Definition JSONFormat.h:71
FormatInfoEntry< SerializerFn, DeserializerFn > FormatInfo
Definition JSONFormat.h:80
llvm::function_ref< Object(EntityId)> EntityIdToJSONFn
Definition JSONFormat.h:70
Typed intermediate that concrete summary analyses inherit from.
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
Registers AnalysisT with the unified registry.