1 //===-- core_main.cpp - Core Index Tool testbed ---------------------------===// 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/Frontend/ASTUnit.h" 11 #include "clang/Frontend/CompilerInstance.h" 12 #include "clang/Frontend/CompilerInvocation.h" 13 #include "clang/Frontend/FrontendAction.h" 14 #include "clang/Index/IndexingAction.h" 15 #include "clang/Index/IndexDataConsumer.h" 16 #include "clang/Index/USRGeneration.h" 17 #include "clang/Index/CodegenNameGenerator.h" 18 #include "llvm/Support/CommandLine.h" 19 #include "llvm/Support/Signals.h" 20 #include "llvm/Support/raw_ostream.h" 21 #include "llvm/Support/PrettyStackTrace.h" 22 23 using namespace clang; 24 using namespace clang::index; 25 using namespace llvm; 26 27 extern "C" int indextest_core_main(int argc, const char **argv); 28 29 namespace { 30 31 enum class ActionType { 32 None, 33 PrintSourceSymbols, 34 }; 35 36 namespace options { 37 38 static cl::OptionCategory IndexTestCoreCategory("index-test-core options"); 39 40 static cl::opt<ActionType> 41 Action(cl::desc("Action:"), cl::init(ActionType::None), 42 cl::values( 43 clEnumValN(ActionType::PrintSourceSymbols, 44 "print-source-symbols", "Print symbols from source"), 45 clEnumValEnd), 46 cl::cat(IndexTestCoreCategory)); 47 48 static cl::extrahelp MoreHelp( 49 "\nAdd \"-- <compiler arguments>\" at the end to setup the compiler " 50 "invocation\n" 51 ); 52 53 } 54 } // anonymous namespace 55 56 static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS); 57 static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx, 58 raw_ostream &OS); 59 60 namespace { 61 62 class PrintIndexDataConsumer : public IndexDataConsumer { 63 raw_ostream &OS; 64 std::unique_ptr<CodegenNameGenerator> CGNameGen; 65 66 public: 67 PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) { 68 } 69 70 void initialize(ASTContext &Ctx) override { 71 CGNameGen.reset(new CodegenNameGenerator(Ctx)); 72 } 73 74 bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, 75 ArrayRef<SymbolRelation> Relations, 76 FileID FID, unsigned Offset, 77 ASTNodeInfo ASTNode) override { 78 ASTContext &Ctx = D->getASTContext(); 79 SourceManager &SM = Ctx.getSourceManager(); 80 81 unsigned Line = SM.getLineNumber(FID, Offset); 82 unsigned Col = SM.getColumnNumber(FID, Offset); 83 OS << Line << ':' << Col << " | "; 84 85 printSymbolInfo(getSymbolInfo(D), OS); 86 OS << " | "; 87 88 printSymbolNameAndUSR(D, Ctx, OS); 89 OS << " | "; 90 91 if (CGNameGen->writeName(D, OS)) 92 OS << "<no-cgname>"; 93 OS << " | "; 94 95 printSymbolRoles(Roles, OS); 96 OS << " | "; 97 98 OS << "rel: " << Relations.size() << '\n'; 99 100 for (auto &SymRel : Relations) { 101 OS << '\t'; 102 printSymbolRoles(SymRel.Roles, OS); 103 OS << " | "; 104 printSymbolNameAndUSR(SymRel.RelatedSymbol, Ctx, OS); 105 OS << '\n'; 106 } 107 108 return true; 109 } 110 111 bool handleModuleOccurence(const ImportDecl *ImportD, SymbolRoleSet Roles, 112 FileID FID, unsigned Offset) override { 113 ASTContext &Ctx = ImportD->getASTContext(); 114 SourceManager &SM = Ctx.getSourceManager(); 115 116 unsigned Line = SM.getLineNumber(FID, Offset); 117 unsigned Col = SM.getColumnNumber(FID, Offset); 118 OS << Line << ':' << Col << " | "; 119 120 printSymbolInfo(getSymbolInfo(ImportD), OS); 121 OS << " | "; 122 123 OS << ImportD->getImportedModule()->getFullModuleName() << " | "; 124 125 printSymbolRoles(Roles, OS); 126 OS << " |\n"; 127 128 return true; 129 } 130 }; 131 132 } // anonymous namespace 133 134 //===----------------------------------------------------------------------===// 135 // Print Source Symbols 136 //===----------------------------------------------------------------------===// 137 138 static bool printSourceSymbols(ArrayRef<const char *> Args) { 139 SmallVector<const char *, 4> ArgsWithProgName; 140 ArgsWithProgName.push_back("clang"); 141 ArgsWithProgName.append(Args.begin(), Args.end()); 142 IntrusiveRefCntPtr<DiagnosticsEngine> 143 Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions)); 144 IntrusiveRefCntPtr<CompilerInvocation> 145 CInvok(createInvocationFromCommandLine(ArgsWithProgName, Diags)); 146 if (!CInvok) 147 return true; 148 149 auto DataConsumer = std::make_shared<PrintIndexDataConsumer>(outs()); 150 IndexingOptions IndexOpts; 151 std::unique_ptr<FrontendAction> IndexAction; 152 IndexAction = createIndexingAction(DataConsumer, IndexOpts, 153 /*WrappedAction=*/nullptr); 154 155 auto PCHContainerOps = std::make_shared<PCHContainerOperations>(); 156 std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction( 157 CInvok.get(), PCHContainerOps, Diags, IndexAction.get())); 158 159 if (!Unit) 160 return true; 161 162 return false; 163 } 164 165 //===----------------------------------------------------------------------===// 166 // Helper Utils 167 //===----------------------------------------------------------------------===// 168 169 static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS) { 170 OS << getSymbolKindString(SymInfo.Kind); 171 if (SymInfo.SubKinds) { 172 OS << '('; 173 printSymbolSubKinds(SymInfo.SubKinds, OS); 174 OS << ')'; 175 } 176 OS << '/' << getSymbolLanguageString(SymInfo.Lang); 177 } 178 179 static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx, 180 raw_ostream &OS) { 181 if (printSymbolName(D, Ctx.getLangOpts(), OS)) { 182 OS << "<no-name>"; 183 } 184 OS << " | "; 185 186 SmallString<256> USRBuf; 187 if (generateUSRForDecl(D, USRBuf)) { 188 OS << "<no-usr>"; 189 } else { 190 OS << USRBuf; 191 } 192 } 193 194 //===----------------------------------------------------------------------===// 195 // Command line processing. 196 //===----------------------------------------------------------------------===// 197 198 int indextest_core_main(int argc, const char **argv) { 199 sys::PrintStackTraceOnErrorSignal(argv[0]); 200 PrettyStackTraceProgram X(argc, argv); 201 202 assert(argv[1] == StringRef("core")); 203 ++argv; 204 --argc; 205 206 std::vector<const char *> CompArgs; 207 const char **DoubleDash = std::find(argv, argv + argc, StringRef("--")); 208 if (DoubleDash != argv + argc) { 209 CompArgs = std::vector<const char *>(DoubleDash + 1, argv + argc); 210 argc = DoubleDash - argv; 211 } 212 213 cl::HideUnrelatedOptions(options::IndexTestCoreCategory); 214 cl::ParseCommandLineOptions(argc, argv, "index-test-core"); 215 216 if (options::Action == ActionType::None) { 217 errs() << "error: action required; pass '-help' for options\n"; 218 return 1; 219 } 220 221 if (options::Action == ActionType::PrintSourceSymbols) { 222 if (CompArgs.empty()) { 223 errs() << "error: missing compiler args; pass '-- <compiler arguments>'\n"; 224 return 1; 225 } 226 return printSourceSymbols(CompArgs); 227 } 228 229 return 0; 230 } 231