brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.1 KiB · c67479f Raw
402 lines · cpp
1//===-- core_main.cpp - Core Index Tool testbed ---------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/AST/Mangle.h"10#include "clang/Basic/LangOptions.h"11#include "clang/Driver/CreateInvocationFromArgs.h"12#include "clang/Frontend/ASTUnit.h"13#include "clang/Frontend/CompilerInstance.h"14#include "clang/Frontend/CompilerInvocation.h"15#include "clang/Frontend/FrontendAction.h"16#include "clang/Frontend/Utils.h"17#include "clang/Index/IndexDataConsumer.h"18#include "clang/Index/IndexingAction.h"19#include "clang/Index/USRGeneration.h"20#include "clang/Lex/Preprocessor.h"21#include "clang/Serialization/ASTReader.h"22#include "clang/Serialization/ObjectFilePCHContainerReader.h"23#include "llvm/Support/CommandLine.h"24#include "llvm/Support/FileSystem.h"25#include "llvm/Support/PrettyStackTrace.h"26#include "llvm/Support/Program.h"27#include "llvm/Support/Signals.h"28#include "llvm/Support/StringSaver.h"29#include "llvm/Support/VirtualFileSystem.h"30#include "llvm/Support/raw_ostream.h"31 32using namespace clang;33using namespace clang::index;34using namespace llvm;35 36extern "C" int indextest_core_main(int argc, const char **argv);37extern "C" int indextest_perform_shell_execution(const char *command_line);38 39namespace {40 41enum class ActionType {42  None,43  PrintSourceSymbols,44};45 46namespace options {47 48static cl::OptionCategory IndexTestCoreCategory("index-test-core options");49 50static cl::opt<ActionType>51Action(cl::desc("Action:"), cl::init(ActionType::None),52       cl::values(53          clEnumValN(ActionType::PrintSourceSymbols,54                     "print-source-symbols", "Print symbols from source")),55       cl::cat(IndexTestCoreCategory));56 57static cl::extrahelp MoreHelp(58  "\nAdd \"-- <compiler arguments>\" at the end to setup the compiler "59  "invocation\n"60);61 62static cl::opt<bool>63DumpModuleImports("dump-imported-module-files",64               cl::desc("Print symbols and input files from imported modules"));65 66static cl::opt<bool>67IncludeLocals("include-locals", cl::desc("Print local symbols"));68 69static cl::opt<bool> IgnoreMacros("ignore-macros",70                                  cl::desc("Skip indexing macros"));71 72static cl::opt<std::string>73ModuleFilePath("module-file",74               cl::desc("Path to module file to print symbols from"));75static cl::opt<std::string>76  ModuleFormat("fmodule-format", cl::init("raw"),77        cl::desc("Container format for clang modules and PCH, 'raw' or 'obj'"));78 79}80} // anonymous namespace81 82static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS);83static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,84                                  raw_ostream &OS);85static void printSymbolNameAndUSR(const clang::Module *Mod, raw_ostream &OS);86 87namespace {88 89class PrintIndexDataConsumer : public IndexDataConsumer {90  raw_ostream &OS;91  std::unique_ptr<ASTNameGenerator> ASTNameGen;92  std::shared_ptr<Preprocessor> PP;93 94public:95  PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) {96  }97 98  void initialize(ASTContext &Ctx) override {99    ASTNameGen.reset(new ASTNameGenerator(Ctx));100  }101 102  void setPreprocessor(std::shared_ptr<Preprocessor> PP) override {103    this->PP = std::move(PP);104  }105 106  bool handleDeclOccurrence(const Decl *D, SymbolRoleSet Roles,107                            ArrayRef<SymbolRelation> Relations,108                            SourceLocation Loc, ASTNodeInfo ASTNode) override {109    ASTContext &Ctx = D->getASTContext();110    SourceManager &SM = Ctx.getSourceManager();111 112    Loc = SM.getFileLoc(Loc);113    FileID FID = SM.getFileID(Loc);114    unsigned Line = SM.getLineNumber(FID, SM.getFileOffset(Loc));115    unsigned Col = SM.getColumnNumber(FID, SM.getFileOffset(Loc));116    OS << Line << ':' << Col << " | ";117 118    printSymbolInfo(getSymbolInfo(D), OS);119    OS << " | ";120 121    printSymbolNameAndUSR(D, Ctx, OS);122    OS << " | ";123 124    if (ASTNameGen->writeName(D, OS))125      OS << "<no-cgname>";126    OS << " | ";127 128    printSymbolRoles(Roles, OS);129    OS << " | ";130 131    OS << "rel: " << Relations.size() << '\n';132 133    for (auto &SymRel : Relations) {134      OS << '\t';135      printSymbolRoles(SymRel.Roles, OS);136      OS << " | ";137      printSymbolNameAndUSR(SymRel.RelatedSymbol, Ctx, OS);138      OS << '\n';139    }140 141    return true;142  }143 144  bool handleModuleOccurrence(const ImportDecl *ImportD,145                              const clang::Module *Mod, SymbolRoleSet Roles,146                              SourceLocation Loc) override {147    ASTContext &Ctx = ImportD->getASTContext();148    SourceManager &SM = Ctx.getSourceManager();149 150    Loc = SM.getFileLoc(Loc);151    FileID FID = SM.getFileID(Loc);152    unsigned Line = SM.getLineNumber(FID, SM.getFileOffset(Loc));153    unsigned Col = SM.getColumnNumber(FID, SM.getFileOffset(Loc));154    OS << Line << ':' << Col << " | ";155 156    printSymbolInfo(getSymbolInfo(ImportD), OS);157    OS << " | ";158 159    printSymbolNameAndUSR(Mod, OS);160    OS << " | ";161 162    printSymbolRoles(Roles, OS);163    OS << " |\n";164 165    return true;166  }167 168  bool handleMacroOccurrence(const IdentifierInfo *Name, const MacroInfo *MI,169                             SymbolRoleSet Roles, SourceLocation Loc) override {170    assert(PP);171    SourceManager &SM = PP->getSourceManager();172 173    Loc = SM.getFileLoc(Loc);174    FileID FID = SM.getFileID(Loc);175    unsigned Line = SM.getLineNumber(FID, SM.getFileOffset(Loc));176    unsigned Col = SM.getColumnNumber(FID, SM.getFileOffset(Loc));177    OS << Line << ':' << Col << " | ";178 179    printSymbolInfo(getSymbolInfoForMacro(*MI), OS);180    OS << " | ";181 182    OS << Name->getName();183    OS << " | ";184 185    SmallString<256> USRBuf;186    if (generateUSRForMacro(Name->getName(), MI->getDefinitionLoc(), SM,187                            USRBuf)) {188      OS << "<no-usr>";189    } else {190      OS << USRBuf;191    }192    OS << " | ";193 194    printSymbolRoles(Roles, OS);195    OS << " |\n";196    return true;197  }198};199 200} // anonymous namespace201 202//===----------------------------------------------------------------------===//203// Print Source Symbols204//===----------------------------------------------------------------------===//205 206static void dumpModuleFileInputs(serialization::ModuleFile &Mod,207                                 ASTReader &Reader,208                                 raw_ostream &OS) {209  OS << "---- Module Inputs ----\n";210  Reader.visitInputFiles(Mod, /*IncludeSystem=*/true, /*Complain=*/false,211                        [&](const serialization::InputFile &IF, bool isSystem) {212    OS << (isSystem ? "system" : "user") << " | ";213    OS << IF.getFile()->getName() << '\n';214  });215}216 217static bool printSourceSymbols(const char *Executable,218                               ArrayRef<const char *> Args,219                               bool dumpModuleImports, bool indexLocals,220                               bool ignoreMacros) {221  SmallVector<const char *, 4> ArgsWithProgName;222  ArgsWithProgName.push_back(Executable);223  ArgsWithProgName.append(Args.begin(), Args.end());224  auto DiagOpts = std::make_shared<DiagnosticOptions>();225  IntrusiveRefCntPtr<DiagnosticsEngine> Diags(226      CompilerInstance::createDiagnostics(*llvm::vfs::getRealFileSystem(),227                                          *DiagOpts));228  CreateInvocationOptions CIOpts;229  CIOpts.Diags = Diags;230  CIOpts.ProbePrecompiled = true; // FIXME: historical default. Needed?231  auto CInvok = createInvocation(ArgsWithProgName, std::move(CIOpts));232  if (!CInvok)233    return true;234 235  raw_ostream &OS = outs();236  auto DataConsumer = std::make_shared<PrintIndexDataConsumer>(OS);237  IndexingOptions IndexOpts;238  IndexOpts.IndexFunctionLocals = indexLocals;239  IndexOpts.IndexMacros = !ignoreMacros;240  IndexOpts.IndexMacrosInPreprocessor = !ignoreMacros;241  std::unique_ptr<FrontendAction> IndexAction =242      createIndexingAction(DataConsumer, IndexOpts);243 244  auto PCHContainerOps = std::make_shared<PCHContainerOperations>();245  std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(246      std::move(CInvok), PCHContainerOps, DiagOpts, Diags, IndexAction.get()));247 248  if (!Unit)249    return true;250 251  if (dumpModuleImports) {252    if (auto Reader = Unit->getASTReader()) {253      Reader->getModuleManager().visit([&](serialization::ModuleFile &Mod) -> bool {254        OS << "==== Module " << Mod.ModuleName << " ====\n";255        indexModuleFile(Mod, *Reader, *DataConsumer, IndexOpts);256        dumpModuleFileInputs(Mod, *Reader, OS);257        return true; // skip module dependencies.258      });259    }260  }261 262  return false;263}264 265static bool printSourceSymbolsFromModule(StringRef modulePath,266                                         StringRef format) {267  FileSystemOptions FileSystemOpts;268  auto pchContOps = std::make_shared<PCHContainerOperations>();269  // Register the support for object-file-wrapped Clang modules.270  pchContOps->registerReader(std::make_unique<ObjectFilePCHContainerReader>());271  auto pchRdr = pchContOps->getReaderOrNull(format);272  if (!pchRdr) {273    errs() << "unknown module format: " << format << '\n';274    return true;275  }276 277  HeaderSearchOptions HSOpts;278 279  auto VFS = llvm::vfs::getRealFileSystem();280 281  auto DiagOpts = std::make_shared<DiagnosticOptions>();282  IntrusiveRefCntPtr<DiagnosticsEngine> Diags =283      CompilerInstance::createDiagnostics(*VFS, *DiagOpts);284  std::unique_ptr<ASTUnit> AU = ASTUnit::LoadFromASTFile(285      modulePath, *pchRdr, ASTUnit::LoadASTOnly, VFS, DiagOpts, Diags,286      FileSystemOpts, HSOpts, /*LangOpts=*/nullptr,287      /*OnlyLocalDecls=*/true, CaptureDiagsKind::None,288      /*AllowASTWithCompilerErrors=*/true,289      /*UserFilesAreVolatile=*/false);290  if (!AU) {291    errs() << "failed to create TU for: " << modulePath << '\n';292    return true;293  }294 295  PrintIndexDataConsumer DataConsumer(outs());296  IndexingOptions IndexOpts;297  indexASTUnit(*AU, DataConsumer, IndexOpts);298 299  return false;300}301 302//===----------------------------------------------------------------------===//303// Helper Utils304//===----------------------------------------------------------------------===//305 306static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS) {307  OS << getSymbolKindString(SymInfo.Kind);308  if (SymInfo.SubKind != SymbolSubKind::None)309    OS << '/' << getSymbolSubKindString(SymInfo.SubKind);310  if (SymInfo.Properties) {311    OS << '(';312    printSymbolProperties(SymInfo.Properties, OS);313    OS << ')';314  }315  OS << '/' << getSymbolLanguageString(SymInfo.Lang);316}317 318static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,319                                  raw_ostream &OS) {320  if (printSymbolName(D, Ctx.getLangOpts(), OS)) {321    OS << "<no-name>";322  }323  OS << " | ";324 325  SmallString<256> USRBuf;326  if (generateUSRForDecl(D, USRBuf)) {327    OS << "<no-usr>";328  } else {329    OS << USRBuf;330  }331}332 333static void printSymbolNameAndUSR(const clang::Module *Mod, raw_ostream &OS) {334  assert(Mod);335  OS << Mod->getFullModuleName() << " | ";336  generateFullUSRForModule(Mod, OS);337}338 339//===----------------------------------------------------------------------===//340// Command line processing.341//===----------------------------------------------------------------------===//342 343int indextest_core_main(int argc, const char **argv) {344  sys::PrintStackTraceOnErrorSignal(argv[0]);345  PrettyStackTraceProgram X(argc, argv);346  void *MainAddr = (void*) (intptr_t) indextest_core_main;347  std::string Executable = llvm::sys::fs::getMainExecutable(argv[0], MainAddr);348 349  assert(argv[1] == StringRef("core"));350  ++argv;351  --argc;352 353  std::vector<const char *> CompArgs;354  const char **DoubleDash = std::find(argv, argv + argc, StringRef("--"));355  if (DoubleDash != argv + argc) {356    CompArgs = std::vector<const char *>(DoubleDash + 1, argv + argc);357    argc = DoubleDash - argv;358  }359 360  cl::HideUnrelatedOptions(options::IndexTestCoreCategory);361  cl::ParseCommandLineOptions(argc, argv, "index-test-core");362 363  if (options::Action == ActionType::None) {364    errs() << "error: action required; pass '-help' for options\n";365    return 1;366  }367 368  if (options::Action == ActionType::PrintSourceSymbols) {369    if (!options::ModuleFilePath.empty()) {370      return printSourceSymbolsFromModule(options::ModuleFilePath,371                                          options::ModuleFormat);372    }373    if (CompArgs.empty()) {374      errs() << "error: missing compiler args; pass '-- <compiler arguments>'\n";375      return 1;376    }377    return printSourceSymbols(Executable.c_str(), CompArgs,378                              options::DumpModuleImports,379                              options::IncludeLocals, options::IgnoreMacros);380  }381 382  return 0;383}384 385//===----------------------------------------------------------------------===//386// Utility functions387//===----------------------------------------------------------------------===//388 389int indextest_perform_shell_execution(const char *command_line) {390  BumpPtrAllocator Alloc;391  llvm::StringSaver Saver(Alloc);392  SmallVector<const char *, 4> Args;393  llvm::cl::TokenizeGNUCommandLine(command_line, Saver, Args);394  auto Program = llvm::sys::findProgramByName(Args[0]);395  if (std::error_code ec = Program.getError()) {396    llvm::errs() << "command not found: " << Args[0] << "\n";397    return ec.value();398  }399  SmallVector<StringRef, 8> execArgs(Args.begin(), Args.end());400  return llvm::sys::ExecuteAndWait(*Program, execArgs);401}402