return Info;
}
+
+void index::applyForEachSymbolRole(SymbolRoleSet Roles,
+ llvm::function_ref<void(SymbolRole)> Fn) {
+#define APPLY_FOR_ROLE(Role) \
+ if (Roles & (unsigned)SymbolRole::Role) \
+ Fn(SymbolRole::Role)
+
+ APPLY_FOR_ROLE(Declaration);
+ APPLY_FOR_ROLE(Definition);
+ APPLY_FOR_ROLE(Reference);
+ APPLY_FOR_ROLE(Read);
+ APPLY_FOR_ROLE(Write);
+ APPLY_FOR_ROLE(Call);
+ APPLY_FOR_ROLE(Dynamic);
+ APPLY_FOR_ROLE(AddressOf);
+ APPLY_FOR_ROLE(Implicit);
+ APPLY_FOR_ROLE(RelationChildOf);
+ APPLY_FOR_ROLE(RelationBaseOf);
+ APPLY_FOR_ROLE(RelationOverrideOf);
+ APPLY_FOR_ROLE(RelationReceivedBy);
+
+#undef APPLY_FOR_ROLE
+}
+
+void index::printSymbolRoles(SymbolRoleSet Roles, raw_ostream &OS) {
+ bool VisitedOnce = false;
+ applyForEachSymbolRole(Roles, [&](SymbolRole Role) {
+ if (VisitedOnce)
+ OS << '/';
+ else
+ VisitedOnce = true;
+ switch (Role) {
+ case SymbolRole::Declaration: OS << "Decl"; break;
+ case SymbolRole::Definition: OS << "Def"; break;
+ case SymbolRole::Reference: OS << "Ref"; break;
+ case SymbolRole::Read: OS << "Read"; break;
+ case SymbolRole::Write: OS << "Writ"; break;
+ case SymbolRole::Call: OS << "Call"; break;
+ case SymbolRole::Dynamic: OS << "Dyn"; break;
+ case SymbolRole::AddressOf: OS << "Addr"; break;
+ case SymbolRole::Implicit: OS << "Impl"; break;
+ case SymbolRole::RelationChildOf: OS << "RelChild"; break;
+ case SymbolRole::RelationBaseOf: OS << "RelBase"; break;
+ case SymbolRole::RelationOverrideOf: OS << "RelOver"; break;
+ case SymbolRole::RelationReceivedBy: OS << "RelRec"; break;
+ }
+ });
+}
+
+StringRef index::getSymbolKindString(SymbolKind K) {
+ switch (K) {
+ case SymbolKind::Unknown: return "<unknown>";
+ case SymbolKind::Module: return "module";
+ case SymbolKind::Macro: return "macro";
+ case SymbolKind::Enum: return "enum";
+ case SymbolKind::Struct: return "struct";
+ case SymbolKind::Union: return "union";
+ case SymbolKind::Typedef: return "typedef";
+ case SymbolKind::Function: return "function";
+ case SymbolKind::Variable: return "variable";
+ case SymbolKind::Field: return "field";
+ case SymbolKind::EnumConstant: return "enumerator";
+ case SymbolKind::ObjCClass: return "objc-class";
+ case SymbolKind::ObjCProtocol: return "objc-protocol";
+ case SymbolKind::ObjCCategory: return "objc-category";
+ case SymbolKind::ObjCInstanceMethod: return "objc-instance-method";
+ case SymbolKind::ObjCClassMethod: return "objc-class-method";
+ case SymbolKind::ObjCProperty: return "objc-property";
+ case SymbolKind::ObjCIvar: return "objc-ivar";
+ case SymbolKind::CXXClass: return "c++-class";
+ case SymbolKind::CXXNamespace: return "namespace";
+ case SymbolKind::CXXNamespaceAlias: return "namespace-alias";
+ case SymbolKind::CXXStaticVariable: return "c++-static-var";
+ case SymbolKind::CXXStaticMethod: return "c++-static-method";
+ case SymbolKind::CXXInstanceMethod: return "c++-instance-method";
+ case SymbolKind::CXXConstructor: return "constructor";
+ case SymbolKind::CXXDestructor: return "destructor";
+ case SymbolKind::CXXConversionFunction: return "coversion-func";
+ case SymbolKind::CXXTypeAlias: return "type-alias";
+ case SymbolKind::CXXInterface: return "c++-__interface";
+ }
+}
+
+StringRef index::getTemplateKindStr(SymbolCXXTemplateKind TK) {
+ switch (TK) {
+ case SymbolCXXTemplateKind::NonTemplate: return "NT";
+ case SymbolCXXTemplateKind::Template : return "T";
+ case SymbolCXXTemplateKind::TemplatePartialSpecialization : return "TPS";
+ case SymbolCXXTemplateKind::TemplateSpecialization: return "TS";
+ }
+}
+
+StringRef index::getSymbolLanguageString(SymbolLanguage K) {
+ switch (K) {
+ case SymbolLanguage::C: return "C";
+ case SymbolLanguage::ObjC: return "ObjC";
+ case SymbolLanguage::CXX: return "C++";
+ }
+}
# include <unistd.h>
#endif
+extern int indextest_core_main(int argc, const char **argv);
+
/******************************************************************************/
/* Utility functions. */
/******************************************************************************/
* size). */
typedef struct thread_info {
+ int (*main_func)(int argc, const char **argv);
int argc;
const char **argv;
int result;
} thread_info;
void thread_runner(void *client_data_v) {
thread_info *client_data = client_data_v;
- client_data->result = cindextest_main(client_data->argc, client_data->argv);
+ client_data->result = client_data->main_func(client_data->argc,
+ client_data->argv);
}
static void flush_atexit(void) {
LIBXML_TEST_VERSION
#endif
- if (getenv("CINDEXTEST_NOTHREADS"))
- return cindextest_main(argc, argv);
-
+ client_data.main_func = cindextest_main;
client_data.argc = argc;
client_data.argv = argv;
+
+ if (argc > 1 && strcmp(argv[1], "core") == 0) {
+ client_data.main_func = indextest_core_main;
+ --client_data.argc;
+ ++client_data.argv;
+ }
+
+ if (getenv("CINDEXTEST_NOTHREADS"))
+ return client_data.main_func(client_data.argc, client_data.argv);
+
clang_executeOnThread(thread_runner, &client_data, 0);
return client_data.result;
}
--- /dev/null
+//===-- core_main.cpp - Core Index Tool testbed ---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#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 "llvm/Support/CommandLine.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"),
+ clEnumValEnd),
+ cl::cat(IndexTestCoreCategory));
+
+static cl::extrahelp MoreHelp(
+ "\nAdd \"-- <compiler arguments>\" at the end to setup the compiler "
+ "invocation\n"
+);
+
+}
+} // anonymous namespace
+
+static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS);
+static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
+ raw_ostream &OS);
+
+namespace {
+
+class PrintIndexDataConsumer : public IndexDataConsumer {
+ raw_ostream &OS;
+
+public:
+ PrintIndexDataConsumer(raw_ostream &OS) : OS(OS) {
+ }
+
+ bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles,
+ ArrayRef<SymbolRelation> Relations,
+ FileID FID, unsigned Offset,
+ ASTNodeInfo ASTNode) override {
+ ASTContext &Ctx = D->getASTContext();
+ SourceManager &SM = Ctx.getSourceManager();
+
+ unsigned Line = SM.getLineNumber(FID, Offset);
+ unsigned Col = SM.getColumnNumber(FID, Offset);
+ OS << Line << ':' << Col << " | ";
+
+ printSymbolInfo(getSymbolInfo(D), OS);
+ OS << " | ";
+
+ printSymbolNameAndUSR(D, Ctx, OS);
+ 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;
+ }
+};
+
+} // anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Print Source Symbols
+//===----------------------------------------------------------------------===//
+
+static bool printSourceSymbols(ArrayRef<const char *> Args) {
+ SmallVector<const char *, 4> ArgsWithProgName;
+ ArgsWithProgName.push_back("clang");
+ ArgsWithProgName.append(Args.begin(), Args.end());
+ IntrusiveRefCntPtr<DiagnosticsEngine>
+ Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
+ IntrusiveRefCntPtr<CompilerInvocation>
+ CInvok(createInvocationFromCommandLine(ArgsWithProgName, Diags));
+ if (!CInvok)
+ return true;
+
+ auto DataConsumer = std::make_shared<PrintIndexDataConsumer>(outs());
+ IndexingOptions IndexOpts;
+ std::unique_ptr<FrontendAction> IndexAction;
+ IndexAction = createIndexingAction(DataConsumer, IndexOpts);
+
+ auto PCHContainerOps = std::make_shared<PCHContainerOperations>();
+ ASTUnit *Unit =
+ ASTUnit::LoadFromCompilerInvocationAction(CInvok.get(), PCHContainerOps,
+ Diags, IndexAction.get());
+
+ if (!Unit)
+ return true;
+
+ return false;
+}
+
+//===----------------------------------------------------------------------===//
+// Helper Utils
+//===----------------------------------------------------------------------===//
+
+static void printSymbolInfo(SymbolInfo SymInfo, raw_ostream &OS) {
+ OS << getSymbolKindString(SymInfo.Kind);
+ if (SymInfo.TemplateKind != SymbolCXXTemplateKind::NonTemplate) {
+ OS << '-' << getTemplateKindStr(SymInfo.TemplateKind);
+ }
+ OS << '/' << getSymbolLanguageString(SymInfo.Lang);
+}
+
+static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx,
+ raw_ostream &OS) {
+ if (auto *ND = dyn_cast<NamedDecl>(D)) {
+ PrintingPolicy PrintPolicy(Ctx.getLangOpts());
+ ND->getDeclName().print(OS, PrintPolicy);
+ } else {
+ OS << "<no-name>";
+ }
+ OS << " | ";
+
+ SmallString<256> USRBuf;
+ if (generateUSRForDecl(D, USRBuf)) {
+ OS << "<no-usr>";
+ } else {
+ OS << USRBuf;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Command line processing.
+//===----------------------------------------------------------------------===//
+
+int indextest_core_main(int argc, const char **argv) {
+ sys::PrintStackTraceOnErrorSignal();
+ PrettyStackTraceProgram X(argc, argv);
+
+ std::vector<const char *> CompArgs;
+ const char *const *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 (CompArgs.empty()) {
+ errs() << "error: missing compiler args; pass '-- <compiler arguments>'\n";
+ return 1;
+ }
+ return printSourceSymbols(CompArgs);
+ }
+
+ return 0;
+}