clang  9.0.0
IndexingAction.cpp
Go to the documentation of this file.
1 //===- IndexingAction.cpp - Frontend index action -------------------------===//
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 
10 #include "IndexingContext.h"
15 #include "clang/Lex/PPCallbacks.h"
16 #include "clang/Lex/Preprocessor.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include <memory>
20 
21 using namespace clang;
22 using namespace clang::index;
23 
25  ArrayRef<SymbolRelation> Relations,
26  SourceLocation Loc,
27  ASTNodeInfo ASTNode) {
28  return true;
29 }
30 
32  const MacroInfo *MI,
33  SymbolRoleSet Roles,
34  SourceLocation Loc) {
35  return true;
36 }
37 
39  const Module *Mod,
40  SymbolRoleSet Roles,
41  SourceLocation Loc) {
42  return true;
43 }
44 
45 namespace {
46 
47 class IndexASTConsumer : public ASTConsumer {
48  std::shared_ptr<Preprocessor> PP;
49  std::shared_ptr<IndexingContext> IndexCtx;
50 
51 public:
52  IndexASTConsumer(std::shared_ptr<Preprocessor> PP,
53  std::shared_ptr<IndexingContext> IndexCtx)
54  : PP(std::move(PP)), IndexCtx(std::move(IndexCtx)) {}
55 
56 protected:
57  void Initialize(ASTContext &Context) override {
58  IndexCtx->setASTContext(Context);
59  IndexCtx->getDataConsumer().initialize(Context);
60  IndexCtx->getDataConsumer().setPreprocessor(PP);
61  }
62 
63  bool HandleTopLevelDecl(DeclGroupRef DG) override {
64  return IndexCtx->indexDeclGroupRef(DG);
65  }
66 
67  void HandleInterestingDecl(DeclGroupRef DG) override {
68  // Ignore deserialized decls.
69  }
70 
71  void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override {
72  IndexCtx->indexDeclGroupRef(DG);
73  }
74 
75  void HandleTranslationUnit(ASTContext &Ctx) override {
76  }
77 };
78 
79 class IndexPPCallbacks : public PPCallbacks {
80  std::shared_ptr<IndexingContext> IndexCtx;
81 
82 public:
83  IndexPPCallbacks(std::shared_ptr<IndexingContext> IndexCtx)
84  : IndexCtx(std::move(IndexCtx)) {}
85 
86  void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
87  SourceRange Range, const MacroArgs *Args) override {
88  IndexCtx->handleMacroReference(*MacroNameTok.getIdentifierInfo(),
89  Range.getBegin(), *MD.getMacroInfo());
90  }
91 
92  void MacroDefined(const Token &MacroNameTok,
93  const MacroDirective *MD) override {
94  IndexCtx->handleMacroDefined(*MacroNameTok.getIdentifierInfo(),
95  MacroNameTok.getLocation(),
96  *MD->getMacroInfo());
97  }
98 
99  void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD,
100  const MacroDirective *Undef) override {
101  if (!MD.getMacroInfo()) // Ignore noop #undef.
102  return;
103  IndexCtx->handleMacroUndefined(*MacroNameTok.getIdentifierInfo(),
104  MacroNameTok.getLocation(),
105  *MD.getMacroInfo());
106  }
107 };
108 
109 class IndexActionBase {
110 protected:
111  std::shared_ptr<IndexDataConsumer> DataConsumer;
112  std::shared_ptr<IndexingContext> IndexCtx;
113 
114  IndexActionBase(std::shared_ptr<IndexDataConsumer> dataConsumer,
115  IndexingOptions Opts)
116  : DataConsumer(std::move(dataConsumer)),
117  IndexCtx(new IndexingContext(Opts, *DataConsumer)) {}
118 
119  std::unique_ptr<IndexASTConsumer>
120  createIndexASTConsumer(CompilerInstance &CI) {
121  return llvm::make_unique<IndexASTConsumer>(CI.getPreprocessorPtr(),
122  IndexCtx);
123  }
124 
125  std::unique_ptr<PPCallbacks> createIndexPPCallbacks() {
126  return llvm::make_unique<IndexPPCallbacks>(IndexCtx);
127  }
128 
129  void finish() {
130  DataConsumer->finish();
131  }
132 };
133 
134 class IndexAction : public ASTFrontendAction, IndexActionBase {
135 public:
136  IndexAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
137  IndexingOptions Opts)
138  : IndexActionBase(std::move(DataConsumer), Opts) {}
139 
140 protected:
141  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
142  StringRef InFile) override {
143  return createIndexASTConsumer(CI);
144  }
145 
146  bool BeginSourceFileAction(clang::CompilerInstance &CI) override {
147  CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks());
148  return true;
149  }
150 
151  void EndSourceFileAction() override {
153  finish();
154  }
155 };
156 
157 class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase {
158  bool IndexActionFailed = false;
159 
160 public:
161  WrappingIndexAction(std::unique_ptr<FrontendAction> WrappedAction,
162  std::shared_ptr<IndexDataConsumer> DataConsumer,
163  IndexingOptions Opts)
164  : WrapperFrontendAction(std::move(WrappedAction)),
165  IndexActionBase(std::move(DataConsumer), Opts) {}
166 
167 protected:
168  std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI,
169  StringRef InFile) override {
170  auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
171  if (!OtherConsumer) {
172  IndexActionFailed = true;
173  return nullptr;
174  }
175 
176  std::vector<std::unique_ptr<ASTConsumer>> Consumers;
177  Consumers.push_back(std::move(OtherConsumer));
178  Consumers.push_back(createIndexASTConsumer(CI));
179  return llvm::make_unique<MultiplexConsumer>(std::move(Consumers));
180  }
181 
182  bool BeginSourceFileAction(clang::CompilerInstance &CI) override {
184  CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks());
185  return true;
186  }
187 
188  void EndSourceFileAction() override {
189  // Invoke wrapped action's method.
191  if (!IndexActionFailed)
192  finish();
193  }
194 };
195 
196 } // anonymous namespace
197 
198 std::unique_ptr<FrontendAction>
199 index::createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer,
200  IndexingOptions Opts,
201  std::unique_ptr<FrontendAction> WrappedAction) {
202  if (WrappedAction)
203  return llvm::make_unique<WrappingIndexAction>(std::move(WrappedAction),
204  std::move(DataConsumer),
205  Opts);
206  return llvm::make_unique<IndexAction>(std::move(DataConsumer), Opts);
207 }
208 
209 static bool topLevelDeclVisitor(void *context, const Decl *D) {
210  IndexingContext &IndexCtx = *static_cast<IndexingContext*>(context);
211  return IndexCtx.indexTopLevelDecl(D);
212 }
213 
214 static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx) {
216 }
217 
218 static void indexPreprocessorMacros(const Preprocessor &PP,
219  IndexDataConsumer &DataConsumer) {
220  for (const auto &M : PP.macros())
221  if (MacroDirective *MD = M.second.getLatest())
222  DataConsumer.handleMacroOccurence(
223  M.first, MD->getMacroInfo(),
224  static_cast<unsigned>(index::SymbolRole::Definition),
225  MD->getLocation());
226 }
227 
229  IndexingOptions Opts) {
230  IndexingContext IndexCtx(Opts, DataConsumer);
231  IndexCtx.setASTContext(Unit.getASTContext());
232  DataConsumer.initialize(Unit.getASTContext());
233  DataConsumer.setPreprocessor(Unit.getPreprocessorPtr());
234 
235  if (Opts.IndexMacrosInPreprocessor)
236  indexPreprocessorMacros(Unit.getPreprocessor(), DataConsumer);
237  indexTranslationUnit(Unit, IndexCtx);
238  DataConsumer.finish();
239 }
240 
243  IndexDataConsumer &DataConsumer,
244  IndexingOptions Opts) {
245  IndexingContext IndexCtx(Opts, DataConsumer);
246  IndexCtx.setASTContext(Ctx);
247 
248  DataConsumer.initialize(Ctx);
249 
250  if (Opts.IndexMacrosInPreprocessor)
251  indexPreprocessorMacros(PP, DataConsumer);
252 
253  for (const Decl *D : Decls)
254  IndexCtx.indexTopLevelDecl(D);
255  DataConsumer.finish();
256 }
257 
258 std::unique_ptr<PPCallbacks>
260  return llvm::make_unique<IndexPPCallbacks>(
261  std::make_shared<IndexingContext>(Opts, Consumer));
262 }
263 
265  IndexDataConsumer &DataConsumer,
266  IndexingOptions Opts) {
267  ASTContext &Ctx = Reader.getContext();
268  IndexingContext IndexCtx(Opts, DataConsumer);
269  IndexCtx.setASTContext(Ctx);
270  DataConsumer.initialize(Ctx);
271 
272  if (Opts.IndexMacrosInPreprocessor)
273  indexPreprocessorMacros(Reader.getPreprocessor(), DataConsumer);
274 
275  for (const Decl *D : Reader.getModuleFileLevelDecls(Mod)) {
276  IndexCtx.indexTopLevelDecl(D);
277  }
278  DataConsumer.finish();
279 }
virtual void setPreprocessor(std::shared_ptr< Preprocessor > PP)
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
Definition: ASTConsumer.h:33
const Preprocessor & getPreprocessor() const
Definition: ASTUnit.h:435
static void indexPreprocessorMacros(const Preprocessor &PP, IndexDataConsumer &DataConsumer)
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:88
virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef< SymbolRelation > Relations, SourceLocation Loc, ASTNodeInfo ASTNode)
A description of the current definition of a macro.
Definition: MacroInfo.h:564
bool indexTopLevelDecl(const Decl *D)
Definition: IndexDecl.cpp:755
void setASTContext(ASTContext &ctx)
This interface provides a way to observe the actions of the preprocessor as it does its thing...
Definition: PPCallbacks.h:35
One of these records is kept for each identifier that is lexed.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:154
Utility class for loading a ASTContext from an AST file.
Definition: ASTUnit.h:89
void indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer, IndexingOptions Opts)
Recursively indexes all decls in the AST.
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
Token - This structure provides full information about a lexed token.
Definition: Token.h:34
std::shared_ptr< Preprocessor > getPreprocessorPtr()
Describes a module or submodule.
Definition: Module.h:64
void indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader, IndexDataConsumer &DataConsumer, IndexingOptions Opts)
Recursively indexes all top-level decls in the module.
llvm::iterator_range< ModuleDeclIterator > getModuleFileLevelDecls(ModuleFile &Mod)
Definition: ASTReader.cpp:5790
ASTContext & getContext()
Retrieve the AST context that this AST reader supplements.
Definition: ASTReader.h:2311
unsigned SymbolRoleSet
Definition: IndexSymbol.h:127
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
Definition: MacroArgs.h:29
bool BeginSourceFileAction(CompilerInstance &CI) override
Callback at the start of processing a single input.
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:126
Defines the clang::Preprocessor interface.
virtual void EndSourceFileAction()
Callback at the end of processing a single input.
Information about a module that has been loaded by the ASTReader.
Definition: Module.h:107
void EndSourceFileAction() override
Callback at the end of processing a single input.
virtual void initialize(ASTContext &Ctx)
Encapsulates changes to the "macros namespace" (the location where the macro name became active...
Definition: MacroInfo.h:290
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:179
Abstract base class to use for AST consumer-based frontend actions.
virtual bool handleModuleOccurence(const ImportDecl *ImportD, const Module *Mod, SymbolRoleSet Roles, SourceLocation Loc)
bool visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn)
Iterate over local declarations (locally parsed if this is a parsed source file or the loaded declara...
Definition: ASTUnit.cpp:2613
Describes a module import declaration, which makes the contents of the named module visible in the cu...
Definition: Decl.h:4213
const MacroInfo * getMacroInfo() const
Definition: MacroInfo.h:390
Dataflow Directional Tag Classes.
virtual bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI, SymbolRoleSet Roles, SourceLocation Loc)
Reads an AST files chain containing the contents of a translation unit.
Definition: ASTReader.h:354
void indexTopLevelDecls(ASTContext &Ctx, Preprocessor &PP, ArrayRef< const Decl *> Decls, IndexDataConsumer &DataConsumer, IndexingOptions Opts)
Recursively indexes Decls.
llvm::iterator_range< macro_iterator > macros(bool IncludeExternalMacros=true) const
A frontend action which simply wraps some other runtime-specified frontend action.
Encapsulates the data about a macro definition (e.g.
Definition: MacroInfo.h:39
std::shared_ptr< Preprocessor > getPreprocessorPtr() const
Definition: ASTUnit.h:437
Preprocessor & getPreprocessor() const
Retrieve the preprocessor.
Definition: ASTReader.h:1661
const ASTContext & getASTContext() const
Definition: ASTUnit.h:439
Defines the PPCallbacks interface.
static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx)
std::unique_ptr< FrontendAction > createIndexingAction(std::shared_ptr< IndexDataConsumer > DataConsumer, IndexingOptions Opts, std::unique_ptr< FrontendAction > WrappedAction)
Creates a frontend action that indexes all symbols (macros and AST decls).
Preprocessor & getPreprocessor() const
Return the current preprocessor.
std::unique_ptr< PPCallbacks > indexMacrosCallback(IndexDataConsumer &Consumer, IndexingOptions Opts)
Creates a PPCallbacks that indexes macros and feeds macros to Consumer.
static bool topLevelDeclVisitor(void *context, const Decl *D)
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
MacroInfo * getMacroInfo() const
Get the MacroInfo that should be used for this definition.
Definition: MacroInfo.h:580
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Definition: Preprocessor.h:995
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:124