Index: include/clang/Basic/AllDiagnostics.h =================================================================== --- include/clang/Basic/AllDiagnostics.h +++ include/clang/Basic/AllDiagnostics.h @@ -21,6 +21,7 @@ #include "clang/CrossTU/CrossTUDiagnostic.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Index/IndexDiagnostic.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Sema/SemaDiagnostic.h" Index: include/clang/Basic/CMakeLists.txt =================================================================== --- include/clang/Basic/CMakeLists.txt +++ include/clang/Basic/CMakeLists.txt @@ -12,6 +12,7 @@ clang_diag_gen(CrossTU) clang_diag_gen(Driver) clang_diag_gen(Frontend) +clang_diag_gen(Index) clang_diag_gen(Lex) clang_diag_gen(Parse) clang_diag_gen(Refactoring) Index: include/clang/Basic/Diagnostic.td =================================================================== --- include/clang/Basic/Diagnostic.td +++ include/clang/Basic/Diagnostic.td @@ -136,6 +136,7 @@ include "DiagnosticCrossTUKinds.td" include "DiagnosticDriverKinds.td" include "DiagnosticFrontendKinds.td" +include "DiagnosticIndexKinds.td" include "DiagnosticLexKinds.td" include "DiagnosticParseKinds.td" include "DiagnosticRefactoringKinds.td" Index: include/clang/Basic/DiagnosticGroups.td =================================================================== --- include/clang/Basic/DiagnosticGroups.td +++ include/clang/Basic/DiagnosticGroups.td @@ -327,6 +327,7 @@ def ModuleBuild : DiagGroup<"module-build">; def ModuleConflict : DiagGroup<"module-conflict">; def ModuleFileExtension : DiagGroup<"module-file-extension">; +def IndexStore : DiagGroup<"index-store">; def NewlineEOF : DiagGroup<"newline-eof">; def Nullability : DiagGroup<"nullability">; def NullabilityDeclSpec : DiagGroup<"nullability-declspec">; Index: include/clang/Basic/DiagnosticIDs.h =================================================================== --- include/clang/Basic/DiagnosticIDs.h +++ include/clang/Basic/DiagnosticIDs.h @@ -40,6 +40,7 @@ DIAG_SIZE_SEMA = 3500, DIAG_SIZE_ANALYSIS = 100, DIAG_SIZE_REFACTORING = 1000, + DIAG_SIZE_INDEX = 100, }; // Start position for diagnostics. enum { @@ -55,7 +56,8 @@ DIAG_START_SEMA = DIAG_START_CROSSTU + DIAG_SIZE_COMMENT, DIAG_START_ANALYSIS = DIAG_START_SEMA + DIAG_SIZE_SEMA, DIAG_START_REFACTORING = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS, - DIAG_UPPER_LIMIT = DIAG_START_REFACTORING + DIAG_SIZE_REFACTORING + DIAG_START_INDEX = DIAG_START_REFACTORING + DIAG_SIZE_REFACTORING, + DIAG_UPPER_LIMIT = DIAG_START_INDEX + DIAG_SIZE_INDEX, }; class CustomDiagInfo; Index: include/clang/Basic/DiagnosticIndexKinds.td =================================================================== --- /dev/null +++ include/clang/Basic/DiagnosticIndexKinds.td @@ -0,0 +1,31 @@ +//==--- DiagnosticIndexKinds.td - indexing diagnostics --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Indexing Diagnostics +//===----------------------------------------------------------------------===// + +let Component = "Index" in { + +let CategoryName = "Index Store Issue" in { + +def err_index_store_dir_create_failed : Error<"failed creating the index store " + "directory: %0">; +def err_index_store_file_status_failed : Error<"failed file status check: %0">; +def err_index_store_record_write_failed : Error<"failed writing record '%0': " + "%1">; +def err_index_store_unit_write_failed : Error<"failed writing unit data: %0">; + +def remark_index_producing_module_file_data : Remark<"producing index data for " + "module file '%0'">, + InGroup; + +} + +} // end of Indexing diagnostics Index: include/clang/Driver/Job.h =================================================================== --- include/clang/Driver/Job.h +++ include/clang/Driver/Job.h @@ -34,9 +34,11 @@ struct CrashReportInfo { StringRef Filename; StringRef VFSPath; + StringRef IndexStorePath; - CrashReportInfo(StringRef Filename, StringRef VFSPath) - : Filename(Filename), VFSPath(VFSPath) {} + CrashReportInfo(StringRef Filename, StringRef VFSPath, + StringRef IndexStorePath) + : Filename(Filename), VFSPath(VFSPath), IndexStorePath(IndexStorePath) {} }; /// Command - An executable path/name and argument vector to Index: include/clang/Driver/Options.td =================================================================== --- include/clang/Driver/Options.td +++ include/clang/Driver/Options.td @@ -324,6 +324,13 @@ def : Joined<["-"], "objcmt-white-list-dir-path=">, Flags<[CC1Option]>, Alias; +def index_store_path : Separate<["-"], "index-store-path">, Flags<[CC1Option]>, + HelpText<"Enable indexing with the specified data store path">; +def index_ignore_system_symbols : Flag<["-"], "index-ignore-system-symbols">, Flags<[CC1Option]>, + HelpText<"Ignore symbols from system headers">; +def index_record_codegen_name : Flag<["-"], "index-record-codegen-name">, Flags<[CC1Option]>, + HelpText<"Record the codegen name for symbols">; + // Make sure all other -ccc- options are rejected. def ccc_ : Joined<["-"], "ccc-">, Group, Flags<[Unsupported]>; Index: include/clang/Frontend/CompilerInstance.h =================================================================== --- include/clang/Frontend/CompilerInstance.h +++ include/clang/Frontend/CompilerInstance.h @@ -183,6 +183,14 @@ /// The list of active output files. std::list OutputFiles; + typedef std::function( + const FrontendOptions &Opts, std::unique_ptr Action)> + ActionWrapperTy; + + /// \brief An optional callback function used to wrap any + /// GenerateModuleActions created and executed when loading modules. + ActionWrapperTy GenModuleActionWrapper; + CompilerInstance(const CompilerInstance &) = delete; void operator=(const CompilerInstance &) = delete; public: @@ -447,7 +455,7 @@ return *PP; } - std::shared_ptr getPreprocessorPtr() { return PP; } + std::shared_ptr getPreprocessorPtr() const { return PP; } void resetAndLeakPreprocessor() { BuryPointer(new std::shared_ptr(PP)); @@ -796,6 +804,14 @@ bool lookupMissingImports(StringRef Name, SourceLocation TriggerLoc) override; + void setGenModuleActionWrapper(ActionWrapperTy Wrapper) { + GenModuleActionWrapper = Wrapper; + }; + + ActionWrapperTy getGenModuleActionWrapper() const { + return GenModuleActionWrapper; + } + void addDependencyCollector(std::shared_ptr Listener) { DependencyCollectors.push_back(std::move(Listener)); } Index: include/clang/Frontend/FrontendOptions.h =================================================================== --- include/clang/Frontend/FrontendOptions.h +++ include/clang/Frontend/FrontendOptions.h @@ -259,6 +259,13 @@ std::string MTMigrateDir; std::string ARCMTMigrateReportOut; + /// The path to write index data to + std::string IndexStorePath; + /// Whether to ignore system files when writing out index data + unsigned IndexIgnoreSystemSymbols : 1; + /// Whether to include the codegen name of symbols in the index data + unsigned IndexRecordCodegenName : 1; + /// The input files and their types. std::vector Inputs; @@ -336,8 +343,9 @@ SkipFunctionBodies(false), UseGlobalModuleIndex(true), GenerateGlobalModuleIndex(true), ASTDumpDecls(false), ASTDumpLookups(false), BuildingImplicitModule(false), ModulesEmbedAllFiles(false), - IncludeTimestamps(true), ARCMTAction(ARCMT_None), - ObjCMTAction(ObjCMT_None), ProgramAction(frontend::ParseSyntaxOnly) + IncludeTimestamps(true), ARCMTAction(ARCMT_None), ObjCMTAction(ObjCMT_None), + IndexIgnoreSystemSymbols(false), IndexRecordCodegenName(false), + ProgramAction(frontend::ParseSyntaxOnly) {} /// getInputKindForExtension - Return the appropriate input kind for a file Index: include/clang/Index/DeclOccurrence.h =================================================================== --- /dev/null +++ include/clang/Index/DeclOccurrence.h @@ -0,0 +1,42 @@ +//===--- DeclOccurrence.h - An occurrence of a decl within a file ---------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_DECLOCCURRENCE_H +#define LLVM_CLANG_INDEX_DECLOCCURRENCE_H + +#include "clang/Basic/LLVM.h" +#include "clang/Index/IndexSymbol.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { +class Decl; + +namespace index { + +struct DeclOccurrence { + SymbolRoleSet Roles; + unsigned Offset; + const Decl *Dcl; + SmallVector Relations; + + DeclOccurrence(SymbolRoleSet R, unsigned Offset, const Decl *D, + ArrayRef Relations) + : Roles(R), Offset(Offset), Dcl(D), + Relations(Relations.begin(), Relations.end()) {} + + friend bool operator<(const DeclOccurrence &LHS, const DeclOccurrence &RHS) { + return LHS.Offset < RHS.Offset; + } +}; + +} // namespace index +} // namespace clang + +#endif Index: include/clang/Index/IndexDataConsumer.h =================================================================== --- include/clang/Index/IndexDataConsumer.h +++ include/clang/Index/IndexDataConsumer.h @@ -43,17 +43,18 @@ virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef Relations, FileID FID, unsigned Offset, - ASTNodeInfo ASTNode); + bool IsInSystemFile, ASTNodeInfo ASTNode); /// \returns true to continue indexing, or false to abort. virtual bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI, SymbolRoleSet Roles, - FileID FID, unsigned Offset); + FileID FID, unsigned Offset, + bool IsInSystemFile); /// \returns true to continue indexing, or false to abort. virtual bool handleModuleOccurence(const ImportDecl *ImportD, - SymbolRoleSet Roles, - FileID FID, unsigned Offset); + SymbolRoleSet Roles, FileID FID, + unsigned Offset, bool IsInSystemFile); virtual void finish() {} Index: include/clang/Index/IndexDiagnostic.h =================================================================== --- /dev/null +++ include/clang/Index/IndexDiagnostic.h @@ -0,0 +1,29 @@ +//===--- IndexDiagnostic.h - ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_INDEXDIAGNOSTIC_H +#define LLVM_CLANG_INDEX_INDEXDIAGNOSTIC_H + +#include "clang/Basic/Diagnostic.h" + +namespace clang { +namespace diag { +enum { +#define DIAG(ENUM, FLAGS, DEFAULT_MAPPING, DESC, GROUP, SFINAE, NOWERROR, \ + SHOWINSYSHEADER, CATEGORY) \ + ENUM, +#define INDEXSTART +#include "clang/Basic/DiagnosticIndexKinds.inc" +#undef DIAG + NUM_BUILTIN_INDEX_DIAGNOSTICS +}; +} // end namespace diag +} // end namespace clang + +#endif // LLVM_CLANG_INDEX_INDEXDIAGNOSTIC_H Index: include/clang/Index/IndexingAction.h =================================================================== --- include/clang/Index/IndexingAction.h +++ include/clang/Index/IndexingAction.h @@ -1,4 +1,4 @@ -//===--- IndexingAction.h - Frontend index action -------------------------===// +//===--- IndexingAction.h - Frontend AST indexing action ------------------===// // // The LLVM Compiler Infrastructure // @@ -13,6 +13,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" #include +#include namespace clang { class ASTContext; @@ -35,11 +36,14 @@ All, }; - SystemSymbolFilterKind SystemSymbolFilter - = SystemSymbolFilterKind::DeclarationsOnly; + SystemSymbolFilterKind SystemSymbolFilter = + SystemSymbolFilterKind::DeclarationsOnly; bool IndexFunctionLocals = false; }; +/// Creates a frontend action that provides decl occurrence information from the +/// AST to the given \c IndexDataConsumer. +/// /// \param WrappedAction another frontend action to wrap over or null. std::unique_ptr createIndexingAction(std::shared_ptr DataConsumer, Index: include/clang/Index/RecordingAction.h =================================================================== --- /dev/null +++ include/clang/Index/RecordingAction.h @@ -0,0 +1,55 @@ +//===--- RecordingAction.h - Frontend index recording action --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_INDEXRECORDINGACTION_H +#define LLVM_CLANG_INDEX_INDEXRECORDINGACTION_H + +#include "clang/Basic/LLVM.h" +#include "clang/Index/UnitIndexingAction.h" +#include "llvm/ADT/ArrayRef.h" + +namespace clang { +class CompilerInstance; +class FrontendAction; +class FrontendOptions; + +namespace serialization { +class ModuleFile; +} + +namespace index { + +struct RecordingOptions : UnitIndexingOptions { + std::string DataDirPath; + bool RecordSymbolCodeGenName = false; +}; + +RecordingOptions +getRecordingOptionsFromFrontendOptions(const FrontendOptions &FEOpts); + +/// \brief Creates a frontend action that collects dependency, file inclusion +/// and decl ocurrence information for the translation unit and persists it to +/// an index store. +/// +/// \param WrappedAction another frontend action to wrap over or null. +std::unique_ptr +createIndexDataRecordingAction(RecordingOptions RecordOpts, + std::unique_ptr WrappedAction); + +/// Collects dependency, file inclusion and decl occurrence information for a +/// \c ModuleFile and persists it to an index store. Does \b not check if +/// the store already has up-to-date information for the provided module file. +void recordIndexDataForModuleFile(serialization::ModuleFile *ModFile, + RecordingOptions RecordOpts, + const CompilerInstance &CI); + +} // namespace index +} // namespace clang + +#endif Index: include/clang/Index/UnitIndexDataConsumer.h =================================================================== --- /dev/null +++ include/clang/Index/UnitIndexDataConsumer.h @@ -0,0 +1,74 @@ +//===--- UnitIndexDataConsumer.h - Abstract unit index data consumer ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_UNITINDEXDATACONSUMER_H +#define LLVM_CLANG_INDEX_UNITINDEXDATACONSUMER_H + +#include "clang/Basic/SourceLocation.h" +#include "clang/Index/DeclOccurrence.h" +#include "clang/Index/IndexSymbol.h" +#include "llvm/ADT/ArrayRef.h" + +namespace clang { +namespace serialization { +class ModuleFile; +} + +namespace index { + +/// Consumer for the index data associated with a translation unit. +class UnitIndexDataConsumer { +public: + virtual ~UnitIndexDataConsumer() = default; + + /// Called for each file dependency of the translation unit. + virtual void handleFileDependency(const FileEntry *FE, bool IsSystem) {} + + /// Called for each file include in the translation unit. + virtual void handleInclude(const FileEntry *Source, unsigned Line, + const FileEntry *Target) {} + + /// Called for each each module imported by the translation unit. + virtual void handleModuleImport(const serialization::ModuleFile &Mod, + bool IsSystem) {} + + /// Determines whether to collect the index data associated with the given + /// dependency of this translation unit or not. + /// + /// \param OutFilePath the output file path of the dependency. + /// \returns true to collect index data for \c Mod. + virtual bool + shouldIndexModuleDependency(const serialization::ModuleFile &Mod) { + return false; + } + + /// Called with the decl occurrences in each file and AST file dependency, + /// sorted by offset. + /// + /// \returns true to cancel consuming data for this translation unit. Finish + /// will not be called. + virtual bool + handleFileOccurrences(FileID FID, + ArrayRef OccurrencesSortedByOffset, + bool IsSystem) { + return false; + } + + /// Called when there is no more data to handle. + virtual void finish() {} + +private: + // avoid duplicate vtables + virtual void _anchor(); +}; + +} // namespace index +} // namespace clang + +#endif Index: include/clang/Index/UnitIndexingAction.h =================================================================== --- /dev/null +++ include/clang/Index/UnitIndexingAction.h @@ -0,0 +1,87 @@ +//===--- UnitIndexingAction.h - Frontend unit indexing action -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_INDEX_UNITINDEXINGACTION_H +#define LLVM_CLANG_INDEX_UNITINDEXINGACTION_H + +#include "clang/Basic/LLVM.h" +#include "clang/Index/IndexingAction.h" +#include "llvm/ADT/ArrayRef.h" + +namespace clang { +class CompilerInstance; +class FileEntry; +class FrontendAction; +class Module; + +namespace serialization { +class ModuleFile; +} + +namespace index { +class UnitIndexDataConsumer; + +struct UnitIndexingOptions : IndexingOptions { + enum class FileIncludeFilterKind { + None, + UserOnly, // only record includes inside non-system files. + All, + }; + + bool IncludeSystemDependencies = true; + FileIncludeFilterKind FileIncludeFilter = FileIncludeFilterKind::UserOnly; +}; + +/// \brief Information about a translation unit useful for indexing. +/// +struct UnitDetails { + const CompilerInstance &CI; ///< The owning compiler instance. + + Module *UnitModule; ///< The corresponding \c Module (module units only). + std::string ModuleName; ///< The \c Module name (module units only). + const FileEntry *RootFile; ///< The root \c FileEntry (non-module units only). + + std::string OutputFile; ///< The output file path. + StringRef SysrootPath; ///< The "virtual system root" path. + bool IsSystemUnit; + bool IsModuleUnit; + bool IsDebugCompilation; +}; + +/// Factory function type for producing UnitIndexDataConsumers for a given +/// translation unit +typedef std::function( + UnitDetails UnitInfo)> + IndexUnitDataConsumerFactory; + +/// \brief Creates a frontend action that provides dependency, file inclusion +/// and decl ocurrence information for the translation unit, and optionally its +/// module dependencies. +/// +/// Decl occurrence information is provided per-file, sorted by offset. +/// +/// \param ConsumerFactory provides an \c IndexUnitDataConsumer to use for a +/// translation unit. +/// \param WrappedAction another frontend action to wrap over or null. +std::unique_ptr +createUnitIndexingAction(IndexUnitDataConsumerFactory ConsumerFactory, + UnitIndexingOptions UnitIndexOpts, + std::unique_ptr WrappedAction); + +/// Collects and provides dependency, file inclusion and decl occurrence +/// information for a \c ModuleFile to an \c IndexUnitDataConsumer constructed +/// from the provided \c IndexUnitDataConsumerFactory. +void indexModuleFile(serialization::ModuleFile &Mod, const CompilerInstance &CI, + IndexUnitDataConsumerFactory UnitConsumerFactory, + UnitIndexingOptions Opts); + +} // namespace index +} // namespace clang + +#endif Index: include/clang/module.modulemap =================================================================== --- include/clang/module.modulemap +++ include/clang/module.modulemap @@ -68,6 +68,7 @@ module Comment { header "AST/CommentDiagnostic.h" export * } module Driver { header "Driver/DriverDiagnostic.h" export * } module Frontend { header "Frontend/FrontendDiagnostic.h" export * } + module Index { header "Index/IndexDiagnostic.h" export * } module Lex { header "Lex/LexDiagnostic.h" export * } module Parse { header "Parse/ParseDiagnostic.h" export * } module Sema { header "Sema/SemaDiagnostic.h" export * } Index: lib/Basic/DiagnosticIDs.cpp =================================================================== --- lib/Basic/DiagnosticIDs.cpp +++ lib/Basic/DiagnosticIDs.cpp @@ -89,6 +89,7 @@ VALIDATE_DIAG_SIZE(SEMA) VALIDATE_DIAG_SIZE(ANALYSIS) VALIDATE_DIAG_SIZE(REFACTORING) +VALIDATE_DIAG_SIZE(INDEX) #undef VALIDATE_DIAG_SIZE #undef STRINGIFY_NAME @@ -114,6 +115,7 @@ #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" #include "clang/Basic/DiagnosticRefactoringKinds.inc" +#include "clang/Basic/DiagnosticIndexKinds.inc" #undef DIAG }; @@ -153,6 +155,7 @@ CATEGORY(SEMA, CROSSTU) CATEGORY(ANALYSIS, SEMA) CATEGORY(REFACTORING, ANALYSIS) +CATEGORY(INDEX, REFACTORING) #undef CATEGORY // Avoid out of bounds reads. Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -1253,7 +1253,9 @@ } // Assume associated files are based off of the first temporary file. - CrashReportInfo CrashInfo(TempFiles[0], VFS); + CrashReportInfo CrashInfo( + TempFiles[0], VFS, + C.getArgs().getLastArgValue(options::OPT_index_store_path)); std::string Script = CrashInfo.Filename.rsplit('.').first.str() + ".sh"; std::error_code EC; Index: lib/Driver/Job.cpp =================================================================== --- lib/Driver/Job.cpp +++ lib/Driver/Job.cpp @@ -68,6 +68,8 @@ .Default(false); if (IsInclude) return HaveCrashVFS ? false : true; + if (StringRef(Flag).startswith("-index-store-path")) + return true; // The remaining flags are treated as a single argument. @@ -206,6 +208,18 @@ IncFlags.push_back(std::move(NewInc)); } +/// Returns a path to a directory named \c DirName adjacent to the module +/// cache directory: +/// <...>.cache/vfs/ +static llvm::SmallString<128> +getDirAdjacentToModCache(StringRef DirName, CrashReportInfo *CrashInfo) { + llvm::SmallString<128> RelModCacheDir = llvm::sys::path::parent_path( + llvm::sys::path::parent_path(CrashInfo->VFSPath)); + llvm::sys::path::append(RelModCacheDir, DirName); + + return RelModCacheDir; +} + void Command::Print(raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo) const { // Always quote the exe. @@ -220,6 +234,7 @@ } bool HaveCrashVFS = CrashInfo && !CrashInfo->VFSPath.empty(); + bool HaveIndexStorePath = CrashInfo && !CrashInfo->IndexStorePath.empty(); for (size_t i = 0, e = Args.size(); i < e; ++i) { const char *const Arg = Args[i]; @@ -267,14 +282,10 @@ OS << ' '; printArg(OS, CrashInfo->VFSPath.str(), Quote); - // The leftover modules from the crash are stored in - // .cache/vfs/modules - // Leave it untouched for pcm inspection and provide a clean/empty dir - // path to contain the future generated module cache: - // .cache/vfs/repro-modules - SmallString<128> RelModCacheDir = llvm::sys::path::parent_path( - llvm::sys::path::parent_path(CrashInfo->VFSPath)); - llvm::sys::path::append(RelModCacheDir, "repro-modules"); + // Provide an empty dir path for the future generated module cache to + // leave the leftover modules from the crash untouched for pcm inspection + SmallString<128> RelModCacheDir = + getDirAdjacentToModCache("repro-modules", CrashInfo); std::string ModCachePath = "-fmodules-cache-path="; ModCachePath.append(RelModCacheDir.c_str()); @@ -283,6 +294,22 @@ printArg(OS, ModCachePath, Quote); } + if (CrashInfo && HaveIndexStorePath) { + SmallString<128> IndexStoreDir; + + if (HaveCrashVFS) { + // Provide a new index store, leaving the old one from the crash untouched + IndexStoreDir = getDirAdjacentToModCache("index-store", CrashInfo); + } else { + IndexStoreDir = "index-store"; + } + + OS << ' '; + printArg(OS, "-index-store-path", Quote); + OS << ' '; + printArg(OS, IndexStoreDir.c_str(), Quote); + } + if (ResponseFile != nullptr) { OS << "\n Arguments passed via response file:\n"; writeResponseFile(OS); Index: lib/Driver/ToolChains/Clang.cpp =================================================================== --- lib/Driver/ToolChains/Clang.cpp +++ lib/Driver/ToolChains/Clang.cpp @@ -3653,6 +3653,18 @@ RenderARCMigrateToolOptions(D, Args, CmdArgs); + if (Args.hasArg(options::OPT_index_store_path)) { + Args.AddLastArg(CmdArgs, options::OPT_index_store_path); + Args.AddLastArg(CmdArgs, options::OPT_index_ignore_system_symbols); + Args.AddLastArg(CmdArgs, options::OPT_index_record_codegen_name); + + // If '-o' is passed along with '-fsyntax-only' pass it along the cc1 + // invocation so that the index action knows what the out file is. + if (isa(JA) && JA.getType() == types::TY_Nothing) { + Args.AddLastArg(CmdArgs, options::OPT_o); + } + } + // Add preprocessing options like -I, -D, etc. if we are using the // preprocessor. // Index: lib/Driver/ToolChains/Darwin.cpp =================================================================== --- lib/Driver/ToolChains/Darwin.cpp +++ lib/Driver/ToolChains/Darwin.cpp @@ -436,6 +436,10 @@ // more information. ArgStringList CmdArgs; + Args.ClaimAllArgs(options::OPT_index_store_path); + Args.ClaimAllArgs(options::OPT_index_ignore_system_symbols); + Args.ClaimAllArgs(options::OPT_index_record_codegen_name); + /// Hack(tm) to ignore linking errors when we are doing ARC migration. if (Args.hasArg(options::OPT_ccc_arcmt_check, options::OPT_ccc_arcmt_migrate)) { Index: lib/Frontend/CompilerInstance.cpp =================================================================== --- lib/Frontend/CompilerInstance.cpp +++ lib/Frontend/CompilerInstance.cpp @@ -28,6 +28,7 @@ #include "clang/Frontend/TextDiagnosticPrinter.h" #include "clang/Frontend/Utils.h" #include "clang/Frontend/VerifyDiagnosticConsumer.h" +#include "clang/Index/IndexingAction.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/PTHManager.h" #include "clang/Lex/Preprocessor.h" @@ -1148,6 +1149,10 @@ SourceMgr.pushModuleBuildStack(ModuleName, FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager())); + // Pass along the GenModuleActionWrapper callback + auto WrapGenModuleAction = ImportingInstance.getGenModuleActionWrapper(); + Instance.setGenModuleActionWrapper(WrapGenModuleAction); + // If we're collecting module dependencies, we need to share a collector // between all of the module CompilerInstances. Other than that, we don't // want to produce any dependency output from the module build. @@ -1166,8 +1171,11 @@ llvm::CrashRecoveryContext CRC; CRC.RunSafelyOnThread( [&]() { - GenerateModuleFromModuleMapAction Action; - Instance.ExecuteAction(Action); + std::unique_ptr Action( + new GenerateModuleFromModuleMapAction); + if (WrapGenModuleAction) + Action = WrapGenModuleAction(FrontendOpts, std::move(Action)); + Instance.ExecuteAction(*Action); }, ThreadStackSize); Index: lib/Frontend/CompilerInvocation.cpp =================================================================== --- lib/Frontend/CompilerInvocation.cpp +++ lib/Frontend/CompilerInvocation.cpp @@ -1513,6 +1513,10 @@ << "ARC migration" << "ObjC migration"; } + Opts.IndexStorePath = Args.getLastArgValue(OPT_index_store_path); + Opts.IndexIgnoreSystemSymbols = Args.hasArg(OPT_index_ignore_system_symbols); + Opts.IndexRecordCodegenName = Args.hasArg(OPT_index_record_codegen_name); + InputKind DashX(InputKind::Unknown); if (const Arg *A = Args.getLastArg(OPT_x)) { StringRef XValue = A->getValue(); Index: lib/FrontendTool/CMakeLists.txt =================================================================== --- lib/FrontendTool/CMakeLists.txt +++ lib/FrontendTool/CMakeLists.txt @@ -8,6 +8,7 @@ clangCodeGen clangDriver clangFrontend + clangIndex clangRewriteFrontend ) Index: lib/FrontendTool/ExecuteCompilerInvocation.cpp =================================================================== --- lib/FrontendTool/ExecuteCompilerInvocation.cpp +++ lib/FrontendTool/ExecuteCompilerInvocation.cpp @@ -23,6 +23,7 @@ #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/FrontendPluginRegistry.h" #include "clang/Frontend/Utils.h" +#include "clang/Index/RecordingAction.h" #include "clang/Rewrite/Frontend/FrontendActions.h" #include "clang/StaticAnalyzer/Frontend/FrontendActions.h" #include "llvm/Option/OptTable.h" @@ -164,6 +165,22 @@ } #endif + if (!FEOpts.IndexStorePath.empty()) { + auto WrapWithIndexRecordAction = + [&](const FrontendOptions &opts, + std::unique_ptr WrappedAction) { + auto RecordOpts = + index::getRecordingOptionsFromFrontendOptions(FEOpts); + return index::createIndexDataRecordingAction( + RecordOpts, std::move(WrappedAction)); + }; + + // Wrap the main action as well as any GenerateModuleActions created while + // loading modules + Act = WrapWithIndexRecordAction(FEOpts, std::move(Act)); + CI.setGenModuleActionWrapper(WrapWithIndexRecordAction); + } + // If there are any AST files to merge, create a frontend action // adaptor to perform the merge. if (!FEOpts.ASTMergeFiles.empty()) Index: lib/Index/CMakeLists.txt =================================================================== --- lib/Index/CMakeLists.txt +++ lib/Index/CMakeLists.txt @@ -6,12 +6,14 @@ add_clang_library(clangIndex CodegenNameGenerator.cpp CommentToXML.cpp + FileIndexData.cpp IndexBody.cpp IndexDecl.cpp IndexingAction.cpp IndexingContext.cpp IndexSymbol.cpp IndexTypeSourceInfo.cpp + UnitIndexDataRecorder.cpp USRGeneration.cpp ADDITIONAL_HEADERS @@ -23,6 +25,7 @@ clangBasic clangFormat clangFrontend + clangLex clangRewrite clangSerialization clangToolingCore Index: lib/Index/FileIndexData.h =================================================================== --- /dev/null +++ lib/Index/FileIndexData.h @@ -0,0 +1,56 @@ +//===--- FileIndexData.h - Index data per file --------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_INDEX_FILEINDEXRECORD_H +#define LLVM_CLANG_LIB_INDEX_FILEINDEXRECORD_H + +#include "clang/Basic/SourceLocation.h" +#include "clang/Index/DeclOccurrence.h" +#include "clang/Index/IndexSymbol.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include + +namespace clang { +class IdentifierInfo; + +namespace index { + +/// Stores the declaration occurrences seen in a particular source or header +/// file of a translation unit +class FileIndexData { +private: + FileID FID; + bool IsSystem; + std::vector Decls; + +public: + FileIndexData(FileID FID, bool IsSystem) : FID(FID), IsSystem(IsSystem) {} + + std::vector getDeclOccurrencesSortedByOffset() const; + + FileID getFileID() const { return FID; } + bool isSystem() const { return IsSystem; } + + /// Adds an occurrence of the canonical declaration \c D at the supplied + /// \c Offset + /// + /// \param Roles the roles the occurrence fulfills in this position. + /// \param Offset the offset in the file of this occurrence. + /// \param D the canonical declaration this is an occurrence of. + /// \param Relations the set of symbols related to this occurrence. + void addDeclOccurence(SymbolRoleSet Roles, unsigned Offset, const Decl *D, + ArrayRef Relations); + void print(llvm::raw_ostream &OS) const; +}; + +} // end namespace index +} // end namespace clang + +#endif Index: lib/Index/FileIndexData.cpp =================================================================== --- /dev/null +++ lib/Index/FileIndexData.cpp @@ -0,0 +1,52 @@ +//===--- FileIndexData.cpp - Index data per file ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "FileIndexData.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/DeclTemplate.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Path.h" + +using namespace clang; +using namespace clang::index; + +void FileIndexData::addDeclOccurence(SymbolRoleSet Roles, unsigned Offset, + const Decl *D, + ArrayRef Relations) { + assert(D->isCanonicalDecl() && + "Occurrences should be associated with their canonical decl"); + + Decls.emplace_back(Roles, Offset, D, Relations); +} + +std::vector +FileIndexData::getDeclOccurrencesSortedByOffset() const { + std::vector Sorted(Decls); + std::sort(Sorted.begin(), Sorted.end()); + return Sorted; +} + +void FileIndexData::print(llvm::raw_ostream &OS) const { + OS << "DECLS BEGIN ---\n"; + for (auto &DclInfo : Decls) { + auto D = DclInfo.Dcl; + SourceManager &SM = D->getASTContext().getSourceManager(); + SourceLocation Loc = SM.getFileLoc(D->getLocation()); + PresumedLoc PLoc = SM.getPresumedLoc(Loc); + OS << llvm::sys::path::filename(PLoc.getFilename()) << ':' << PLoc.getLine() + << ':' << PLoc.getColumn(); + + if (auto ND = dyn_cast(D)) { + OS << ' ' << ND->getNameAsString(); + } + + OS << '\n'; + } + OS << "DECLS END ---\n"; +} Index: lib/Index/IndexingAction.cpp =================================================================== --- lib/Index/IndexingAction.cpp +++ lib/Index/IndexingAction.cpp @@ -8,35 +8,51 @@ //===----------------------------------------------------------------------===// #include "clang/Index/IndexingAction.h" +#include "clang/Index/RecordingAction.h" +#include "clang/Index/UnitIndexingAction.h" + +#include "FileIndexData.h" #include "IndexingContext.h" +#include "UnitIndexDataRecorder.h" +#include "clang/Basic/FileManager.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendAction.h" +#include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/MultiplexConsumer.h" +#include "clang/Frontend/Utils.h" #include "clang/Index/IndexDataConsumer.h" +#include "clang/Index/IndexDiagnostic.h" +#include "clang/Index/UnitIndexDataConsumer.h" #include "clang/Lex/Preprocessor.h" #include "clang/Serialization/ASTReader.h" +#include "llvm/Support/Path.h" using namespace clang; using namespace clang::index; +void UnitIndexDataConsumer::_anchor() {} void IndexDataConsumer::_anchor() {} bool IndexDataConsumer::handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef Relations, FileID FID, unsigned Offset, + bool IsInSystemFile, ASTNodeInfo ASTNode) { return true; } bool IndexDataConsumer::handleMacroOccurence(const IdentifierInfo *Name, - const MacroInfo *MI, SymbolRoleSet Roles, - FileID FID, unsigned Offset) { + const MacroInfo *MI, + SymbolRoleSet Roles, FileID FID, + unsigned Offset, + bool IsInSystemFile) { return true; } bool IndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD, - SymbolRoleSet Roles, - FileID FID, unsigned Offset) { + SymbolRoleSet Roles, FileID FID, + unsigned Offset, + bool IsInSystemFile) { return true; } @@ -73,96 +89,116 @@ } }; -class IndexActionBase { -protected: - std::shared_ptr DataConsumer; - IndexingContext IndexCtx; - - IndexActionBase(std::shared_ptr dataConsumer, - IndexingOptions Opts) - : DataConsumer(std::move(dataConsumer)), - IndexCtx(Opts, *DataConsumer) {} - - std::unique_ptr - createIndexASTConsumer(CompilerInstance &CI) { - return llvm::make_unique(CI.getPreprocessorPtr(), - IndexCtx); - } - - void finish() { - DataConsumer->finish(); - } +/// Abstracts the core logic shared between \c IndexAction and +/// \c WrappingIndexAction frontend actions. +class IndexActionImpl { +public: + virtual ~IndexActionImpl() = default; + + /// Called at the beginning of processing a single input, this creates the + /// IndexASTConsumer object to use. + /// + /// \param CI The compiler instance used to process the input + /// \returns the created IndexASTConsumer. + virtual std::unique_ptr + createIndexASTConsumer(CompilerInstance &CI) = 0; + + /// Callback at the end of processing a single input. + /// + /// \param CI The compiler instance used to process the input. It will be the + /// same instance as provided in \c createIndexASTConsumer. + virtual void finish(CompilerInstance &CI) = 0; }; -class IndexAction : public ASTFrontendAction, IndexActionBase { +class IndexAction : public ASTFrontendAction { + std::unique_ptr Impl; + public: - IndexAction(std::shared_ptr DataConsumer, - IndexingOptions Opts) - : IndexActionBase(std::move(DataConsumer), Opts) {} + IndexAction(std::unique_ptr Impl) : Impl(std::move(Impl)) {} protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override { - return createIndexASTConsumer(CI); + return Impl->createIndexASTConsumer(CI); } void EndSourceFileAction() override { FrontendAction::EndSourceFileAction(); - finish(); + Impl->finish(getCompilerInstance()); } }; -class WrappingIndexAction : public WrapperFrontendAction, IndexActionBase { - bool IndexActionFailed = false; +class WrappingIndexAction : public WrapperFrontendAction { + std::unique_ptr Impl; + bool CreatedASTConsumer = false; public: WrappingIndexAction(std::unique_ptr WrappedAction, - std::shared_ptr DataConsumer, - IndexingOptions Opts) - : WrapperFrontendAction(std::move(WrappedAction)), - IndexActionBase(std::move(DataConsumer), Opts) {} + std::unique_ptr Impl) + : WrapperFrontendAction(std::move(WrappedAction)), Impl(std::move(Impl)) { + } protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; - void EndSourceFileAction() override; + StringRef InFile) override { + auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); + if (!OtherConsumer) + return nullptr; + + std::vector> Consumers; + Consumers.push_back(std::move(OtherConsumer)); + Consumers.push_back(Impl->createIndexASTConsumer(CI)); + CreatedASTConsumer = true; + + return llvm::make_unique(std::move(Consumers)); + }; + + void EndSourceFileAction() override { + // Invoke wrapped action's method. + WrapperFrontendAction::EndSourceFileAction(); + if (CreatedASTConsumer) { + CreatedASTConsumer = false; + Impl->finish(getCompilerInstance()); + } + }; }; -} // anonymous namespace +/// An implementation for \c IndexAction or \c WrappingIndexAction that provides +/// decl ocurrences information from the AST. +class DataConsumerActionImpl : public IndexActionImpl { +protected: + std::shared_ptr DataConsumer; + IndexingContext IndexCtx; -void WrappingIndexAction::EndSourceFileAction() { - // Invoke wrapped action's method. - WrapperFrontendAction::EndSourceFileAction(); - if (!IndexActionFailed) - finish(); -} +public: + DataConsumerActionImpl(std::shared_ptr Consumer, + IndexingOptions Opts) + : DataConsumer(std::move(Consumer)), IndexCtx(Opts, *DataConsumer) {} -std::unique_ptr -WrappingIndexAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - auto OtherConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile); - if (!OtherConsumer) { - IndexActionFailed = true; - return nullptr; + std::unique_ptr + createIndexASTConsumer(CompilerInstance &CI) override { + IndexCtx.setSysrootPath(CI.getHeaderSearchOpts().Sysroot); + return llvm::make_unique(CI.getPreprocessorPtr(), + IndexCtx); } - std::vector> Consumers; - Consumers.push_back(std::move(OtherConsumer)); - Consumers.push_back(createIndexASTConsumer(CI)); - return llvm::make_unique(std::move(Consumers)); -} + void finish(CompilerInstance &CI) override { DataConsumer->finish(); } +}; + +} // anonymous namespace std::unique_ptr index::createIndexingAction(std::shared_ptr DataConsumer, IndexingOptions Opts, std::unique_ptr WrappedAction) { + auto ActionImpl = + llvm::make_unique(std::move(DataConsumer), Opts); if (WrappedAction) return llvm::make_unique(std::move(WrappedAction), - std::move(DataConsumer), - Opts); - return llvm::make_unique(std::move(DataConsumer), Opts); + std::move(ActionImpl)); + return llvm::make_unique(std::move(ActionImpl)); } - static bool topLevelDeclVisitor(void *context, const Decl *D) { IndexingContext &IndexCtx = *static_cast(context); return IndexCtx.indexTopLevelDecl(D); @@ -209,3 +245,545 @@ } DataConsumer->finish(); } + +//===----------------------------------------------------------------------===// +// Index Data Recording +//===----------------------------------------------------------------------===// + +/// Construct a \c UnitDetails for a translation unit with the provided root +/// \c FileEntry or \c Module and with the provided sysroot path. +static index::UnitDetails getUnitDetails(const CompilerInstance &CI, + std::string OutputFile, + const FileEntry *RootFile, + Module *UnitMod, + StringRef SysrootPath) { + std::string ModuleName = + UnitMod ? UnitMod->getFullModuleName() : std::string(); + bool IsSystemUnit = UnitMod ? UnitMod->IsSystem : false; + bool IsModuleUnit = UnitMod != nullptr; + bool IsDebugCompilation = CI.getCodeGenOpts().OptimizationLevel == 0; + + // Ignore sysroot path if it points to root, otherwise every header will be + // treated as system one. + if (llvm::sys::path::root_path(SysrootPath) == SysrootPath) + SysrootPath = ""; + + return {CI, UnitMod, ModuleName, + RootFile, OutputFile, SysrootPath, + IsSystemUnit, IsModuleUnit, IsDebugCompilation}; +} + +/// Construct a \c UnitDetails from the invocation associated with the provided +/// \c CompilerInstance and the provided sysroot path. +static index::UnitDetails getUnitDetails(const CompilerInstance &CI, + StringRef SysrootPath) { + SourceManager &SM = CI.getASTContext().getSourceManager(); + + std::string OutputFile = CI.getFrontendOpts().OutputFile; + if (OutputFile.empty()) { + OutputFile = CI.getFrontendOpts().Inputs[0].getFile(); + OutputFile += ".o"; + } + + const FileEntry *RootFile = nullptr; + Module *UnitMod = nullptr; + bool IsModuleGeneration = CI.getLangOpts().isCompilingModule(); + if (!IsModuleGeneration && + CI.getFrontendOpts().ProgramAction != frontend::GeneratePCH) + RootFile = SM.getFileEntryForID(SM.getMainFileID()); + + if (IsModuleGeneration) { + HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); + UnitMod = HS.lookupModule(CI.getLangOpts().CurrentModule, + /*AllowSearch=*/false); + assert(UnitMod && "only loaded modules should be indexed"); + } + return getUnitDetails(CI, std::move(OutputFile), RootFile, UnitMod, + SysrootPath); +} + +/// Construct a \c UnitDetails for the given module file. +static index::UnitDetails getUnitDetails(serialization::ModuleFile &Mod, + const CompilerInstance &CI, + StringRef SysrootPath) { + HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); + Module *UnitMod = HS.lookupModule(Mod.ModuleName, /*AllowSearch=*/false); + assert(UnitMod && "only loaded modules should be indexed"); + + return getUnitDetails(CI, /*OutputFile=*/Mod.FileName, /*RootFile=*/nullptr, + UnitMod, SysrootPath); +} + +namespace { + +/// Collects and groups consumed index data by \c FileID. +class FileIndexDataCollector : public IndexDataConsumer { + std::shared_ptr PP; + typedef llvm::DenseMap> + IndexDataByFileTy; + IndexDataByFileTy IndexDataByFile; + +public: + void setPreprocessor(std::shared_ptr PreProc) override { + PP = PreProc; + } + + IndexDataByFileTy::const_iterator begin() const { + return IndexDataByFile.begin(); + } + + IndexDataByFileTy::const_iterator end() const { + return IndexDataByFile.end(); + } + + bool empty() const { return IndexDataByFile.empty(); } + + bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, + ArrayRef Relations, FileID FID, + unsigned Offset, bool IsInSystemFile, + ASTNodeInfo ASTNode) override { + // Ignore occurrences in the predefines buffer + if (FID == PP->getPredefinesFileID()) + return true; + + FileIndexData &FileData = getFileIndexData(FID, IsInSystemFile); + FileData.addDeclOccurence(Roles, Offset, D, Relations); + return true; + } + +private: + FileIndexData &getFileIndexData(FileID FID, bool IsInSystemFile) { + auto &Entry = IndexDataByFile[FID]; + if (!Entry) { + Entry.reset(new FileIndexData(FID, IsInSystemFile)); + } + return *Entry; + } +}; + +struct IncludeLocation { + const FileEntry *Source; + const FileEntry *Target; + unsigned Line; +}; + +/// Preprocessor callbacks to collect file to file inclusion information +class IncludePPCallbacks : public PPCallbacks { + SystemFileCache &SystemCache; + UnitIndexingOptions::FileIncludeFilterKind FileIncludeFilter; + std::vector &Includes; + SourceManager &SourceMgr; + +public: + IncludePPCallbacks(SystemFileCache &SystemCache, + UnitIndexingOptions::FileIncludeFilterKind IncludeFilter, + std::vector &IncludesForFile, + SourceManager &SourceMgr) + : SystemCache(SystemCache), FileIncludeFilter(IncludeFilter), + Includes(IncludesForFile), SourceMgr(SourceMgr) {} + + virtual void InclusionDirective(SourceLocation HashLoc, + const Token &IncludeTok, StringRef FileName, + bool IsAngled, CharSourceRange FilenameRange, + const FileEntry *File, StringRef SearchPath, + StringRef RelativePath, + const Module *Imported) override { + if (HashLoc.isFileID() && File && File->isValid()) + addInclude(HashLoc, File); + } + +private: + void addInclude(SourceLocation From, const FileEntry *To) { + assert(To); + if (FileIncludeFilter == UnitIndexingOptions::FileIncludeFilterKind::None) + return; + + std::pair LocInfo = + SourceMgr.getDecomposedExpansionLoc(From); + + if (LocInfo.first.isInvalid()) + return; // Ignore invalid locations. + + if (FileIncludeFilter == + UnitIndexingOptions::FileIncludeFilterKind::UserOnly) + if (SystemCache.isSystem(LocInfo.first, SourceMgr)) + return; // Ignore includes of system headers. + + if (auto *FE = SourceMgr.getFileEntryForID(LocInfo.first)) { + auto lineNo = SourceMgr.getLineNumber(LocInfo.first, LocInfo.second); + Includes.push_back({FE, To, lineNo}); + } + } +}; + +/// Abstract interface for providing the file and module dependencies of a +/// translation unit, as well as the set of file to file inclusions +class IndexDependencyProvider { +public: + virtual ~IndexDependencyProvider() {} + + virtual void forEachFileDependency( + const CompilerInstance &CI, + llvm::function_ref Callback) + const = 0; + + virtual void + forEachInclude(llvm::function_ref + Callback) const = 0; + virtual void forEachModuleImport( + const CompilerInstance &CI, + llvm::function_ref + Callback) const = 0; +}; + +/// An IndexDependencyProvider for the index data collected by +/// \c FileIndexDependencyCollector. +class FileIndexDependencyProvider : public IndexDependencyProvider { + llvm::SetVector Files; + llvm::BitVector IsSystemByUID; + std::vector Includes; + bool IncludeSysModules; + +public: + FileIndexDependencyProvider(llvm::SetVector Entries, + llvm::BitVector IsSystemByUID, + std::vector Includes, + bool IncludeSysDeps) + : Files(std::move(Entries)), IsSystemByUID(std::move(IsSystemByUID)), + Includes(std::move(Includes)), IncludeSysModules(IncludeSysDeps) {} + + void forEachFileDependency( + const CompilerInstance &CI, + llvm::function_ref Callback) + const override { + for (auto *FE : Files) + Callback(FE, isSystemFile(FE)); + } + + void + forEachInclude(llvm::function_ref + Callback) const override { + for (auto &Include : Includes) + Callback(Include.Source, Include.Line, Include.Target); + } + + void forEachModuleImport( + const CompilerInstance &CI, + llvm::function_ref + Callback) const override { + HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); + + if (auto Reader = CI.getModuleManager()) { + Reader->getModuleManager().visit( + [&](serialization::ModuleFile &Mod) -> bool { + bool IsSystemMod = false; + if (Mod.isModule()) { + if (auto *M = + HS.lookupModule(Mod.ModuleName, /*AllowSearch=*/false)) + IsSystemMod = M->IsSystem; + } + if (!IsSystemMod || IncludeSysModules) + Callback(Mod, IsSystemMod); + return true; // skip module dependencies. + }); + } + } + +private: + bool isSystemFile(const FileEntry *FE) const { + auto UID = FE->getUID(); + return IsSystemByUID.size() > UID && IsSystemByUID[UID]; + } +}; + +/// Collects file and module dependency information for a translation unit, +/// including file to file inclusions. +class FileIndexDependencyCollector : public DependencyCollector { + SystemFileCache &SystemCache; + UnitIndexingOptions IndexOpts; + llvm::SetVector SeenFiles; + llvm::BitVector IsSystemByUID; + std::vector Includes; + SourceManager *SourceMgr = nullptr; + +public: + FileIndexDependencyCollector(SystemFileCache &SystemCache, + UnitIndexingOptions IndexOpts) + : SystemCache(SystemCache), IndexOpts(IndexOpts) {} + + void attachToPreprocessor(Preprocessor &PP) override { + DependencyCollector::attachToPreprocessor(PP); + PP.addPPCallbacks(llvm::make_unique( + SystemCache, IndexOpts.FileIncludeFilter, Includes, + PP.getSourceManager())); + } + + void setSourceManager(SourceManager *SourceMgr) { + this->SourceMgr = SourceMgr; + } + + FileIndexDependencyProvider consume() { + return FileIndexDependencyProvider( + std::move(SeenFiles), std::move(IsSystemByUID), std::move(Includes), + IndexOpts.IncludeSystemDependencies); + } + +private: + bool needSystemDependencies() override { + return IndexOpts.IncludeSystemDependencies; + } + + bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, + bool IsModuleFile, bool IsMissing) override { + bool SawIt = DependencyCollector::sawDependency( + Filename, FromModule, IsSystem, IsModuleFile, IsMissing); + if (auto *FE = SourceMgr->getFileManager().getFile(Filename)) { + if (SawIt) + SeenFiles.insert(FE); + + // Record system-ness for all files that we pass through. + if (IsSystemByUID.size() < FE->getUID() + 1) + IsSystemByUID.resize(FE->getUID() + 1); + IsSystemByUID[FE->getUID()] = IsSystem || isInSysroot(Filename); + } + return SawIt; + } + + bool isInSysroot(StringRef Filename) { + StringRef SysrootPath = SystemCache.getSysrootPath(); + return !SysrootPath.empty() && Filename.startswith(SysrootPath); + } +}; +} // anonymous namespace + +static void reportData(const CompilerInstance &CI, + const FileIndexDataCollector &Collector, + const IndexDependencyProvider &DepProvider, + UnitDetails UnitInfo, + const IndexUnitDataConsumerFactory &UnitConsumerFactory, + const UnitIndexingOptions &IndexOpts) { + + std::unique_ptr Consumer = + UnitConsumerFactory(UnitInfo); + if (!Consumer) + return; + + DepProvider.forEachFileDependency( + CI, [&](const FileEntry *FE, bool IsSystemFile) { + Consumer->handleFileDependency(FE, IsSystemFile); + }); + DepProvider.forEachInclude( + [&](const FileEntry *Source, unsigned Line, const FileEntry *Target) { + Consumer->handleInclude(Source, Line, Target); + }); + DepProvider.forEachModuleImport( + CI, [&](serialization::ModuleFile &Mod, bool IsSystemMod) { + Consumer->handleModuleImport(Mod, IsSystemMod); + if (Mod.isModule() && Consumer->shouldIndexModuleDependency(Mod)) + indexModuleFile(Mod, CI, UnitConsumerFactory, IndexOpts); + }); + + for (auto I = Collector.begin(), E = Collector.end(); I != E; ++I) { + FileID FID = I->first; + const FileIndexData &FileData = *I->second; + if (Consumer->handleFileOccurrences( + FID, FileData.getDeclOccurrencesSortedByOffset(), + FileData.isSystem())) + return; + } + + Consumer->finish(); +} + +namespace { + +/// An implementation for IndexAction or WrappingIndexAction that gathers decl +/// occurrence, file inclusion and dependency information for the translation +/// and, optionally, its module dependencies. +class UnitDataConsumerActionImpl : public IndexActionImpl { + UnitIndexingOptions IndexOpts; + FileIndexDataCollector Collector; + IndexingContext IndexCtx; + FileIndexDependencyCollector DepCollector; + IndexUnitDataConsumerFactory UnitConsumerFactory; + +public: + UnitDataConsumerActionImpl(UnitIndexingOptions UnitIndexOpts, + IndexUnitDataConsumerFactory UnitConsumerFactory) + : IndexOpts(UnitIndexOpts), IndexCtx(UnitIndexOpts, Collector), + DepCollector(IndexCtx.getSystemCache(), IndexOpts), + UnitConsumerFactory(std::move(UnitConsumerFactory)) {} + + std::unique_ptr + createIndexASTConsumer(CompilerInstance &CI) override { + IndexCtx.setSysrootPath(CI.getHeaderSearchOpts().Sysroot); + + std::shared_ptr PP = CI.getPreprocessorPtr(); + Collector.setPreprocessor(PP); + DepCollector.setSourceManager(&CI.getSourceManager()); + DepCollector.attachToPreprocessor(CI.getPreprocessor()); + + return llvm::make_unique(PP, IndexCtx); + } + + /// Provides the collected indexing info to the \c IndexUnitDataConsumer + void finish(CompilerInstance &CI) override { + // The consumer may emit more diagnostics so do the begin/end source file + // invocations on the diagnostic client. + // FIXME: FrontendAction::EndSourceFile() should probably not call + // CI.getDiagnosticClient().EndSourceFile()' until after it has called + // 'EndSourceFileAction()', so that code executing during + // EndSourceFileAction() can emit diagnostics. If this is fixed, + // DiagClientBeginEndRAII can go away. + struct DiagClientBeginEndRAII { + CompilerInstance &CI; + DiagClientBeginEndRAII(CompilerInstance &CI) : CI(CI) { + CI.getDiagnosticClient().BeginSourceFile(CI.getLangOpts()); + } + ~DiagClientBeginEndRAII() { CI.getDiagnosticClient().EndSourceFile(); } + } diagClientBeginEndRAII(CI); + + Collector.finish(); + reportData(CI, Collector, DepCollector.consume(), + getUnitDetails(CI, IndexCtx.getSysrootPath()), + UnitConsumerFactory, IndexOpts); + } +}; + +/// Provides the file and module dependency information for a \c ModuleFile +class ModuleFileIndexDependencyCollector : public IndexDependencyProvider { + serialization::ModuleFile &ModFile; + bool CollectSystemDependencies; + +public: + ModuleFileIndexDependencyCollector(serialization::ModuleFile &Mod, + bool CollectSystemDependencies) + : ModFile(Mod), CollectSystemDependencies(CollectSystemDependencies) {} + + void forEachFileDependency( + const CompilerInstance &CI, + llvm::function_ref Callback) + const override { + auto Reader = CI.getModuleManager(); + Reader->visitInputFiles( + ModFile, CollectSystemDependencies, /*Complain=*/false, + [&](const serialization::InputFile &IF, bool IsSystem) { + auto *FE = IF.getFile(); + if (!FE) + return; + // Ignore module map files, they are not as important to track as + // source files and they may be auto-generated which would create an + // undesirable dependency on an intermediate build byproduct. + if (FE->getName().endswith("module.modulemap")) + return; + + Callback(FE, IsSystem); + }); + } + + void + forEachInclude(llvm::function_ref + Callback) const override { + // FIXME: Module files without a preprocessing record do not have info about + // include locations. Serialize enough data to be able to retrieve such + // info. + } + + void forEachModuleImport( + const CompilerInstance &CI, + llvm::function_ref + Callback) const override { + HeaderSearch &HS = CI.getPreprocessor().getHeaderSearchInfo(); + for (auto *Mod : ModFile.Imports) { + bool IsSystemMod = false; + if (auto *M = HS.lookupModule(Mod->ModuleName, /*AllowSearch=*/false)) + IsSystemMod = M->IsSystem; + if (!IsSystemMod || CollectSystemDependencies) + Callback(*Mod, IsSystemMod); + } + } +}; +} // anonymous namespace. + +void index::indexModuleFile(serialization::ModuleFile &Mod, + const CompilerInstance &CI, + IndexUnitDataConsumerFactory UnitConsumerFactory, + UnitIndexingOptions IndexOpts) { + + DiagnosticsEngine &Diag = CI.getDiagnostics(); + Diag.Report(Mod.ImportLoc, diag::remark_index_producing_module_file_data) + << Mod.FileName; + + FileIndexDataCollector Collector; + IndexingContext ModIndexCtx(IndexOpts, Collector); + + auto &ASTCtx = CI.getASTContext(); + Collector.initialize(ASTCtx); + Collector.setPreprocessor(CI.getPreprocessorPtr()); + ModIndexCtx.setASTContext(ASTCtx); + ModIndexCtx.setSysrootPath(CI.getHeaderSearchOpts().Sysroot); + + for (const Decl *D : CI.getModuleManager()->getModuleFileLevelDecls(Mod)) + ModIndexCtx.indexTopLevelDecl(D); + + Collector.finish(); + + ModuleFileIndexDependencyCollector DepCollector( + Mod, IndexOpts.IncludeSystemDependencies); + + reportData(CI, Collector, DepCollector, + getUnitDetails(Mod, CI, ModIndexCtx.getSysrootPath()), + UnitConsumerFactory, IndexOpts); +} + +std::unique_ptr +index::createUnitIndexingAction(IndexUnitDataConsumerFactory ConsumerFactory, + UnitIndexingOptions IndexOpts, + std::unique_ptr WrappedAction) { + auto ActionImpl = llvm::make_unique( + std::move(IndexOpts), ConsumerFactory); + if (WrappedAction) + return llvm::make_unique(std::move(WrappedAction), + std::move(ActionImpl)); + return llvm::make_unique(std::move(ActionImpl)); +}; + +std::unique_ptr index::createIndexDataRecordingAction( + RecordingOptions RecordOpts, + std::unique_ptr WrappedAction) { + + auto ConsumerFactory = + [RecordOpts]( + UnitDetails UnitInfo) -> std::unique_ptr { + return llvm::make_unique(std::move(UnitInfo), + RecordOpts); + }; + return createUnitIndexingAction(ConsumerFactory, std::move(RecordOpts), + std::move(WrappedAction)); +}; + +RecordingOptions +index::getRecordingOptionsFromFrontendOptions(const FrontendOptions &FEOpts) { + RecordingOptions RecordOpts; + RecordOpts.DataDirPath = FEOpts.IndexStorePath; + if (FEOpts.IndexIgnoreSystemSymbols) { + RecordOpts.SystemSymbolFilter = + index::IndexingOptions::SystemSymbolFilterKind::None; + } + RecordOpts.RecordSymbolCodeGenName = FEOpts.IndexRecordCodegenName; + return RecordOpts; +} + +void index::recordIndexDataForModuleFile(serialization::ModuleFile *ModFile, + RecordingOptions RecordOpts, + const CompilerInstance &CI) { + auto UnitConsumerFactory = [RecordOpts](UnitDetails UnitInfo) { + return llvm::make_unique(std::move(UnitInfo), + RecordOpts); + }; + return indexModuleFile(*ModFile, CI, UnitConsumerFactory, + std::move(RecordOpts)); +} Index: lib/Index/IndexingContext.h =================================================================== --- lib/Index/IndexingContext.h +++ lib/Index/IndexingContext.h @@ -11,9 +11,11 @@ #define LLVM_CLANG_LIB_INDEX_INDEXINGCONTEXT_H #include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Index/IndexSymbol.h" #include "clang/Index/IndexingAction.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" namespace clang { class ASTContext; @@ -29,25 +31,51 @@ class Stmt; class Expr; class TypeLoc; - class SourceLocation; + class DirectoryEntry; namespace index { class IndexDataConsumer; +/// Tracks the current system root path and computes and caches whether a +/// file is considered a system file or not +class SystemFileCache { + std::string SysrootPath; + // Records whether a directory entry is system or not. + llvm::DenseMap DirEntries; + // Keeps track of the last check for whether a FileID is system or + // not. This is used to speed up isSystemFile() call. + std::pair LastFileCheck; + +public: + SystemFileCache() = default; + SystemFileCache(std::string SysrootPath); + + void setSysrootPath(StringRef path); + StringRef getSysrootPath() const { return SysrootPath; } + bool isSystem(FileID FID, SourceManager &SM); +}; + +/// Generates and reports indexing data to the provided \c IndexDataConsumer +/// for any AST nodes passed to its various \c index* methods. class IndexingContext { IndexingOptions IndexOpts; + SystemFileCache SystemCache; IndexDataConsumer &DataConsumer; ASTContext *Ctx = nullptr; public: IndexingContext(IndexingOptions IndexOpts, IndexDataConsumer &DataConsumer) - : IndexOpts(IndexOpts), DataConsumer(DataConsumer) {} + : IndexOpts(IndexOpts), DataConsumer(DataConsumer) {} const IndexingOptions &getIndexOpts() const { return IndexOpts; } + SystemFileCache &getSystemCache() { return SystemCache; } IndexDataConsumer &getDataConsumer() { return DataConsumer; } void setASTContext(ASTContext &ctx) { Ctx = &ctx; } + void setSysrootPath(StringRef path) { SystemCache.setSysrootPath(path); } + StringRef getSysrootPath() const { return SystemCache.getSysrootPath(); } + bool shouldIndex(const Decl *D); const LangOptions &getLangOpts() const; Index: lib/Index/IndexingContext.cpp =================================================================== --- lib/Index/IndexingContext.cpp +++ lib/Index/IndexingContext.cpp @@ -8,14 +8,16 @@ //===----------------------------------------------------------------------===// #include "IndexingContext.h" -#include "clang/Index/IndexDataConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclTemplate.h" #include "clang/Basic/SourceManager.h" +#include "clang/Index/IndexDataConsumer.h" +#include "llvm/Support/Path.h" using namespace clang; using namespace index; +using namespace llvm; static bool isGeneratedDecl(const Decl *D) { if (auto *attr = D->getAttr()) { @@ -24,6 +26,59 @@ return false; } +void SystemFileCache::setSysrootPath(llvm::StringRef Path) { + // Ignore sysroot path if it points to root, otherwise every header will be + // treated as system one. + SysrootPath = sys::path::root_path(Path) == Path ? StringRef() : Path; + + // Invalidate existing results + LastFileCheck = {FileID(), false}; + DirEntries.clear(); +} + +SystemFileCache::SystemFileCache(std::string Path) { setSysrootPath(Path); } + +bool SystemFileCache::isSystem(clang::FileID FID, clang::SourceManager &SM) { + if (LastFileCheck.first == FID) + return LastFileCheck.second; + + auto Result = [&](bool Res) -> bool { + LastFileCheck = {FID, Res}; + return Res; + }; + + bool Invalid = false; + const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); + if (Invalid || !SEntry.isFile()) + return Result(false); + + const SrcMgr::FileInfo &FI = SEntry.getFile(); + if (FI.getFileCharacteristic() != SrcMgr::C_User) + return Result(true); + + auto *CC = FI.getContentCache(); + if (!CC) + return Result(false); + auto *FE = CC->OrigEntry; + if (!FE) + return Result(false); + + if (SysrootPath.empty()) + return Result(false); + + // Check if directory is in sysroot so that we can consider system headers + // even the headers found via a user framework search path, pointing inside + // sysroot. + auto DirEntry = FE->getDir(); + auto Pair = DirEntries.insert(std::make_pair(DirEntry, false)); + bool &IsSystemDir = Pair.first->second; + bool WasInserted = Pair.second; + if (WasInserted) { + IsSystemDir = StringRef(DirEntry->getName()).startswith(SysrootPath); + } + return Result(IsSystemDir); +} + bool IndexingContext::shouldIndex(const Decl *D) { return !isGeneratedDecl(D); } @@ -93,12 +148,8 @@ if (FID.isInvalid()) return true; - bool Invalid = false; - const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); - if (Invalid || !SEntry.isFile()) - return true; - - if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { + bool IsInSystemFile = SystemCache.isSystem(FID, SM); + if (IsInSystemFile) { switch (IndexOpts.SystemSymbolFilter) { case IndexingOptions::SystemSymbolFilterKind::None: return true; @@ -112,7 +163,8 @@ if (ImportD->isImplicit()) Roles |= (unsigned)SymbolRole::Implicit; - return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset); + return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset, + IsInSystemFile); } bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) { @@ -205,7 +257,8 @@ return nullptr; } -static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, ASTContext &Ctx) { +static bool isDeclADefinition(const Decl *D, const DeclContext *ContainerDC, + ASTContext &Ctx) { if (auto VD = dyn_cast(D)) return VD->isThisDeclarationADefinition(Ctx); @@ -321,7 +374,7 @@ const Expr *OrigE, const Decl *OrigD, const DeclContext *ContainerDC) { - if (D->isImplicit() && !isa(D)) + if (D->isImplicit() && !(isa(D) || isa(D))) return true; if (!isa(D) || shouldSkipNamelessDecl(cast(D))) return true; @@ -337,12 +390,8 @@ if (FID.isInvalid()) return true; - bool Invalid = false; - const SrcMgr::SLocEntry &SEntry = SM.getSLocEntry(FID, &Invalid); - if (Invalid || !SEntry.isFile()) - return true; - - if (SEntry.getFile().getFileCharacteristic() != SrcMgr::C_User) { + bool IsInSystemFile = SystemCache.isSystem(FID, SM); + if (IsInSystemFile) { switch (IndexOpts.SystemSymbolFilter) { case IndexingOptions::SystemSymbolFilterKind::None: return true; @@ -416,5 +465,5 @@ IndexDataConsumer::ASTNodeInfo Node{ OrigE, OrigD, Parent, ContainerDC }; return DataConsumer.handleDeclOccurence(D, Roles, FinalRelations, FID, Offset, - Node); + IsInSystemFile, Node); } Index: lib/Index/UnitIndexDataRecorder.h =================================================================== --- /dev/null +++ lib/Index/UnitIndexDataRecorder.h @@ -0,0 +1,52 @@ +//===--- UnitIndexDataRecorder.h - Persist index data to the file system --===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_INDEX_UNITINDEXDATARECORDER_H +#define LLVM_CLANG_LIB_INDEX_UNITINDEXDATARECORDER_H + +#include "clang/Index/RecordingAction.h" +#include "clang/Index/UnitIndexDataConsumer.h" + +namespace clang { +class DiagnosticsEngine; +class FrontendOptions; + +namespace index { + +/// Persists the provided index data for a single translation unit out to the +/// file system. +class UnitIndexDataRecorder : public UnitIndexDataConsumer { +protected: + UnitDetails UnitInfo; + +public: + UnitIndexDataRecorder(UnitDetails UnitInfo, RecordingOptions RecordOpts); + + void handleFileDependency(const FileEntry *FE, bool IsSystem) override; + + void handleInclude(const FileEntry *Source, unsigned Line, + const FileEntry *Target) override; + + void handleModuleImport(const serialization::ModuleFile &Mod, + bool IsSystem) override; + + bool + shouldIndexModuleDependency(const serialization::ModuleFile &Mod) override; + + bool handleFileOccurrences(FileID FID, + ArrayRef OccurrencesSortedByOffset, + bool IsSystem) override; + + void finish() override; +}; + +} // end namespace index +} // end namespace clang + +#endif Index: lib/Index/UnitIndexDataRecorder.cpp =================================================================== --- /dev/null +++ lib/Index/UnitIndexDataRecorder.cpp @@ -0,0 +1,52 @@ +//===--- UnitIndexDataRecorder.cpp - Persist index data to the file system ===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "UnitIndexDataRecorder.h" +#include "clang/Frontend/FrontendOptions.h" + +using namespace clang; +using namespace clang::index; + +UnitIndexDataRecorder::UnitIndexDataRecorder(UnitDetails UnitDetails, + RecordingOptions RecordOpts) + : UnitInfo(UnitDetails) { + // TODO +} + +void UnitIndexDataRecorder::handleFileDependency(const FileEntry *FE, + bool IsSystem) { + // TODO +} + +void UnitIndexDataRecorder::handleInclude(const FileEntry *Source, + unsigned int Line, + const FileEntry *Target) { + // TODO +} + +void UnitIndexDataRecorder::handleModuleImport( + const serialization::ModuleFile &Mod, bool IsSystem) { + // TODO +} + +bool UnitIndexDataRecorder::shouldIndexModuleDependency( + const serialization::ModuleFile &Mod) { + // TODO + return true; +}; + +bool UnitIndexDataRecorder::handleFileOccurrences( + FileID FID, ArrayRef Occurs, bool IsSystem) { + // TODO + return false; +}; + +void UnitIndexDataRecorder::finish(){ + // TODO +}; Index: test/Index/Core/Inputs/module/ModDep.h =================================================================== --- /dev/null +++ test/Index/Core/Inputs/module/ModDep.h @@ -0,0 +1,3 @@ +#include "ModTop.h" + +void ModDep_func(ModTopStruct s); Index: test/Index/Core/Inputs/module/ModSystem.h =================================================================== --- /dev/null +++ test/Index/Core/Inputs/module/ModSystem.h @@ -0,0 +1,4 @@ + +typedef struct {} ModSystemStruct; + +void ModSystem_func(void); Index: test/Index/Core/Inputs/module/ModTop.h =================================================================== --- /dev/null +++ test/Index/Core/Inputs/module/ModTop.h @@ -0,0 +1,4 @@ + +typedef struct {} ModTopStruct; + +void ModTop_func(void); Index: test/Index/Core/Inputs/module/ModTopSub1.h =================================================================== --- /dev/null +++ test/Index/Core/Inputs/module/ModTopSub1.h @@ -0,0 +1 @@ +void ModTopSub1_func(void); Index: test/Index/Core/Inputs/module/ModTopSub2.h =================================================================== --- /dev/null +++ test/Index/Core/Inputs/module/ModTopSub2.h @@ -0,0 +1 @@ +// This header has no symbols, intended to show up as file dependency. Index: test/Index/Core/Inputs/module/module.modulemap =================================================================== --- test/Index/Core/Inputs/module/module.modulemap +++ test/Index/Core/Inputs/module/module.modulemap @@ -1 +1,13 @@ module ModA { header "ModA.h" export * } +module ModDep { header "ModDep.h" export * } +module ModSystem [system] { header "ModSystem.h" export * } +module ModTop { + header "ModTop.h" + export * + module Sub1 { + header "ModTopSub1.h" + } + module Sub2 { + header "ModTopSub2.h" + } +} Index: test/Index/Core/Inputs/sys/system-head.h =================================================================== --- test/Index/Core/Inputs/sys/system-head.h +++ test/Index/Core/Inputs/sys/system-head.h @@ -1,3 +1,20 @@ +// UNIT: index-system.mm.o +// UNIT: is-system: 0 +// UNIT: is-module: 0 +// UNIT: has-main: 1 +// UNIT: main-path: {{.*}}index-system.mm +// UNIT: out-file: {{.*}}index-system.mm.o +// UNIT: is-debug: 1 + +// UNIT: DEPEND START +// UNIT: File | user | {{.*}}index-system.mm +// UNIT: File | system | {{.*}}system-head.h +// UNIT: DEPEND END (2) + +// UNIT: INCLUDE START +// UNIT: {{.*}}index-system.mm:4 -> {{.*}}system-head.h +// UNIT: INCLUDE END (1) + // CHECK: [[@LINE+1]]:12 | class/ObjC | Base | [[Base_USR:.*]] | {{.*}} | Decl | rel: 0 @interface Base @end Index: test/Index/Core/Inputs/transitive-include.h =================================================================== --- /dev/null +++ test/Index/Core/Inputs/transitive-include.h @@ -0,0 +1,6 @@ +#include "system-head.h" + +struct Point { + int x; + int y; +}; Index: test/Index/Core/external-source-symbol-attr.m =================================================================== --- test/Index/Core/external-source-symbol-attr.m +++ test/Index/Core/external-source-symbol-attr.m @@ -1,4 +1,5 @@ // RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s +// RUN: c-index-test core -print-source-unit -- %s -target x86_64-apple-macosx10.7 | FileCheck %s #define EXT_DECL(mod_name) __attribute__((external_source_symbol(language="Swift", defined_in=mod_name))) #define GEN_DECL(mod_name) __attribute__((external_source_symbol(language="Swift", defined_in=mod_name, generated_declaration))) Index: test/Index/Core/index-instantiated-source.cpp =================================================================== --- test/Index/Core/index-instantiated-source.cpp +++ test/Index/Core/index-instantiated-source.cpp @@ -1,4 +1,5 @@ // RUN: c-index-test core -print-source-symbols -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s +// RUN: c-index-test core -print-source-unit -- %s -std=c++14 -target x86_64-apple-macosx10.7 | FileCheck %s // References to declarations in instantiations should be canonicalized: template Index: test/Index/Core/index-source.mm =================================================================== --- test/Index/Core/index-source.mm +++ test/Index/Core/index-source.mm @@ -1,4 +1,5 @@ // RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s +// RUN: c-index-test core -print-source-unit -- %s -target x86_64-apple-macosx10.7 | FileCheck -check-prefixes=CHECK %s @interface MyCls @end Index: test/Index/Core/index-subkinds.m =================================================================== --- test/Index/Core/index-subkinds.m +++ test/Index/Core/index-subkinds.m @@ -1,4 +1,5 @@ // RUN: c-index-test core -print-source-symbols -- %s -target x86_64-apple-macosx10.7 | FileCheck %s +// RUN: c-index-test core -print-source-unit -- %s -target x86_64-apple-macosx10.7 | FileCheck %s // CHECK: [[@LINE+1]]:12 | class/ObjC | XCTestCase | c:objc(cs)XCTestCase | _OBJC_CLASS_$_XCTestCase | Decl | rel: 0 @interface XCTestCase Index: test/Index/Core/index-system.mm =================================================================== --- test/Index/Core/index-system.mm +++ test/Index/Core/index-system.mm @@ -1,3 +1,4 @@ // RUN: c-index-test core -print-source-symbols -- %s -isystem %S/Inputs/sys | FileCheck %S/Inputs/sys/system-head.h +// RUN: c-index-test core -print-source-unit -- %s -isystem %S/Inputs/sys | FileCheck -check-prefixes=UNIT,CHECK %S/Inputs/sys/system-head.h #include "system-head.h" Index: test/Index/Core/index-unit.mm =================================================================== --- /dev/null +++ test/Index/Core/index-unit.mm @@ -0,0 +1,135 @@ +// RUN: rm -rf %t.mcp +// RUN: c-index-test core -print-source-unit -- -arch x86_64 -mmacosx-version-min=10.7 -c %s -o %t.o -isystem %S/Inputs/sys -fmodules -fmodules-cache-path=%t.mcp -Xclang -fdisable-module-hash -I %S/Inputs/module -I %S/Inputs | FileCheck %s + +@import ModDep; +@import ModSystem; + + + +// CHECK: ModTop.pcm + +// CHECK: is-system: 0 +// CHECK: is-module: 1 +// CHECK: module-name: ModTop +// CHECK: has-main: 0 +// CHECK: main-path: {{$}} +// CHECK: out-file: {{.*}}/ModTop.pcm + +// CHECK: DEPEND START +// CHECK: File | user | {{.*}}/Inputs/module/ModTopSub2.h +// CHECK: File | user | {{.*}}/Inputs/module/ModTopSub1.h +// CHECK: File | user | {{.*}}/Inputs/module/ModTop.h +// CHECK: DEPEND END (3) + +// CHECK: INCLUDE START +// CHECK: INCLUDE END (0) + +// CHECK: {{.*}}/Inputs/module/ModTop.h +// CHECK: 2:9 | struct/C | | c:{{.*}} | | Def | rel: 0 +// CHECK: 2:19 | type-alias/C | ModTopStruct | [[ModTopStruct_USR:.*]] | | Def | rel: 0 +// CHECK: 4:6 | function/C | ModTop_func | {{.*}} | __Z11ModTop_funcv | Decl | rel: 0 + +// CHECK: {{.*}}/Inputs/module/ModTopSub1.h +// CHECK: 1:6 | function/C | ModTopSub1_func | {{.*}} | __Z15ModTopSub1_funcv | Decl | rel: 0 + + + +// CHECK: ModDep.pcm + +// CHECK: is-system: 0 +// CHECK: is-module: 1 +// CHECK: module-name: ModDep +// CHECK: has-main: 0 +// CHECK: main-path: {{$}} +// CHECK: out-file: {{.*}}/ModDep.pcm + +// CHECK: DEPEND START +// CHECK: File | user | {{.*}}/Inputs/module/ModDep.h +// CHECK: Module | user | {{.*}}/ModTop.pcm +// CHECK: DEPEND END (2) + +// CHECK: INCLUDE START +// CHECK: INCLUDE END (0) + +// CHECK: {{.*}}/Inputs/module/ModDep.h +// CHECK: 3:6 | function/C | ModDep_func | [[ModDep_func_USR:.*]] | __Z11ModDep_func12ModTopStruct | Decl | rel: 0 +// CHECK: 3:18 | type-alias/C | ModTopStruct | [[ModTopStruct_USR]] | | Ref,RelCont | rel: 1 +// CHECK-NEXT: RelCont | ModDep_func | [[ModDep_func_USR]] + + + +// CHECK: ModSystem.pcm + +// CHECK: is-system: 1 +// CHECK: is-module: 1 +// CHECK: module-name: ModSystem +// CHECK: has-main: 0 +// CHECK: main-path: {{$}} +// CHECK: out-file: {{.*}}/ModSystem.pcm + +// CHECK: DEPEND START +// CHECK: File | system | {{.*}}/Inputs/module/ModSystem.h +// CHECK: DEPEND END (1) + +// CHECK: INCLUDE START +// CHECK: INCLUDE END (0) + +// CHECK: {{.*}}/Inputs/module/ModSystem.h +// CHECK: 2:9 | struct/C | | {{.*}} | | Def | rel: 0 +// CHECK: 2:19 | type-alias/C | ModSystemStruct | {{.*}} | | Def | rel: 0 +// CHECK: 4:6 | function/C | ModSystem_func | {{.*}} | __Z14ModSystem_funcv | Decl | rel: 0 + + + +// CHECK: index-unit.mm.o + +// CHECK: is-system: 0 +// CHECK: is-module: 0 +// CHECK: module-name: {{$}} +// CHECK: has-main: 1 +// CHECK: main-path: {{.*}}/index-unit.mm +// CHECK: out-file: {{.*}}/index-unit.mm.o + +// CHECK: DEPEND START +// CHECK: File | user | {{.*}}/index-unit.mm +// CHECK: File | user | {{.*}}/Inputs/module/module.modulemap +// CHECK: File | user | {{.*}}/Inputs/transitive-include.h +// CHECK: File | system | {{.*}}/Inputs/sys/system-head.h +// CHECK: Module | user | {{.*}}/ModDep.pcm +// CHECK: Module | system | {{.*}}/ModSystem.pcm +// CHECK: DEPEND END (6) + +// CHECK: INCLUDE START +// CHECK: {{.*}}index-unit.mm:[[@LINE+1]] -> {{.*}}/Inputs/transitive-include.h +#include "transitive-include.h" +// CHECK: {{.*}}/Inputs/transitive-include.h:1 -> {{.*}}/Inputs/sys/system-head.h +// CHECK: INCLUDE END (2) + +// CHECK: {{.*}}/Inputs/transitive-include.h +// CHECK: 3:8 | struct/C | Point | [[Point_USR:.*]] | | Def | rel: 0 +// CHECK: 4:7 | field/C | x | {{.*}} | | Def,RelChild | rel: 1 +// CHECK-NEXT: RelChild | Point | [[Point_USR]] +// CHECK: 5:7 | field/C | y | {{.*}} | | Def,RelChild | rel: 1 +// CHECK-NEXT: RelChild | Point | [[Point_USR]] + +// CHECK: {{.*}}/Inputs/sys/system-head.h +// CHECK: 19:12 | class/ObjC | Base | [[Base_USR:.*]] | _OBJC_CLASS_$_Base | Decl | rel: 0 +// CHECK: 23:11 | protocol/ObjC | Prot1 | [[Prot1_USR:.*]] | | Decl | rel: 0 +// CHECK: 29:11 | protocol/ObjC | Prot2 | [[Prot2_USR:.*]] | | Decl | rel: 0 +// CHECK: 29:17 | protocol/ObjC | Prot1 | [[Prot1_USR]] | | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | Prot2 | [[Prot2_USR]] +// CHECK: 39:12 | class/ObjC | Sub | [[Sub_USR:.*]] | _OBJC_CLASS_$_Sub | Decl | rel: 0 +// CHECK: 39:18 | class/ObjC | Base | [[Base_USR]] | _OBJC_CLASS_$_Base | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | Sub | [[Sub_USR]] +// CHECK: 39:23 | protocol/ObjC | Prot2 | [[Prot2_USR]] | | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | Sub | [[Sub_USR]] +// CHECK: 39:30 | protocol/ObjC | Prot1 | [[Prot1_USR]] | | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | Sub | [[Sub_USR]] +// CHECK: 41:8 | instance-method/ObjC | getit | {{.*}} | -[Sub getit] | Decl,Dyn,RelChild | rel: 1 +// CHECK-NEXT: RelChild | Sub | [[Sub_USR]] +// CHECK: 45:7 | class/C++ | Cls | [[Cls_USR:.*]] | | Def | rel: 0 +// CHECK: 50:7 | class/C++ | SubCls1 | [[SubCls1_USR:.*]] | | Def | rel: 0 +// CHECK: 50:24 | class/C++ | Cls | [[Cls_USR]] | | Ref,RelBase,RelCont | rel: 1 +// CHECK-NEXT: RelBase,RelCont | SubCls1 | [[SubCls1_USR]] +// CHECK: 52:12 | field/C++ | f | {{.*}} | | Def,RelChild | rel: 1 +// CHECK-NEXT: RelChild | SubCls1 | [[SubCls1_USR]] Index: test/Index/Store/assembly-invocation.c =================================================================== --- /dev/null +++ test/Index/Store/assembly-invocation.c @@ -0,0 +1,3 @@ +// Make sure it doesn't crash. +// RUN: %clang -target x86_64-apple-macosx10.7 -S %s -o %t.s +// RUN: %clang -target x86_64-apple-macosx10.7 -c %t.s -o %t.o -index-store-path %t.idx Index: tools/c-index-test/core_main.cpp =================================================================== --- tools/c-index-test/core_main.cpp +++ tools/c-index-test/core_main.cpp @@ -12,15 +12,17 @@ #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendAction.h" -#include "clang/Index/IndexingAction.h" +#include "clang/Index/CodegenNameGenerator.h" #include "clang/Index/IndexDataConsumer.h" #include "clang/Index/USRGeneration.h" -#include "clang/Index/CodegenNameGenerator.h" +#include "clang/Index/UnitIndexDataConsumer.h" +#include "clang/Index/UnitIndexingAction.h" #include "clang/Serialization/ASTReader.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/PrettyStackTrace.h" using namespace clang; using namespace clang::index; @@ -33,18 +35,20 @@ enum class ActionType { None, PrintSourceSymbols, + PrintSourceUnit, }; namespace options { static cl::OptionCategory IndexTestCoreCategory("index-test-core options"); -static cl::opt -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::opt Action( + cl::desc("Action:"), cl::init(ActionType::None), + cl::values(clEnumValN(ActionType::PrintSourceSymbols, + "print-source-symbols", "Print symbols from source"), + clEnumValN(ActionType::PrintSourceUnit, "print-source-unit", + "Print unit info from source")), + cl::cat(IndexTestCoreCategory)); static cl::extrahelp MoreHelp( "\nAdd \"-- \" at the end to setup the compiler " @@ -72,6 +76,42 @@ static void printSymbolNameAndUSR(const Decl *D, ASTContext &Ctx, raw_ostream &OS); +static void printDeclOccurrence(const Decl *D, SymbolRoleSet Roles, + ArrayRef Relations, FileID FID, + unsigned Offset, bool IsInSystemFile, + CodegenNameGenerator &CGNameGen, + raw_ostream &OS) { + 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 << " | "; + + if (CGNameGen.writeName(D, OS)) + 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'; + } +} + namespace { class PrintIndexDataConsumer : public IndexDataConsumer { @@ -87,44 +127,17 @@ } bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, - ArrayRef Relations, - FileID FID, unsigned Offset, + ArrayRef Relations, FileID FID, + unsigned Offset, bool IsInSystemFile, 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 << " | "; - - if (CGNameGen->writeName(D, OS)) - 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'; - } - + printDeclOccurrence(D, Roles, Relations, FID, Offset, IsInSystemFile, + *CGNameGen, OS); return true; } bool handleModuleOccurence(const ImportDecl *ImportD, SymbolRoleSet Roles, - FileID FID, unsigned Offset) override { + FileID FID, unsigned Offset, + bool IsInSystemFile) override { ASTContext &Ctx = ImportD->getASTContext(); SourceManager &SM = Ctx.getSourceManager(); @@ -235,6 +248,156 @@ return false; } +class PrintUnitDataConsumer : public UnitIndexDataConsumer { + struct Dependency { + enum Kind { File, Module }; + + Kind Kind; + std::string Name; + bool IsSystem; + + void print(raw_ostream &OS) const { + switch (Kind) { + case File: + OS << "File"; + break; + case Module: + OS << "Module"; + break; + } + OS << " | " << (IsSystem ? "system" : "user") << " | " << Name << '\n'; + } + }; + + struct Include { + std::string Source; + std::string Target; + unsigned Line; + + void print(raw_ostream &OS) const { + OS << Source << ':' << Line << " -> " << Target << '\n'; + } + }; + + struct FileOccurrences { + SourceManager &SM; + FileID FID; + bool IsSystem; + std::vector Occurrences; + + void print(raw_ostream &OS, CodegenNameGenerator &CGNameGen) const { + const FileEntry *FE = SM.getFileEntryForID(FID); + OS << '\n' << FE->getName() << "\n----------\n"; + for (const DeclOccurrence &Occur : Occurrences) { + printDeclOccurrence(Occur.Dcl, Occur.Roles, Occur.Relations, FID, + Occur.Offset, IsSystem, CGNameGen, OS); + } + } + }; + + raw_ostream &OS; + UnitDetails UnitInfo; + const CompilerInstance &CI; + CodegenNameGenerator CGNameGen; + bool IndexModDependencies = true; + std::vector Dependencies; + std::vector Includes; + std::vector FileOccurInfos; + +public: + PrintUnitDataConsumer(raw_ostream &OS, UnitDetails UnitInfo, + bool IndexModDeps) + : OS(OS), UnitInfo(UnitInfo), CI(UnitInfo.CI), + CGNameGen(CI.getASTContext()), IndexModDependencies(IndexModDeps) {} + + void handleFileDependency(const FileEntry *FE, bool IsSystem) override { + Dependencies.push_back({Dependency::File, FE->getName(), IsSystem}); + } + + void handleModuleImport(const serialization::ModuleFile &Mod, + bool IsSystem) override { + Dependencies.push_back({Dependency::Module, Mod.FileName, IsSystem}); + } + + void handleInclude(const FileEntry *Source, unsigned Line, + const FileEntry *Target) override { + Includes.push_back({Source->getName(), Target->getName(), Line}); + } + + bool + shouldIndexModuleDependency(const serialization::ModuleFile &Mod) override { + return IndexModDependencies; + } + + bool handleFileOccurrences(FileID FID, + ArrayRef OccurrencesSortedByOffset, + bool IsSystem) override { + SourceManager &SM = CI.getASTContext().getSourceManager(); + FileOccurInfos.push_back({SM, FID, IsSystem, OccurrencesSortedByOffset}); + return false; + } + + void finish() override { + OS << sys::path::filename(UnitInfo.OutputFile) << '\n' + << "----------\n" + << "is-system: " << UnitInfo.IsSystemUnit << '\n' + << "is-module: " << UnitInfo.IsModuleUnit << '\n' + << "module-name: " << UnitInfo.ModuleName << '\n' + << "has-main: " << !!UnitInfo.RootFile << '\n' + << "main-path: " + << (UnitInfo.RootFile ? UnitInfo.RootFile->getName() : "") << '\n' + << "out-file: " << UnitInfo.OutputFile << '\n' + << "target: " << UnitInfo.CI.getTargetOpts().Triple << '\n' + << "is-debug: " << UnitInfo.IsDebugCompilation << '\n'; + + OS << "\nDEPEND START\n"; + for (const Dependency &Dep : Dependencies) { + Dep.print(OS); + } + OS << "DEPEND END (" << Dependencies.size() << ")\n"; + OS << "\nINCLUDE START\n"; + for (const Include &Inc : Includes) { + Inc.print(OS); + } + OS << "INCLUDE END (" << Includes.size() << ")\n"; + for (const FileOccurrences &FileInfo : FileOccurInfos) { + FileInfo.print(OS, CGNameGen); + } + OS << '\n'; + } +}; + +static bool printSourceUnit(ArrayRef Args, bool IndexLocals, + bool IndexModDeps) { + SmallVector ArgsWithProgName; + ArgsWithProgName.push_back("clang"); + ArgsWithProgName.append(Args.begin(), Args.end()); + IntrusiveRefCntPtr Diags( + CompilerInstance::createDiagnostics(new DiagnosticOptions)); + auto CInvok = createInvocationFromCommandLine(ArgsWithProgName, Diags); + if (!CInvok) + return true; + + raw_ostream &OS = outs(); + UnitIndexingOptions IndexOpts; + IndexOpts.IndexFunctionLocals = IndexLocals; + + auto ConsumerFactory = [&OS, IndexModDeps](UnitDetails UnitInfo) { + return llvm::make_unique(OS, std::move(UnitInfo), + IndexModDeps); + }; + + std::unique_ptr IndexAction; + IndexAction = createUnitIndexingAction(ConsumerFactory, IndexOpts, + /*WrappedAction=*/nullptr); + + auto PCHContainerOps = std::make_shared(); + std::unique_ptr Unit(ASTUnit::LoadFromCompilerInvocationAction( + std::move(CInvok), PCHContainerOps, Diags, IndexAction.get())); + + return !Unit; +} + //===----------------------------------------------------------------------===// // Helper Utils //===----------------------------------------------------------------------===// @@ -305,5 +468,15 @@ return printSourceSymbols(CompArgs, options::DumpModuleImports, options::IncludeLocals); } + if (options::Action == ActionType::PrintSourceUnit) { + if (CompArgs.empty()) { + errs() + << "error: missing compiler args; pass '-- '\n"; + return 1; + } + return printSourceUnit(CompArgs, options::IncludeLocals, + /*IndexModDepedencies=*/true); + } + return 0; } Index: tools/diagtool/DiagnosticNames.cpp =================================================================== --- tools/diagtool/DiagnosticNames.cpp +++ tools/diagtool/DiagnosticNames.cpp @@ -43,6 +43,7 @@ #include "clang/Basic/DiagnosticSemaKinds.inc" #include "clang/Basic/DiagnosticAnalysisKinds.inc" #include "clang/Basic/DiagnosticRefactoringKinds.inc" +#include "clang/Basic/DiagnosticIndexKinds.inc" #undef DIAG }; Index: tools/libclang/CXIndexDataConsumer.h =================================================================== --- tools/libclang/CXIndexDataConsumer.h +++ tools/libclang/CXIndexDataConsumer.h @@ -463,12 +463,12 @@ private: bool handleDeclOccurence(const Decl *D, index::SymbolRoleSet Roles, ArrayRef Relations, - FileID FID, unsigned Offset, + FileID FID, unsigned Offset, bool IsInSystemFile, ASTNodeInfo ASTNode) override; bool handleModuleOccurence(const ImportDecl *ImportD, - index::SymbolRoleSet Roles, - FileID FID, unsigned Offset) override; + index::SymbolRoleSet Roles, FileID FID, + unsigned Offset, bool IsInSystemFile) override; void finish() override; Index: tools/libclang/CXIndexDataConsumer.cpp =================================================================== --- tools/libclang/CXIndexDataConsumer.cpp +++ tools/libclang/CXIndexDataConsumer.cpp @@ -150,11 +150,9 @@ }; } -bool CXIndexDataConsumer::handleDeclOccurence(const Decl *D, - SymbolRoleSet Roles, - ArrayRef Relations, - FileID FID, unsigned Offset, - ASTNodeInfo ASTNode) { +bool CXIndexDataConsumer::handleDeclOccurence( + const Decl *D, SymbolRoleSet Roles, ArrayRef Relations, + FileID FID, unsigned Offset, bool IsInSystemFile, ASTNodeInfo ASTNode) { SourceLocation Loc = getASTContext().getSourceManager() .getLocForStartOfFile(FID).getLocWithOffset(Offset); @@ -219,9 +217,9 @@ } bool CXIndexDataConsumer::handleModuleOccurence(const ImportDecl *ImportD, - SymbolRoleSet Roles, - FileID FID, - unsigned Offset) { + SymbolRoleSet Roles, FileID FID, + unsigned Offset, + bool IsInSystemFile) { IndexingDeclVisitor(*this, SourceLocation(), nullptr).Visit(ImportD); return !shouldAbort(); }