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