clang 8.0.0

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
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 }
clang::index::IndexDataConsumer::setPreprocessor
virtual void setPreprocessor(std::shared_ptr< Preprocessor > PP)
Definition: IndexDataConsumer.h:40
clang::ASTConsumer
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs...
Definition: ASTConsumer.h:34
clang::ASTUnit::getPreprocessor
const Preprocessor & getPreprocessor() const
Definition: ASTUnit.h:430
indexPreprocessorMacros
static void indexPreprocessorMacros(const Preprocessor &PP, IndexDataConsumer &DataConsumer)
Definition: IndexingAction.cpp:219
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:87
clang::index::IndexDataConsumer::handleDeclOccurence
virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef< SymbolRelation > Relations, SourceLocation Loc, ASTNodeInfo ASTNode)
Definition: IndexingAction.cpp:25
clang::index::IndexingOptions
Definition: IndexingAction.h:33
clang::MacroDefinition
A description of the current definition of a macro.
Definition: MacroInfo.h:565
clang::index::IndexingContext::indexTopLevelDecl
bool indexTopLevelDecl(const Decl *D)
Definition: IndexDecl.cpp:750
ASTReader.h
IndexDataConsumer.h
clang::index::IndexingOptions::IndexMacrosInPreprocessor
bool IndexMacrosInPreprocessor
Definition: IndexingAction.h:47
clang::index::IndexingContext::setASTContext
void setASTContext(ASTContext &ctx)
Definition: IndexingContext.h:51
clang::PPCallbacks
This interface provides a way to observe the actions of the preprocessor as it does its thing...
Definition: PPCallbacks.h:36
clang::IdentifierInfo
One of these records is kept for each identifier that is lexed.
Definition: IdentifierTable.h:58
clang::ASTContext
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:155
clang::ASTUnit
Utility class for loading a ASTContext from an AST file.
Definition: ASTUnit.h:87
clang::index::indexASTUnit
void indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer, IndexingOptions Opts)
Recursively indexes all decls in the AST.
Definition: IndexingAction.cpp:229
clang::WrapperFrontendAction::CreateASTConsumer
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
Definition: FrontendAction.cpp:1049
clang::Token
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
clang::CompilerInstance::getPreprocessorPtr
std::shared_ptr< Preprocessor > getPreprocessorPtr()
Definition: CompilerInstance.h:454
clang::Module
Describes a module or submodule.
Definition: Module.h:65
clang::index::IndexDataConsumer::ASTNodeInfo
Definition: IndexDataConsumer.h:29
clang::index::indexModuleFile
void indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader, IndexDataConsumer &DataConsumer, IndexingOptions Opts)
Recursively indexes all top-level decls in the module.
Definition: IndexingAction.cpp:265
clang::ASTReader::getModuleFileLevelDecls
llvm::iterator_range< ModuleDeclIterator > getModuleFileLevelDecls(ModuleFile &Mod)
Definition: ASTReader.cpp:5420
clang::ASTReader::getContext
ASTContext & getContext()
Retrieve the AST context that this AST reader supplements.
Definition: ASTReader.h:2307
clang::index::IndexDataConsumer
Definition: IndexDataConsumer.h:27
IndexingContext.h
llvm::ArrayRef
Definition: LLVM.h:32
clang::index::SymbolRole::Definition
clang::index::SymbolRoleSet
unsigned SymbolRoleSet
Definition: IndexSymbol.h:124
CompilerInstance.h
clang::index::IndexingContext
Definition: IndexingContext.h:39
clang::MacroArgs
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
Definition: MacroArgs.h:30
clang::WrapperFrontendAction::BeginSourceFileAction
bool BeginSourceFileAction(CompilerInstance &CI) override
Callback at the start of processing a single input.
Definition: FrontendAction.cpp:1056
clang::Token::getLocation
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Definition: Token.h:124
Preprocessor.h
Defines the clang::Preprocessor interface.
clang::FrontendAction::EndSourceFileAction
virtual void EndSourceFileAction()
Callback at the end of processing a single input.
Definition: FrontendAction.h:100
clang::serialization::ModuleFile
Information about a module that has been loaded by the ASTReader.
Definition: Module.h:108
clang::WrapperFrontendAction::EndSourceFileAction
void EndSourceFileAction() override
Callback at the end of processing a single input.
Definition: FrontendAction.cpp:1067
clang::index::IndexDataConsumer::initialize
virtual void initialize(ASTContext &Ctx)
Definition: IndexDataConsumer.h:38
clang::MacroDirective
Encapsulates changes to the "macros namespace" (the location where the macro name became active...
Definition: MacroInfo.h:291
clang::CompilerInstance
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Definition: CompilerInstance.h:73
clang::SourceLocation
Encodes a location in the source.
Definition: SourceLocation.h:88
clang::Token::getIdentifierInfo
IdentifierInfo * getIdentifierInfo() const
Definition: Token.h:177
clang::index
Definition: CodegenNameGenerator.h:26
clang::ASTFrontendAction
Abstract base class to use for AST consumer-based frontend actions.
Definition: FrontendAction.h:243
clang::index::IndexDataConsumer::handleModuleOccurence
virtual bool handleModuleOccurence(const ImportDecl *ImportD, const Module *Mod, SymbolRoleSet Roles, SourceLocation Loc)
Definition: IndexingAction.cpp:39
clang::ASTUnit::visitLocalTopLevelDecls
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:2586
clang::ImportDecl
Describes a module import declaration, which makes the contents of the named module visible in the cu...
Definition: Decl.h:4149
clang::MacroDirective::getMacroInfo
const MacroInfo * getMacroInfo() const
Definition: MacroInfo.h:391
clang
Dataflow Directional Tag Classes.
Definition: CFGReachabilityAnalysis.h:22
clang::index::IndexDataConsumer::handleMacroOccurence
virtual bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI, SymbolRoleSet Roles, SourceLocation Loc)
Definition: IndexingAction.cpp:32
clang::ASTReader
Reads an AST files chain containing the contents of a translation unit.
Definition: ASTReader.h:355
clang::index::indexTopLevelDecls
void indexTopLevelDecls(ASTContext &Ctx, Preprocessor &PP, ArrayRef< const Decl *> Decls, IndexDataConsumer &DataConsumer, IndexingOptions Opts)
Recursively indexes Decls.
Definition: IndexingAction.cpp:242
clang::DeclGroupRef
Definition: DeclGroup.h:52
clang::Preprocessor::macros
llvm::iterator_range< macro_iterator > macros(bool IncludeExternalMacros=true) const
Definition: Preprocessor.h:1042
IndexingAction.h
clang::WrapperFrontendAction
A frontend action which simply wraps some other runtime-specified frontend action.
Definition: FrontendAction.h:304
clang::MacroInfo
Encapsulates the data about a macro definition (e.g.
Definition: MacroInfo.h:40
clang::index::IndexDataConsumer::finish
virtual void finish()
Definition: IndexDataConsumer.h:61
clang::ASTUnit::getPreprocessorPtr
std::shared_ptr< Preprocessor > getPreprocessorPtr() const
Definition: ASTUnit.h:432
clang::ASTReader::getPreprocessor
Preprocessor & getPreprocessor() const
Retrieve the preprocessor.
Definition: ASTReader.h:1664
MultiplexConsumer.h
clang::ASTUnit::getASTContext
const ASTContext & getASTContext() const
Definition: ASTUnit.h:434
PPCallbacks.h
Defines the PPCallbacks interface.
indexTranslationUnit
static void indexTranslationUnit(ASTUnit &Unit, IndexingContext &IndexCtx)
Definition: IndexingAction.cpp:215
clang::index::createIndexingAction
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).
Definition: IndexingAction.cpp:200
clang::CompilerInstance::getPreprocessor
Preprocessor & getPreprocessor() const
Return the current preprocessor.
Definition: CompilerInstance.h:449
clang::index::indexMacrosCallback
std::unique_ptr< PPCallbacks > indexMacrosCallback(IndexDataConsumer &Consumer, IndexingOptions Opts)
Creates a PPCallbacks that indexes macros and feeds macros to Consumer.
Definition: IndexingAction.cpp:260
topLevelDeclVisitor
static bool topLevelDeclVisitor(void *context, const Decl *D)
Definition: IndexingAction.cpp:210
FrontendAction.h
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
clang::MacroDefinition::getMacroInfo
MacroInfo * getMacroInfo() const
Get the MacroInfo that should be used for this definition.
Definition: MacroInfo.h:581
clang::SourceRange
A trivial tuple used to represent a source range.
Definition: SourceLocation.h:198
clang::SourceRange::getBegin
SourceLocation getBegin() const
Definition: SourceLocation.h:207
clang::Preprocessor::addPPCallbacks
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Definition: Preprocessor.h:908
clang::Preprocessor
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
Definition: Preprocessor.h:125