clang 23.0.0git
TagsAnalysis.cpp
Go to the documentation of this file.
1//===- TagsAnalysis.cpp - Tags 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 <algorithm>
19#include <memory>
20#include <string>
21#include <vector>
22
23using namespace clang::ssaf;
24using namespace llvm;
26
27namespace {
28
29//===----------------------------------------------------------------------===//
30// TagsEntitySummary
31//
32// Per-entity data: a list of string tags. Stored in the LU data section
33// under summary_name "TagsEntitySummary". Serialized as:
34// { "tags": ["tag1", "tag2", ...] }
35//===----------------------------------------------------------------------===//
36
37struct TagsEntitySummary final : EntitySummary {
38 static SummaryName summaryName() { return SummaryName("TagsEntitySummary"); }
39
40 SummaryName getSummaryName() const override {
41 return SummaryName("TagsEntitySummary");
42 }
43
44 std::vector<std::string> Tags;
45};
46
47json::Object serializeTagsEntitySummary(const EntitySummary &ES,
49 const auto &S = static_cast<const TagsEntitySummary &>(ES);
50 json::Array TagsArray;
51 TagsArray.reserve(S.Tags.size());
52 llvm::append_range(TagsArray, S.Tags);
53 return json::Object{{"tags", std::move(TagsArray)}};
54}
55
57deserializeTagsEntitySummary(const json::Object &Obj, EntityIdTable &,
59 const json::Array *TagsArray = Obj.getArray("tags");
60 if (!TagsArray) {
61 return createStringError(inconvertibleErrorCode(),
62 "missing or invalid field 'tags'");
63 }
64
65 auto S = std::make_unique<TagsEntitySummary>();
66 for (const auto &[Index, Val] : llvm::enumerate(*TagsArray)) {
67 auto Str = Val.getAsString();
68 if (!Str) {
69 return createStringError(inconvertibleErrorCode(),
70 "tags element at index %zu is not a string",
71 Index);
72 }
73 S->Tags.push_back(Str->str());
74 }
75 return std::move(S);
76}
77
78struct TagsEntitySummaryFormatInfo final : JSONFormat::FormatInfo {
79 TagsEntitySummaryFormatInfo()
80 : JSONFormat::FormatInfo(SummaryName("TagsEntitySummary"),
81 serializeTagsEntitySummary,
82 deserializeTagsEntitySummary) {}
83};
84
85llvm::Registry<JSONFormat::FormatInfo>::Add<TagsEntitySummaryFormatInfo>
86 RegisterTagsEntitySummaryForJSON("TagsEntitySummary",
87 "JSON format info for TagsEntitySummary");
88
89//===----------------------------------------------------------------------===//
90// TagsAnalysisResult serialization
91//
92// Sorted, deduplicated list of all tags seen across entities. Serialized as:
93// { "tags": ["tag1", "tag2", ...] }
94//===----------------------------------------------------------------------===//
95
96json::Object serializeTagsAnalysisResult(const TagsAnalysisResult &R,
98 json::Array TagsArray;
99 TagsArray.reserve(R.Tags.size());
100 llvm::append_range(TagsArray, R.Tags);
101 return json::Object{{"tags", std::move(TagsArray)}};
102}
103
105deserializeTagsAnalysisResult(const json::Object &Obj,
107 const json::Array *TagsArray = Obj.getArray("tags");
108 if (!TagsArray) {
109 return createStringError(inconvertibleErrorCode(),
110 "missing or invalid field 'tags'");
111 }
112
113 auto R = std::make_unique<TagsAnalysisResult>();
114 for (const auto &[Index, Val] : llvm::enumerate(*TagsArray)) {
115 auto S = Val.getAsString();
116 if (!S) {
117 return createStringError(inconvertibleErrorCode(),
118 "tags element at index %zu is not a string",
119 Index);
120 }
121 R->Tags.push_back(S->str());
122 }
123 return std::move(R);
124}
125
126JSONFormat::AnalysisResultRegistry::Add<TagsAnalysisResult>
127 RegisterTagsResultForJSON(serializeTagsAnalysisResult,
128 deserializeTagsAnalysisResult);
129
130//===----------------------------------------------------------------------===//
131// TagsAnalysis
132//
133// SummaryAnalysis that reads per-entity TagsEntitySummary data and collects
134// all unique tags into a sorted, deduplicated flat list.
135//===----------------------------------------------------------------------===//
136
137class TagsAnalysis final
138 : public SummaryAnalysis<TagsAnalysisResult, TagsEntitySummary> {
139public:
140 using ResultType = TagsAnalysisResult;
141
142 llvm::Error add(EntityId, const TagsEntitySummary &S) override {
143 for (const auto &Tag : S.Tags) {
144 result().Tags.push_back(Tag);
145 }
146 return llvm::Error::success();
147 }
148
149 llvm::Error finalize() override {
150 auto &Tags = result().Tags;
151 std::sort(Tags.begin(), Tags.end());
152 Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end());
153 return llvm::Error::success();
154 }
155};
156
158 RegisterTagsAnalysis("Collects unique tags across entities");
159
160} // namespace
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.
void finalize(TemplateInstantiationCallbackPtrs &Callbacks, const Sema &TheSema)
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
Registers AnalysisT with the unified registry.