123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363 |
- //===-- core_main.cpp - Core Index Tool testbed ---------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include "clang/Basic/LangOptions.h"
- #include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
- #include "clang/Frontend/ASTUnit.h"
- #include "clang/Frontend/CompilerInstance.h"
- #include "clang/Frontend/CompilerInvocation.h"
- #include "clang/Frontend/FrontendAction.h"
- #include "clang/Index/IndexingAction.h"
- #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/FileSystem.h"
- #include "llvm/Support/Signals.h"
- #include "llvm/Support/raw_ostream.h"
- #include "llvm/Support/PrettyStackTrace.h"
- using namespace clang;
- using namespace clang::index;
- using namespace llvm;
- extern "C" int indextest_core_main(int argc, const char **argv);
- namespace {
- enum class ActionType {
- None,
- PrintSourceSymbols,
- };
- namespace options {
- static cl::OptionCategory IndexTestCoreCategory("index-test-core options");
- static cl::opt<ActionType>
- Action(cl::desc("Action:"), cl::init(ActionType::None),
- cl::values(
- clEnumValN(ActionType::PrintSourceSymbols,
- "print-source-symbols", "Print symbols from source")),
- cl::cat(IndexTestCoreCategory));
- static cl::extrahelp MoreHelp(
- "\nAdd \"-- <compiler arguments>\" at the end to setup the compiler "
- "invocation\n"
- );
- static cl::opt<bool>
- DumpModuleImports("dump-imported-module-files",
- cl::desc("Print symbols and input files from imported modules"));
- static cl::opt<bool>
- IncludeLocals("include-locals", cl::desc("Print local symbols"));
- static cl::opt<std::string>
- ModuleFilePath("module-file",
- cl::desc("Path to module file to print symbols from"));
- static cl::opt<std::string>
- ModuleFormat("fmodule-format", cl::init("raw"),
- cl::desc("Container format for clang modules and PCH, 'raw' or 'obj'"));
- }
- } // anonymous namespace
- static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS);
- static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
- raw_ostream &OS);
- static void printSymbolNameAndUSR(const clang::Module *Mod, raw_ostream &OS);
- namespace {
- class PrintIndexDataConsumer : public IndexDataConsumer {
- raw_ostream &OS;
- std::unique_ptr<CodegenNameGenerator> CGNameGen;
- std::shared_ptr<Preprocessor> PP;
- public:
- PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) {
- }
- void initialize(ASTContext &Ctx) override {
- CGNameGen.reset(new CodegenNameGenerator(Ctx));
- }
- void setPreprocessor(std::shared_ptr<Preprocessor> PP) override {
- this->PP = std::move(PP);
- }
- bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
- ArrayRef<SymbolRelation> Relations,
- SourceLocation Loc, ASTNodeInfo ASTNode) override {
- ASTContext &Ctx = D->getASTContext();
- SourceManager &SM = Ctx.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(getSymbolInfo(D), OS);
- OS << " | ";
- printSymbolNameAndUSR(D, Ctx, OS);
- OS << " | ";
- if (CGNameGen->writeName(D, OS))
- OS << "<no-cgname>";
- OS << " | ";
- printSymbolRoles(Roles, OS);
- OS << " | ";
- OS << "rel: " << Relations.size() << '\n';
- for (auto &SymRel : Relations) {
- OS << '\t';
- printSymbolRoles(SymRel.Roles, OS);
- OS << " | ";
- printSymbolNameAndUSR(SymRel.RelatedSymbol, Ctx, OS);
- OS << '\n';
- }
- return true;
- }
- bool handleModuleOccurence(const ImportDecl *ImportD,
- const clang::Module *Mod,
- SymbolRoleSet Roles, SourceLocation Loc) override {
- ASTContext &Ctx = ImportD->getASTContext();
- SourceManager &SM = Ctx.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(getSymbolInfo(ImportD), OS);
- OS << " | ";
- printSymbolNameAndUSR(Mod, OS);
- OS << " | ";
- printSymbolRoles(Roles, OS);
- OS << " |\n";
- return true;
- }
- bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI,
- SymbolRoleSet Roles, SourceLocation Loc) 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(*MI), OS);
- OS << " | ";
- OS << Name->getName();
- OS << " | ";
- SmallString<256> USRBuf;
- if (generateUSRForMacro(Name->getName(), MI->getDefinitionLoc(), SM,
- USRBuf)) {
- OS << "<no-usr>";
- } else {
- OS << USRBuf;
- }
- OS << " | ";
- printSymbolRoles(Roles, OS);
- OS << " |\n";
- return true;
- }
- };
- } // anonymous namespace
- //===----------------------------------------------------------------------===//
- // Print Source Symbols
- //===----------------------------------------------------------------------===//
- static void dumpModuleFileInputs(serialization::ModuleFile &Mod,
- ASTReader &Reader,
- raw_ostream &OS) {
- OS << "---- Module Inputs ----\n";
- Reader.visitInputFiles(Mod, /*IncludeSystem=*/true, /*Complain=*/false,
- [&](const serialization::InputFile &IF, bool isSystem) {
- OS << (isSystem ? "system" : "user") << " | ";
- OS << IF.getFile()->getName() << '\n';
- });
- }
- static bool printSourceSymbols(const char *Executable,
- ArrayRef<const char *> Args,
- bool dumpModuleImports, bool indexLocals) {
- SmallVector<const char *, 4> ArgsWithProgName;
- ArgsWithProgName.push_back(Executable);
- ArgsWithProgName.append(Args.begin(), Args.end());
- IntrusiveRefCntPtr<DiagnosticsEngine>
- Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
- auto CInvok = createInvocationFromCommandLine(ArgsWithProgName, Diags);
- if (!CInvok)
- return true;
- raw_ostream &OS = outs();
- auto DataConsumer = std::make_shared<PrintIndexDataConsumer>(OS);
- IndexingOptions IndexOpts;
- IndexOpts.IndexFunctionLocals = indexLocals;
- std::unique_ptr<FrontendAction> IndexAction;
- IndexAction = createIndexingAction(DataConsumer, IndexOpts,
- /*WrappedAction=*/nullptr);
- auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
- std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
- std::move(CInvok), PCHContainerOps, Diags, IndexAction.get()));
- if (!Unit)
- return true;
- if (dumpModuleImports) {
- if (auto Reader = Unit->getASTReader()) {
- Reader->getModuleManager().visit([&](serialization::ModuleFile &Mod) -> bool {
- OS << "==== Module " << Mod.ModuleName << " ====\n";
- indexModuleFile(Mod, *Reader, *DataConsumer, IndexOpts);
- dumpModuleFileInputs(Mod, *Reader, OS);
- return true; // skip module dependencies.
- });
- }
- }
- return false;
- }
- static bool printSourceSymbolsFromModule(StringRef modulePath,
- StringRef format) {
- FileSystemOptions FileSystemOpts;
- auto pchContOps = std::make_shared<PCHContainerOperations>();
- // Register the support for object-file-wrapped Clang modules.
- pchContOps->registerReader(llvm::make_unique<ObjectFilePCHContainerReader>());
- auto pchRdr = pchContOps->getReaderOrNull(format);
- if (!pchRdr) {
- errs() << "unknown module format: " << format << '\n';
- return true;
- }
- IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
- CompilerInstance::createDiagnostics(new DiagnosticOptions());
- std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(
- modulePath, *pchRdr, ASTUnit::LoadASTOnly, Diags,
- FileSystemOpts, /*UseDebugInfo=*/false,
- /*OnlyLocalDecls=*/true, None,
- CaptureDiagsKind::None,
- /*AllowPCHWithCompilerErrors=*/true,
- /*UserFilesAreVolatile=*/false);
- if (!AU) {
- errs() << "failed to create TU for: " << modulePath << '\n';
- return true;
- }
- PrintIndexDataConsumer DataConsumer(outs());
- IndexingOptions IndexOpts;
- indexASTUnit(*AU, DataConsumer, IndexOpts);
- return false;
- }
- //===----------------------------------------------------------------------===//
- // Helper Utils
- //===----------------------------------------------------------------------===//
- static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS) {
- OS << getSymbolKindString(SymInfo.Kind);
- if (SymInfo.SubKind != SymbolSubKind::None)
- OS << '/' << getSymbolSubKindString(SymInfo.SubKind);
- if (SymInfo.Properties) {
- OS << '(';
- printSymbolProperties(SymInfo.Properties, OS);
- OS << ')';
- }
- OS << '/' << getSymbolLanguageString(SymInfo.Lang);
- }
- static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
- raw_ostream &OS) {
- if (printSymbolName(D, Ctx.getLangOpts(), OS)) {
- OS << "<no-name>";
- }
- OS << " | ";
- SmallString<256> USRBuf;
- if (generateUSRForDecl(D, USRBuf)) {
- OS << "<no-usr>";
- } else {
- OS << USRBuf;
- }
- }
- static void printSymbolNameAndUSR(const clang::Module *Mod, raw_ostream &OS) {
- assert(Mod);
- OS << Mod->getFullModuleName() << " | ";
- generateFullUSRForModule(Mod, OS);
- }
- //===----------------------------------------------------------------------===//
- // Command line processing.
- //===----------------------------------------------------------------------===//
- int indextest_core_main(int argc, const char **argv) {
- sys::PrintStackTraceOnErrorSignal(argv[0]);
- PrettyStackTraceProgram X(argc, argv);
- void *MainAddr = (void*) (intptr_t) indextest_core_main;
- std::string Executable = llvm::sys::fs::getMainExecutable(argv[0], MainAddr);
- assert(argv[1] == StringRef("core"));
- ++argv;
- --argc;
- std::vector<const char *> CompArgs;
- const char **DoubleDash = std::find(argv, argv + argc, StringRef("--"));
- if (DoubleDash != argv + argc) {
- CompArgs = std::vector<const char *>(DoubleDash + 1, argv + argc);
- argc = DoubleDash - argv;
- }
- cl::HideUnrelatedOptions(options::IndexTestCoreCategory);
- cl::ParseCommandLineOptions(argc, argv, "index-test-core");
- if (options::Action == ActionType::None) {
- errs() << "error: action required; pass '-help' for options\n";
- return 1;
- }
- if (options::Action == ActionType::PrintSourceSymbols) {
- if (!options::ModuleFilePath.empty()) {
- return printSourceSymbolsFromModule(options::ModuleFilePath,
- options::ModuleFormat);
- }
- if (CompArgs.empty()) {
- errs() << "error: missing compiler args; pass '-- <compiler arguments>'\n";
- return 1;
- }
- return printSourceSymbols(Executable.c_str(), CompArgs,
- options::DumpModuleImports,
- options::IncludeLocals);
- }
- return 0;
- }
|