Index: include/clang/Index/IndexDataConsumer.h =================================================================== --- include/clang/Index/IndexDataConsumer.h +++ include/clang/Index/IndexDataConsumer.h @@ -45,9 +45,9 @@ SourceLocation Loc, ASTNodeInfo ASTNode); /// \returns true to continue indexing, or false to abort. - virtual bool handleMacroOccurence(const IdentifierInfo *Name, - const MacroInfo *MI, SymbolRoleSet Roles, - SourceLocation Loc); + virtual bool handleMacroOccurence(const IdentifierInfo &Name, + const MacroInfo &MI, SymbolRoleSet Roles, + SourceLocation Loc, bool Undefined = false); /// \returns true to continue indexing, or false to abort. virtual bool handleModuleOccurence(const ImportDecl *ImportD, Index: include/clang/Index/IndexSymbol.h =================================================================== --- include/clang/Index/IndexSymbol.h +++ include/clang/Index/IndexSymbol.h @@ -135,6 +135,8 @@ SymbolInfo getSymbolInfo(const Decl *D); +SymbolInfo getSymbolInfoForMacro(); + bool isFunctionLocalSymbol(const Decl *D); void applyForEachSymbolRole(SymbolRoleSet Roles, Index: lib/Index/IndexSymbol.cpp =================================================================== --- lib/Index/IndexSymbol.cpp +++ lib/Index/IndexSymbol.cpp @@ -348,6 +348,16 @@ return Info; } +SymbolInfo index::getSymbolInfoForMacro() { + SymbolInfo Info; + Info.Kind = SymbolKind::Macro; + Info.SubKind = SymbolSubKind::None; + Info.Properties = SymbolPropertySet(); + // FIXME: set languages more accurately. + Info.Lang = SymbolLanguage::C; + return Info; +} + bool index::applyForEachSymbolRoleInterruptible(SymbolRoleSet Roles, llvm::function_ref Fn) { #define APPLY_FOR_ROLE(Role) \ Index: lib/Index/IndexingAction.cpp =================================================================== --- lib/Index/IndexingAction.cpp +++ lib/Index/IndexingAction.cpp @@ -13,8 +13,11 @@ #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/MultiplexConsumer.h" #include "clang/Index/IndexDataConsumer.h" +#include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" #include "clang/Serialization/ASTReader.h" +#include "llvm/ADT/STLExtras.h" +#include using namespace clang; using namespace clang::index; @@ -28,10 +31,11 @@ return true; } -bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name, - const MacroInfo *MI, +bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo &Name, + const MacroInfo &MI, SymbolRoleSet Roles, - SourceLocation Loc) { + SourceLocation Loc, + bool Undefined) { return true; } @@ -74,6 +78,33 @@ } }; +class IndexPPCallbacks : public PPCallbacks { + IndexingContext &IndexCtx; + +public: + IndexPPCallbacks(IndexingContext &IndexCtx) : IndexCtx(IndexCtx) {} + + void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, + SourceRange Range, const MacroArgs *Args) override { + IndexCtx.handleMacroReference(*MacroNameTok.getIdentifierInfo(), + Range.getBegin(), *MD.getMacroInfo()); + } + + void MacroDefined(const Token &MacroNameTok, + const MacroDirective *MD) override { + IndexCtx.handleMacroDefined(*MacroNameTok.getIdentifierInfo(), + MacroNameTok.getLocation(), + *MD->getMacroInfo()); + } + + void MacroUndefined(const Token &MacroNameTok, const MacroDefinition &MD, + const MacroDirective *Undef) override { + IndexCtx.handleMacroUndefined(*MacroNameTok.getIdentifierInfo(), + MacroNameTok.getLocation(), + *MD.getMacroInfo()); + } +}; + class IndexActionBase { protected: std::shared_ptr DataConsumer; @@ -90,6 +121,10 @@ IndexCtx); } + std::unique_ptr createIndexPPCallbacks() { + return llvm::make_unique(IndexCtx); + } + void finish() { DataConsumer->finish(); } @@ -107,6 +142,11 @@ return createIndexASTConsumer(CI); } + bool BeginSourceFileAction(clang::CompilerInstance &CI) override { + CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks()); + return true; + } + void EndSourceFileAction() override { FrontendAction::EndSourceFileAction(); finish(); @@ -125,7 +165,25 @@ protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + StringRef InFile) override { + auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); + if (!OtherConsumer) { + IndexActionFailed = true; + return nullptr; + } + + std::vector> Consumers; + Consumers.push_back(std::move(OtherConsumer)); + Consumers.push_back(createIndexASTConsumer(CI)); + return llvm::make_unique(std::move(Consumers)); + } + + bool BeginSourceFileAction(clang::CompilerInstance &CI) override { + WrapperFrontendAction::BeginSourceFileAction(CI); + CI.getPreprocessor().addPPCallbacks(createIndexPPCallbacks()); + return true; + } + void EndSourceFileAction() override; }; @@ -138,20 +196,6 @@ finish(); } -std::unique_ptr -WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); - if (!OtherConsumer) { - IndexActionFailed = true; - return nullptr; - } - - std::vector> Consumers; - Consumers.push_back(std::move(OtherConsumer)); - Consumers.push_back(createIndexASTConsumer(CI)); - return llvm::make_unique(std::move(Consumers)); -} - std::unique_ptr index::createIndexingAction(std::shared_ptr DataConsumer, IndexingOptions Opts, Index: lib/Index/IndexingContext.h =================================================================== --- lib/Index/IndexingContext.h +++ lib/Index/IndexingContext.h @@ -10,9 +10,11 @@ #ifndef LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H #define LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H +#include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Index/IndexSymbol.h" #include "clang/Index/IndexingAction.h" +#include "clang/Lex/MacroInfo.h" #include "llvm/ADT/ArrayRef.h" namespace clang { @@ -80,6 +82,15 @@ const Expr *RefE = nullptr, const Decl *RefD = nullptr); + void handleMacroDefined(const IdentifierInfo &Name, SourceLocation Loc, + const MacroInfo &MI); + + void handleMacroUndefined(const IdentifierInfo &Name, SourceLocation Loc, + const MacroInfo &MI); + + void handleMacroReference(const IdentifierInfo &Name, SourceLocation Loc, + const MacroInfo &MD); + bool importedModule(const ImportDecl *ImportD); bool indexDecl(const Decl *D); Index: lib/Index/IndexingContext.cpp =================================================================== --- lib/Index/IndexingContext.cpp +++ lib/Index/IndexingContext.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "IndexingContext.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Index/IndexDataConsumer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/DeclTemplate.h" @@ -406,3 +407,24 @@ IndexDataConsumer::ASTNodeInfo Node{OrigE, OrigD, Parent, ContainerDC}; return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, Loc, Node); } + +void IndexingContext::handleMacroDefined(const IdentifierInfo &Name, + SourceLocation Loc, + const MacroInfo &MI) { + SymbolRoleSet Roles = (unsigned)SymbolRole::Definition; + DataConsumer.handleMacroOccurence(Name, MI, Roles, Loc); +} + +void IndexingContext::handleMacroUndefined(const IdentifierInfo &Name, + SourceLocation Loc, + const MacroInfo &MI) { + SymbolRoleSet Roles = (unsigned)SymbolRole::Reference; + DataConsumer.handleMacroOccurence(Name, MI, Roles, Loc, /*Undefined=*/true); +} + +void IndexingContext::handleMacroReference(const IdentifierInfo &Name, + SourceLocation Loc, + const MacroInfo &MI) { + SymbolRoleSet Roles = (unsigned)SymbolRole::Reference; + DataConsumer.handleMacroOccurence(Name, MI, Roles, Loc); +} Index: test/Index/Core/index-macros.c =================================================================== --- /dev/null +++ test/Index/Core/index-macros.c @@ -0,0 +1,12 @@ +// RUN: c-index-test core -print-source-symbols -- %s | FileCheck %s + +// CHECK: [[@LINE+1]]:9 | macro/C | X1 | c:index-macros.c@157@macro@X1 | Def | +#define X1 1 +// CHECK: [[@LINE+1]]:9 | macro/C | DEF | c:index-macros.c@251@macro@DEF | Def | +#define DEF(x) int x +// CHECK: [[@LINE+1]]:8 | macro/C | X1 | c:index-macros.c@157@macro@X1 | (undefined) | +#undef X1 + +// CHECK: [[@LINE+2]]:1 | macro/C | DEF | c:index-macros.c@251@macro@DEF | Ref | +// CHECK: [[@LINE+1]]:5 | variable/C | i | c:@i | i | Def | rel: 0 +DEF(i); Index: tools/c-index-test/core_main.cpp =================================================================== --- tools/c-index-test/core_main.cpp +++ tools/c-index-test/core_main.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Basic/LangOptions.h" #include "clang/CodeGen/ObjectFilePCHContainerOperations.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" @@ -16,6 +17,7 @@ #include "clang/Index/IndexDataConsumer.h" #include "clang/Index/USRGeneration.h" #include "clang/Index/CodegenNameGenerator.h" +#include "clang/Lex/Preprocessor.h" #include "clang/Serialization/ASTReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Signals.h" @@ -77,6 +79,7 @@ class PrintIndexDataConsumer : public IndexDataConsumer { raw_ostream &OS; std::unique_ptr CGNameGen; + std::shared_ptr PP; public: PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) { @@ -86,6 +89,10 @@ CGNameGen.reset(new CodegenNameGenerator(Ctx)); } + void setPreprocessor(std::shared_ptr PP) override { + this->PP = std::move(PP); + } + bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef Relations, SourceLocation Loc, ASTNodeInfo ASTNode) override { @@ -145,6 +152,42 @@ return true; } + + bool handleMacroOccurence(const IdentifierInfo &Name, const MacroInfo &MI, + SymbolRoleSet Roles, SourceLocation Loc, + bool Undefined) override { + assert(PP); + SourceManager &SM = PP->getSourceManager(); + + Loc = SM.getFileLoc(Loc); + FileID FID = SM.getFileID(Loc); + unsigned Line = SM.getLineNumber(FID, SM.getFileOffset(Loc)); + unsigned Col = SM.getColumnNumber(FID, SM.getFileOffset(Loc)); + OS << Line << ':' << Col << " | "; + + printSymbolInfo(getSymbolInfoForMacro(), OS); + OS << " | "; + + OS << Name.getName(); + OS << " | "; + + SmallString<256> USRBuf; + if (generateUSRForMacro(Name.getName(), MI.getDefinitionLoc(), SM, + USRBuf)) { + OS << ""; + } else { + OS << USRBuf; + } + + OS << " | "; + + if (Undefined) + OS << "(undefined)"; + else + printSymbolRoles(Roles, OS); + OS << " |\n"; + return true; + } }; } // anonymous namespace