15
15
#include " clang/Basic/FileEntry.h"
16
16
#include " clang/Basic/LangStandard.h"
17
17
#include " clang/Basic/Sarif.h"
18
+ #include " clang/Basic/SourceManager.h"
18
19
#include " clang/Basic/Stack.h"
19
20
#include " clang/Frontend/ASTUnit.h"
20
21
#include " clang/Frontend/CompilerInstance.h"
35
36
#include " clang/Serialization/ASTReader.h"
36
37
#include " clang/Serialization/GlobalModuleIndex.h"
37
38
#include " llvm/ADT/ScopeExit.h"
39
+ #include " llvm/ADT/StringRef.h"
38
40
#include " llvm/Support/BuryPointer.h"
39
41
#include " llvm/Support/ErrorHandling.h"
40
42
#include " llvm/Support/FileSystem.h"
@@ -49,6 +51,135 @@ LLVM_INSTANTIATE_REGISTRY(FrontendPluginRegistry)
49
51
50
52
namespace {
51
53
54
+ // / Dumps deserialized declarations.
55
+ class DeserializedDeclsLineRangePrinter : public DelegatingDeserializationListener , public ASTConsumer {
56
+ public:
57
+ explicit DeserializedDeclsLineRangePrinter (SourceManager &SM, std::unique_ptr<llvm::raw_fd_ostream> OS)
58
+ : DelegatingDeserializationListener(nullptr , false ), SM(SM), OS(std::move(OS)) {}
59
+
60
+ void DeclRead (GlobalDeclID ID, const Decl *D) override {
61
+ if (!IsCollectingDecls) {
62
+ return ;
63
+ }
64
+ if (!D || isa<TranslationUnitDecl>(D) || isa<LinkageSpecDecl>(D) ||
65
+ isa<NamespaceDecl>(D))
66
+ return ;
67
+ if (auto *DC = D->getDeclContext (); !DC || !DC->isFileContext ())
68
+ return ;
69
+ PendingDecls.push_back (D);
70
+ DelegatingDeserializationListener::DeclRead (ID, D);
71
+ }
72
+
73
+ using Position = std::pair<unsigned , unsigned >;
74
+ struct RequiredRanges {
75
+ StringRef Filename;
76
+ std::vector<std::pair<Position, Position>> FromTo;
77
+ };
78
+ void HandleTranslationUnit (ASTContext &Context) override {
79
+ IsCollectingDecls = false ;
80
+ std::vector<const Decl *> Decls = std::move (PendingDecls);
81
+ if (!PendingDecls.empty ()) {
82
+ llvm::errs () << " Deserialized more decls while printing, total of "
83
+ << PendingDecls.size () << " \n " ;
84
+ PendingDecls.clear ();
85
+ }
86
+
87
+ // Merge ranges in each of the files. For simplicity, track lines and hope
88
+ // they do not break things.
89
+ struct FileData {
90
+ std::vector<std::pair<Position, Position>> FromTo;
91
+ std::vector<std::pair<unsigned , unsigned >> Columns;
92
+ OptionalFileEntryRef Ref;
93
+ };
94
+ llvm::DenseMap<const FileEntry *, FileData> FileToLines;
95
+ for (const Decl *D : Decls) {
96
+ CharSourceRange R = SM.getExpansionRange (D->getSourceRange ());
97
+ if (!R.isValid ())
98
+ continue ;
99
+
100
+ auto *F = SM.getFileEntryForID (SM.getFileID (R.getBegin ()));
101
+ if (F != SM.getFileEntryForID (SM.getFileID (R.getEnd ())))
102
+ continue ;
103
+
104
+ auto &Data = FileToLines[F];
105
+ if (!Data.Ref )
106
+ Data.Ref =
107
+ SM.getFileEntryRefForID (SM.getFileID (R.getBegin ()));
108
+ Data.FromTo .push_back ({{SM.getSpellingLineNumber (R.getBegin ()), SM.getSpellingColumnNumber (R.getBegin ())},
109
+ {SM.getSpellingLineNumber (R.getEnd ()), SM.getSpellingColumnNumber (R.getEnd ())}});
110
+ }
111
+
112
+ std::vector<RequiredRanges> Result;
113
+ for (auto &[F, Data] : FileToLines) {
114
+ auto & FromTo = Data.FromTo ;
115
+ assert (!FromTo.empty ());
116
+
117
+ if (!Data.Ref ) continue ;
118
+
119
+ llvm::sort (FromTo);
120
+
121
+ std::vector<std::pair<Position, Position>> MergedLines;
122
+ MergedLines.push_back (FromTo.front ());
123
+ for (auto It = FromTo.begin () + 1 ; It < FromTo.end (); ++It) {
124
+ if (MergedLines.back ().second < It->first ) {
125
+ MergedLines.push_back (*It);
126
+ continue ;
127
+ }
128
+ if (MergedLines.back ().second < It->second )
129
+ MergedLines.back ().second = It->second ;
130
+ }
131
+ Result.push_back ({Data.Ref ->getName (), MergedLines});
132
+ }
133
+ printJson (Result);
134
+ }
135
+
136
+ void printJson (const std::vector<RequiredRanges>& Result) {
137
+ *OS << " {\n " ;
138
+ *OS << " \" required_ranges\" : [\n " ;
139
+ for (size_t i = 0 ; i < Result.size (); ++i) {
140
+ auto &F = Result[i].Filename ;
141
+ auto &MergedLines = Result[i].FromTo ;
142
+ *OS << " {\n " ;
143
+ *OS << " \" file\" : \" " << F << " \" ,\n " ;
144
+ *OS << " \" range\" : [\n " ;
145
+ for (size_t j = 0 ; j < MergedLines.size (); ++j) {
146
+ auto &From = MergedLines[j].first ;
147
+ auto &To = MergedLines[j].second ;
148
+ *OS << " {\n " ;
149
+ *OS << " \" from\" : {\n " ;
150
+ *OS << " \" line\" : " << From.first << " ,\n " ;
151
+ *OS << " \" column\" : " << From.second << " \n },\n " ;
152
+ *OS << " \" to\" : {\n " ;
153
+ *OS << " \" line\" : " << To.first << " ,\n " ;
154
+ *OS << " \" column\" : " << To.second << " \n }\n " ;
155
+ *OS << " }" ;
156
+ if (j < MergedLines.size () - 1 ) {
157
+ *OS << " ," ;
158
+ }
159
+ *OS << " \n " ;
160
+ }
161
+ *OS << " ]\n }" ;
162
+ if (i < Result.size () - 1 ) {
163
+ *OS << " ," ;
164
+ }
165
+ *OS << " \n " ;
166
+ }
167
+ *OS << " ]\n " ;
168
+ *OS << " }\n " ;
169
+ }
170
+
171
+ ASTDeserializationListener *GetASTDeserializationListener () override {
172
+ return this ;
173
+ }
174
+
175
+ private:
176
+ std::vector<const Decl *> PendingDecls;
177
+ bool IsCollectingDecls = true ;
178
+ const SourceManager &SM;
179
+ std::unique_ptr<llvm::raw_ostream> OS;
180
+ };
181
+
182
+
52
183
// / Dumps deserialized declarations.
53
184
class DeserializedDeclsDumper : public DelegatingDeserializationListener {
54
185
public:
@@ -121,6 +252,19 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
121
252
if (!Consumer)
122
253
return nullptr ;
123
254
255
+ std::vector<std::unique_ptr<ASTConsumer>> Consumers;
256
+ llvm::StringRef PrintDeserializedDeclarationsPath = CI.getFrontendOpts ().PrintDeserializedDeclarationsPath ;
257
+ if (!PrintDeserializedDeclarationsPath.empty ()) {
258
+ std::error_code ErrorCode;
259
+ auto * FileStream = new llvm::raw_fd_ostream (PrintDeserializedDeclarationsPath, ErrorCode, llvm::sys::fs::OF_None);
260
+ if (!ErrorCode) {
261
+ DeserializedDeclsLineRangePrinter* Printer = new DeserializedDeclsLineRangePrinter (CI.getSourceManager (), std::unique_ptr<llvm::raw_fd_ostream>(FileStream));
262
+ Consumers.push_back (std::unique_ptr<ASTConsumer>(Printer));
263
+ } else {
264
+ llvm::errs () << " Could not open file with path: " << PrintDeserializedDeclarationsPath << " , error: " << ErrorCode.message () << " \n " ;
265
+ }
266
+ }
267
+
124
268
// Validate -add-plugin args.
125
269
bool FoundAllPlugins = true ;
126
270
for (const std::string &Arg : CI.getFrontendOpts ().AddPluginActions ) {
@@ -139,16 +283,17 @@ FrontendAction::CreateWrappedASTConsumer(CompilerInstance &CI,
139
283
return nullptr ;
140
284
141
285
// If there are no registered plugins we don't need to wrap the consumer
142
- if (FrontendPluginRegistry::begin () == FrontendPluginRegistry::end ())
143
- return Consumer;
286
+ if (FrontendPluginRegistry::begin () == FrontendPluginRegistry::end ()) {
287
+ Consumers.push_back (std::move (Consumer));
288
+ return std::make_unique<MultiplexConsumer>(std::move (Consumers));
289
+ }
144
290
145
291
// If this is a code completion run, avoid invoking the plugin consumers
146
292
if (CI.hasCodeCompletionConsumer ())
147
293
return Consumer;
148
294
149
295
// Collect the list of plugins that go before the main action (in Consumers)
150
296
// or after it (in AfterConsumers)
151
- std::vector<std::unique_ptr<ASTConsumer>> Consumers;
152
297
std::vector<std::unique_ptr<ASTConsumer>> AfterConsumers;
153
298
for (const FrontendPluginRegistry::entry &Plugin :
154
299
FrontendPluginRegistry::entries ()) {
0 commit comments