diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index e6ef410be4..cadf2810b9 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -623,6 +623,9 @@ public: /// \returns true if the iteration was complete or false if it was aborted. bool visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn); + /// \brief Get the PCH file if one was included. + const FileEntry *getPCHFile(); + llvm::MemoryBuffer *getBufferForFile(StringRef Filename, std::string *ErrorStr = 0); diff --git a/lib/Frontend/ASTUnit.cpp b/lib/Frontend/ASTUnit.cpp index 79559a3dcd..136e72a6c6 100644 --- a/lib/Frontend/ASTUnit.cpp +++ b/lib/Frontend/ASTUnit.cpp @@ -2816,6 +2816,42 @@ bool ASTUnit::visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn) { return true; } +namespace { +struct PCHLocatorInfo { + serialization::ModuleFile *Mod; + PCHLocatorInfo() : Mod(0) {} +}; +} + +static bool PCHLocator(serialization::ModuleFile &M, void *UserData) { + PCHLocatorInfo &Info = *static_cast(UserData); + switch (M.Kind) { + case serialization::MK_Module: + return true; // skip dependencies. + case serialization::MK_PCH: + Info.Mod = &M; + return true; // found it. + case serialization::MK_Preamble: + return false; // look in dependencies. + case serialization::MK_MainFile: + return false; // look in dependencies. + } + + return true; +} + +const FileEntry *ASTUnit::getPCHFile() { + if (!Reader) + return 0; + + PCHLocatorInfo Info; + Reader->getModuleManager().visit(PCHLocator, &Info); + if (Info.Mod) + return Info.Mod->File; + + return 0; +} + void ASTUnit::PreambleData::countLines() const { NumLines = 0; if (empty()) diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp index 6cf3a637ac..0b12d82d30 100644 --- a/tools/libclang/Indexing.cpp +++ b/tools/libclang/Indexing.cpp @@ -197,13 +197,20 @@ public: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { + PreprocessorOptions &PPOpts = CI.getPreprocessorOpts(); + // We usually disable the preprocessing record for indexing even if the // original preprocessing options had it enabled. Now that the indexing // Preprocessor has been created (without a preprocessing record), re-enable // the option in case modules are enabled, so that the detailed record // option can be propagated when the module file is generated. if (CI.getLangOpts().Modules && EnablePPDetailedRecordForModules) - CI.getPreprocessorOpts().DetailedRecord = true; + PPOpts.DetailedRecord = true; + + if (!PPOpts.ImplicitPCHInclude.empty()) { + IndexCtx.importedPCH( + CI.getFileManager().getFile(PPOpts.ImplicitPCHInclude)); + } IndexCtx.setASTContext(CI.getASTContext()); Preprocessor &PP = CI.getPreprocessor(); @@ -536,6 +543,9 @@ static void clang_indexTranslationUnit_Impl(void *UserData) { ASTUnit::ConcurrencyCheck Check(*Unit); + if (const FileEntry *PCHFile = Unit->getPCHFile()) + IndexCtx->importedPCH(PCHFile); + FileManager &FileMgr = Unit->getFileManager(); if (Unit->getOriginalSourceFileName().empty()) diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp index c964e963c7..1186191cc3 100644 --- a/tools/libclang/IndexingContext.cpp +++ b/tools/libclang/IndexingContext.cpp @@ -273,6 +273,21 @@ void IndexingContext::importedModule(const ImportDecl *ImportD) { (void)astFile; } +void IndexingContext::importedPCH(const FileEntry *File) { + if (!CB.importedASTFile) + return; + + CXIdxImportedASTFileInfo Info = { + (CXFile)File, + getIndexLoc(SourceLocation()), + /*isModule=*/false, + /*isImplicit=*/false, + /*moduleName=*/NULL + }; + CXIdxClientASTFile astFile = CB.importedASTFile(ClientData, &Info); + (void)astFile; +} + void IndexingContext::startedTranslationUnit() { CXIdxClientContainer idxCont = 0; if (CB.startedTranslationUnit) diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h index e556d4dd5f..e92894ae66 100644 --- a/tools/libclang/IndexingContext.h +++ b/tools/libclang/IndexingContext.h @@ -383,6 +383,7 @@ public: bool isImport, bool isAngled); void importedModule(const ImportDecl *ImportD); + void importedPCH(const FileEntry *File); void startedTranslationUnit();