clang  8.0.0svn
IndexingAction.cpp
Go to the documentation of this file.
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 
11 #include "IndexingContext.h"
16 #include "clang/Lex/PPCallbacks.h"
17 #include "clang/Lex/Preprocessor.h"
19 #include "llvm/ADT/STLExtras.h"
20 #include <memory>
21 
22 using namespace clang;
23 using namespace clang::index;
24 
26  ArrayRef<SymbolRelation> Relations,
27  SourceLocation Loc,
28  ASTNodeInfo ASTNode) {
29  return true;
30 }
31 
33  const MacroInfo *MI,
34  SymbolRoleSet Roles,
35  SourceLocation Loc) {
36  return true;
37 }
38 
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 {
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 {
185  CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks());
186  return true;
187  }
188 
189  void EndSourceFileAction() override {
190  // Invoke wrapped action's method.
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) {
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 
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 
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>
261  return llvm::make_unique<IndexPPCallbacks>(
262  std::make_shared<IndexingContext>(Opts, Consumer));
263 }
264 
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 }
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:34
const Preprocessor & getPreprocessor() const
Definition: ASTUnit.h:431
static void indexPreprocessorMacros(const Preprocessor &PP, IndexDataConsumer &DataConsumer)
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:87
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:750
void setASTContext(ASTContext &ctx)
This interface provides a way to observe the actions of the preprocessor as it does its thing...
Definition: PPCallbacks.h:36
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:88
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:35
std::shared_ptr< Preprocessor > getPreprocessorPtr()
Describes a module or submodule.
Definition: Module.h:65
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:5421
ASTContext & getContext()
Retrieve the AST context that this AST reader supplements.
Definition: ASTReader.h:2307
unsigned SymbolRoleSet
Definition: IndexSymbol.h:124
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
Definition: MacroArgs.h:30
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:124
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:108
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:291
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:177
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:2584
Describes a module import declaration, which makes the contents of the named module visible in the cu...
Definition: Decl.h:4118
const MacroInfo * getMacroInfo() const
Definition: MacroInfo.h:391
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:355
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:40
std::shared_ptr< Preprocessor > getPreprocessorPtr() const
Definition: ASTUnit.h:433
Preprocessor & getPreprocessor() const
Retrieve the preprocessor.
Definition: ASTReader.h:1664
const ASTContext & getASTContext() const
Definition: ASTUnit.h:435
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:924
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:127