clang 23.0.0git
TUSummaryExtractorFrontendAction.cpp
Go to the documentation of this file.
1//===- TUSummaryExtractorFrontendAction.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
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/Support/Path.h"
21#include <memory>
22#include <string>
23#include <vector>
24
25using namespace clang;
26using namespace ssaf;
27
28static std::optional<std::pair<llvm::StringRef, llvm::StringRef>>
30 StringRef SSAFTUSummaryFile) {
31
32 StringRef Ext = llvm::sys::path::extension(SSAFTUSummaryFile);
33 StringRef FilePath = SSAFTUSummaryFile.drop_back(Ext.size());
34
35 if (!Ext.consume_front(".") || FilePath.empty()) {
36 Diags.Report(diag::warn_ssaf_extract_tu_summary_file_unknown_format)
37 << SSAFTUSummaryFile;
38 return std::nullopt;
39 }
40
41 if (!isFormatRegistered(Ext)) {
42 Diags.Report(diag::warn_ssaf_extract_tu_summary_file_unknown_output_format)
43 << Ext << SSAFTUSummaryFile;
44 return std::nullopt;
45 }
46
47 return std::pair{Ext, FilePath};
48}
49
50/// Return \c true if reported unrecognized extractors.
51static bool
53 ArrayRef<std::string> SSAFExtractSummaries) {
54 if (SSAFExtractSummaries.empty()) {
55 Diags.Report(diag::warn_ssaf_must_enable_summary_extractors);
56 return true;
57 }
58
59 std::vector<StringRef> UnrecognizedExtractorNames;
60 for (StringRef Name : SSAFExtractSummaries)
62 UnrecognizedExtractorNames.push_back(Name);
63
64 if (!UnrecognizedExtractorNames.empty()) {
65 Diags.Report(diag::warn_ssaf_extract_summary_unknown_extractor_name)
66 << UnrecognizedExtractorNames.size()
67 << llvm::join(UnrecognizedExtractorNames, ", ");
68 return true;
69 }
70
71 return false;
72}
73
74static std::vector<std::unique_ptr<ASTConsumer>>
76 ArrayRef<std::string> SSAFExtractSummaries) {
77 std::vector<std::unique_ptr<ASTConsumer>> Extractors;
78 Extractors.reserve(SSAFExtractSummaries.size());
79 for (StringRef Name : SSAFExtractSummaries) {
81 Extractors.push_back(makeTUSummaryExtractor(Name, Builder));
82 }
83 return Extractors;
84}
85
86namespace {
87
88/// Drives all extractor \c ASTConsumers and serializes the completed
89/// \c TUSummary.
90///
91/// Derives from \c MultiplexConsumer so every \c ASTConsumer virtual method is
92/// automatically forwarded to each extractor.
93class TUSummaryRunner final : public MultiplexConsumer {
94public:
95 static std::unique_ptr<TUSummaryRunner> create(CompilerInstance &CI,
96 StringRef InFile);
97
98private:
99 TUSummaryRunner(StringRef InFile, std::unique_ptr<SerializationFormat> Format,
100 const FrontendOptions &Opts);
101
102 void HandleTranslationUnit(ASTContext &Ctx) override;
103
104 TUSummary Summary;
105 TUSummaryBuilder Builder = TUSummaryBuilder(Summary);
106 std::unique_ptr<SerializationFormat> Format;
107 const FrontendOptions &Opts;
108};
109} // namespace
110
111std::unique_ptr<TUSummaryRunner> TUSummaryRunner::create(CompilerInstance &CI,
112 StringRef InFile) {
113 const FrontendOptions &Opts = CI.getFrontendOpts();
114 DiagnosticsEngine &Diags = CI.getDiagnostics();
115
116 auto MaybePair =
118 if (!MaybePair.has_value())
119 return nullptr;
120 auto [FormatName, OutputPath] = MaybePair.value();
121
123 return nullptr;
124
125 return std::unique_ptr<TUSummaryRunner>{
126 new TUSummaryRunner{InFile, makeFormat(FormatName), Opts}};
127}
128
129TUSummaryRunner::TUSummaryRunner(StringRef InFile,
130 std::unique_ptr<SerializationFormat> Format,
131 const FrontendOptions &Opts)
132 : MultiplexConsumer(std::vector<std::unique_ptr<ASTConsumer>>{}),
133 Summary(BuildNamespace(BuildNamespaceKind::CompilationUnit, InFile)),
134 Format(std::move(Format)), Opts(Opts) {
135 assert(this->Format);
136
137 // Now the Summary and the builders are constructed, we can also construct the
138 // extractors.
139 auto Extractors = makeTUSummaryExtractors(Builder, Opts.SSAFExtractSummaries);
140 assert(!Extractors.empty());
141
142 // We must initialize the Consumers here because our extractors need a
143 // Builder that holds a reference to the TUSummary, which would be only
144 // initialized after the MultiplexConsumer ctor. This is the only way we can
145 // avoid the use of the TUSummary before it starts its lifetime.
146 MultiplexConsumer::Consumers = std::move(Extractors);
147}
148
149void TUSummaryRunner::HandleTranslationUnit(ASTContext &Ctx) {
150 // First, invoke the Summary Extractors.
152
153 // Then serialize the result.
154 if (auto Err = Format->writeTUSummary(Summary, Opts.SSAFTUSummaryFile)) {
155 Ctx.getDiagnostics().Report(diag::warn_ssaf_write_tu_summary_failed)
156 << Opts.SSAFTUSummaryFile << llvm::toString(std::move(Err));
157 }
158}
159
161
165
166std::unique_ptr<ASTConsumer>
168 StringRef InFile) {
169 auto WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
170 if (!WrappedConsumer)
171 return nullptr;
172
173 if (auto Runner = TUSummaryRunner::create(CI, InFile)) {
174 std::vector<std::unique_ptr<ASTConsumer>> Consumers;
175 Consumers.reserve(2);
176 Consumers.push_back(std::move(WrappedConsumer));
177 Consumers.push_back(std::move(Runner));
178 return std::make_unique<MultiplexConsumer>(std::move(Consumers));
179 }
180 return WrappedConsumer;
181}
static bool reportUnrecognizedExtractorNames(DiagnosticsEngine &Diags, ArrayRef< std::string > SSAFExtractSummaries)
Return true if reported unrecognized extractors.
static std::optional< std::pair< llvm::StringRef, llvm::StringRef > > parseOutputFileFormatAndPathOrReportError(DiagnosticsEngine &Diags, StringRef SSAFTUSummaryFile)
static std::vector< std::unique_ptr< ASTConsumer > > makeTUSummaryExtractors(TUSummaryBuilder &Builder, ArrayRef< std::string > SSAFExtractSummaries)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:226
DiagnosticsEngine & getDiagnostics() const
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
FrontendOptions & getFrontendOpts()
Concrete class used by the front-end to report problems and issues.
Definition Diagnostic.h:232
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
std::string SSAFTUSummaryFile
The TU summary output file with the file extension representing the file format.
std::vector< std::string > SSAFExtractSummaries
List of SSAF extractors to enable.
void HandleTranslationUnit(ASTContext &Ctx) override
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
std::vector< std::unique_ptr< ASTConsumer > > Consumers
WrapperFrontendAction(std::unique_ptr< FrontendAction > WrappedAction)
Construct a WrapperFrontendAction from an existing action, taking ownership of it.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
std::unique_ptr< FrontendAction > WrappedAction
Represents a single namespace in the build process.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
TUSummaryExtractorFrontendAction(std::unique_ptr< FrontendAction > WrappedAction)
std::unique_ptr< DiagnosticConsumer > create(StringRef OutputFile, DiagnosticOptions &DiagOpts, bool MergeChildRecords=false)
Returns a DiagnosticConsumer that serializes diagnostics to a bitcode file.
std::unique_ptr< ASTConsumer > makeTUSummaryExtractor(llvm::StringRef SummaryName, TUSummaryBuilder &Builder)
Try to instantiate a TUSummaryExtractor with a given name.
std::unique_ptr< SerializationFormat > makeFormat(llvm::StringRef FormatName)
Try to instantiate a SerializationFormat with a given name.
bool isFormatRegistered(llvm::StringRef FormatName)
Check if a SerializationFormat was registered with a given name.
bool isTUSummaryExtractorRegistered(llvm::StringRef SummaryName)
Check if a TUSummaryExtractor was registered with a given name.
The JSON file list parser is used to communicate input to InstallAPI.