]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/Index/IndexingAction.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / Index / IndexingAction.cpp
1 //===- IndexingAction.cpp - Frontend index action -------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "clang/Index/IndexingAction.h"
11 #include "IndexingContext.h"
12 #include "clang/Frontend/CompilerInstance.h"
13 #include "clang/Frontend/FrontendAction.h"
14 #include "clang/Frontend/MultiplexConsumer.h"
15 #include "clang/Index/IndexDataConsumer.h"
16 #include "clang/Lex/PPCallbacks.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "clang/Serialization/ASTReader.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include <memory>
21
22 using namespace clang;
23 using namespace clang::index;
24
25 bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
26                                             ArrayRef<SymbolRelation> Relations,
27                                             SourceLocation Loc,
28                                             ASTNodeInfo ASTNode) {
29   return true;
30 }
31
32 bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name,
33                                              const MacroInfo *MI,
34                                              SymbolRoleSet Roles,
35                                              SourceLocation Loc) {
36   return true;
37 }
38
39 bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD,
40                                               const Module *Mod,
41                                               SymbolRoleSet Roles,
42                                               SourceLocation Loc) {
43   return true;
44 }
45
46 namespace {
47
48 class IndexASTConsumer : public ASTConsumer {
49   std::shared_ptr<Preprocessor> PP;
50   std::shared_ptr<IndexingContext> IndexCtx;
51
52 public:
53   IndexASTConsumer(std::shared_ptr<Preprocessor> PP,
54                    std::shared_ptr<IndexingContext> IndexCtx)
55       : PP(std::move(PP)), IndexCtx(std::move(IndexCtx)) {}
56
57 protected:
58   void Initialize(ASTContext &Context) override {
59     IndexCtx->setASTContext(Context);
60     IndexCtx->getDataConsumer().initialize(Context);
61     IndexCtx->getDataConsumer().setPreprocessor(PP);
62   }
63
64   bool HandleTopLevelDecl(DeclGroupRef DG) override {
65     return IndexCtx->indexDeclGroupRef(DG);
66   }
67
68   void HandleInterestingDecl(DeclGroupRef DG) override {
69     // Ignore deserialized decls.
70   }
71
72   void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
73     IndexCtx->indexDeclGroupRef(DG);
74   }
75
76   void HandleTranslationUnit(ASTContext &Ctx) override {
77   }
78 };
79
80 class IndexPPCallbacks : public PPCallbacks {
81   std::shared_ptr<IndexingContext> IndexCtx;
82
83 public:
84   IndexPPCallbacks(std::shared_ptr<IndexingContext> IndexCtx)
85       : IndexCtx(std::move(IndexCtx)) {}
86
87   void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
88                     SourceRange Range, const MacroArgs *Args) override {
89     IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),
90                                    Range.getBegin(), *MD.getMacroInfo());
91   }
92
93   void MacroDefined(const Token &MacroNameTok,
94                     const MacroDirective *MD) override {
95     IndexCtx->handleMacroDefined(*MacroNameTok.getIdentifierInfo(),
96                                  MacroNameTok.getLocation(),
97                                  *MD->getMacroInfo());
98   }
99
100   void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
101                       const MacroDirective *Undef) override {
102     if (!MD.getMacroInfo())  // Ignore noop #undef.
103       return;
104     IndexCtx->handleMacroUndefined(*MacroNameTok.getIdentifierInfo(),
105                                    MacroNameTok.getLocation(),
106                                    *MD.getMacroInfo());
107   }
108 };
109
110 class IndexActionBase {
111 protected:
112   std::shared_ptr<IndexDataConsumer> DataConsumer;
113   std::shared_ptr<IndexingContext> IndexCtx;
114
115   IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
116                   IndexingOptions Opts)
117       : DataConsumer(std::move(dataConsumer)),
118         IndexCtx(new IndexingContext(Opts, *DataConsumer)) {}
119
120   std::unique_ptr<IndexASTConsumer>
121   createIndexASTConsumer(CompilerInstance &CI) {
122     return llvm::make_unique<IndexASTConsumer>(CI.getPreprocessorPtr(),
123                                                IndexCtx);
124   }
125
126   std::unique_ptr<PPCallbacks> createIndexPPCallbacks() {
127     return llvm::make_unique<IndexPPCallbacks>(IndexCtx);
128   }
129
130   void finish() {
131     DataConsumer->finish();
132   }
133 };
134
135 class IndexAction : public ASTFrontendAction, IndexActionBase {
136 public:
137   IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
138               IndexingOptions Opts)
139     : IndexActionBase(std::move(DataConsumer), Opts) {}
140
141 protected:
142   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
143                                                  StringRef InFile) override {
144     return createIndexASTConsumer(CI);
145   }
146
147   bool BeginSourceFileAction(clang::CompilerInstance &CI) override {
148     CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks());
149     return true;
150   }
151
152   void EndSourceFileAction() override {
153     FrontendAction::EndSourceFileAction();
154     finish();
155   }
156 };
157
158 class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase {
159   bool IndexActionFailed = false;
160
161 public:
162   WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction,
163                       std::shared_ptr<IndexDataConsumer> DataConsumer,
164                       IndexingOptions Opts)
165     : WrapperFrontendAction(std::move(WrappedAction)),
166       IndexActionBase(std::move(DataConsumer), Opts) {}
167
168 protected:
169   std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
170                                                  StringRef InFile) override {
171     auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
172     if (!OtherConsumer) {
173       IndexActionFailed = true;
174       return nullptr;
175     }
176
177     std::vector<std::unique_ptr<ASTConsumer>> Consumers;
178     Consumers.push_back(std::move(OtherConsumer));
179     Consumers.push_back(createIndexASTConsumer(CI));
180     return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
181   }
182
183   bool BeginSourceFileAction(clang::CompilerInstance &CI) override {
184     WrapperFrontendAction::BeginSourceFileAction(CI);
185     CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks());
186     return true;
187   }
188
189   void EndSourceFileAction() override {
190     // Invoke wrapped action's method.
191     WrapperFrontendAction::EndSourceFileAction();
192     if (!IndexActionFailed)
193       finish();
194   }
195 };
196
197 } // anonymous namespace
198
199 std::unique_ptr<FrontendAction>
200 index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
201                             IndexingOptions Opts,
202                             std::unique_ptr<FrontendAction> WrappedAction) {
203   if (WrappedAction)
204     return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction),
205                                                   std::move(DataConsumer),
206                                                   Opts);
207   return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts);
208 }
209
210 static bool topLevelDeclVisitor(void *context, const Decl *D) {
211   IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
212   return IndexCtx.indexTopLevelDecl(D);
213 }
214
215 static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
216   Unit.visitLocalTopLevelDecls(&IndexCtx, topLevelDeclVisitor);
217 }
218
219 static void indexPreprocessorMacros(const Preprocessor &PP,
220                                     IndexDataConsumer &DataConsumer) {
221   for (const auto &M : PP.macros())
222     if (MacroDirective *MD = M.second.getLatest())
223       DataConsumer.handleMacroOccurence(
224           M.first, MD->getMacroInfo(),
225           static_cast<unsigned>(index::SymbolRole::Definition),
226           MD->getLocation());
227 }
228
229 void index::indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer,
230                          IndexingOptions Opts) {
231   IndexingContext IndexCtx(Opts, DataConsumer);
232   IndexCtx.setASTContext(Unit.getASTContext());
233   DataConsumer.initialize(Unit.getASTContext());
234   DataConsumer.setPreprocessor(Unit.getPreprocessorPtr());
235
236   if (Opts.IndexMacrosInPreprocessor)
237     indexPreprocessorMacros(Unit.getPreprocessor(), DataConsumer);
238   indexTranslationUnit(Unit, IndexCtx);
239   DataConsumer.finish();
240 }
241
242 void index::indexTopLevelDecls(ASTContext &Ctx, Preprocessor &PP,
243                                ArrayRef<const Decl *> Decls,
244                                IndexDataConsumer &DataConsumer,
245                                IndexingOptions Opts) {
246   IndexingContext IndexCtx(Opts, DataConsumer);
247   IndexCtx.setASTContext(Ctx);
248
249   DataConsumer.initialize(Ctx);
250
251   if (Opts.IndexMacrosInPreprocessor)
252     indexPreprocessorMacros(PP, DataConsumer);
253
254   for (const Decl *D : Decls)
255     IndexCtx.indexTopLevelDecl(D);
256   DataConsumer.finish();
257 }
258
259 std::unique_ptr<PPCallbacks>
260 index::indexMacrosCallback(IndexDataConsumer &Consumer, IndexingOptions Opts) {
261   return llvm::make_unique<IndexPPCallbacks>(
262       std::make_shared<IndexingContext>(Opts, Consumer));
263 }
264
265 void index::indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader,
266                             IndexDataConsumer &DataConsumer,
267                             IndexingOptions Opts) {
268   ASTContext &Ctx = Reader.getContext();
269   IndexingContext IndexCtx(Opts, DataConsumer);
270   IndexCtx.setASTContext(Ctx);
271   DataConsumer.initialize(Ctx);
272
273   if (Opts.IndexMacrosInPreprocessor)
274     indexPreprocessorMacros(Reader.getPreprocessor(), DataConsumer);
275
276   for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {
277     IndexCtx.indexTopLevelDecl(D);
278   }
279   DataConsumer.finish();
280 }