From 1f76c4e8101b9beaf8f1b10a57faa80256ab2b05 Mon Sep 17 00:00:00 2001 From: Manuel Klimek <klimek@google.com> Date: Thu, 24 Oct 2013 07:51:24 +0000 Subject: [PATCH] Use the same SourceManager for ModuleMaps and compilations. This allows using virtual file mappings on the original SourceManager to map in virtual module.map files. Without this patch, the ModuleMap search will find a module.map file (as the FileEntry exists in the FileManager), but will be unable to get the content from the SourceManager (as ModuleMap previously created its own SourceManager). Two problems needed to be fixed which this patch exposed: 1. Storing the inferred module map When writing out a module, the ASTWriter stores the names of the files in the main source manager; when loading the AST again, the ASTReader errs out if such a file is found missing, unless it is overridden. Previously CompilerInstance's compileModule method would store the inferred module map to a temporary file; the problem with this approach is that now that the module map is handled by the main source manager, the ASTWriter stores the name of the temporary module map as source to the compilation; later, when the module is loaded, the temporary file has already been deleted, which leads to a compilation error. This patch changes the inferred module map to instead inject a virtual file into the source manager. This both saves some disk IO, and works with how the ASTWriter/ASTReader handle overridden source files. 2. Changing test input in test/Modules/Inputs/* Now that the module map file is handled by the main source manager, the VerifyDiagnosticConsumer will not ignore diagnostics created while parsing the module map file. The module test test/Modules/renamed.m uses -I test/Modules/Inputs and triggers recursive loading of all module maps in test/Modules/Inputs, some of which had conflicting names, thus leading errors while parsing the module maps. Those diagnostics already occur on trunk, but before this patch they would not break the test, as they were ignored by the VerifyDiagnosticConsumer. This patch thus changes the module maps that have been recently introduced which broke the invariant of compatible modules maps in test/Modules/Inputs. llvm-svn: 193314 --- clang/include/clang/Lex/HeaderSearch.h | 2 +- clang/include/clang/Lex/ModuleMap.h | 10 ++-- clang/lib/Frontend/ASTUnit.cpp | 2 +- clang/lib/Frontend/CompilerInstance.cpp | 47 +++++++++---------- clang/lib/Lex/HeaderSearch.cpp | 6 +-- clang/lib/Lex/ModuleMap.cpp | 36 +++++++------- .../Modules/Inputs/declare-use/module.map | 36 +++++++------- clang/test/Modules/Inputs/private1/module.map | 2 +- clang/test/Modules/Inputs/private2/module.map | 2 +- clang/test/Modules/declare-use1.cpp | 2 +- clang/test/Modules/declare-use2.cpp | 2 +- clang/test/Modules/private1.cpp | 2 +- clang/unittests/Basic/SourceManagerTest.cpp | 6 +-- clang/unittests/Lex/LexerTest.cpp | 2 +- clang/unittests/Lex/PPCallbacksTest.cpp | 5 +- .../Lex/PPConditionalDirectiveRecordTest.cpp | 2 +- clang/unittests/Tooling/ToolingTest.cpp | 20 ++++++++ 17 files changed, 99 insertions(+), 85 deletions(-) diff --git a/clang/include/clang/Lex/HeaderSearch.h b/clang/include/clang/Lex/HeaderSearch.h index 84dd6eb44117..fb1a86206354 100644 --- a/clang/include/clang/Lex/HeaderSearch.h +++ b/clang/include/clang/Lex/HeaderSearch.h @@ -240,7 +240,7 @@ class HeaderSearch { public: HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts, - FileManager &FM, DiagnosticsEngine &Diags, + SourceManager &SourceMgr, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target); ~HeaderSearch(); diff --git a/clang/include/clang/Lex/ModuleMap.h b/clang/include/clang/Lex/ModuleMap.h index b7982a17aa56..3a17157f94d5 100644 --- a/clang/include/clang/Lex/ModuleMap.h +++ b/clang/include/clang/Lex/ModuleMap.h @@ -37,7 +37,7 @@ class HeaderSearch; class ModuleMapParser; class ModuleMap { - SourceManager *SourceMgr; + SourceManager &SourceMgr; IntrusiveRefCntPtr<DiagnosticsEngine> Diags; const LangOptions &LangOpts; const TargetInfo *Target; @@ -178,9 +178,9 @@ private: public: /// \brief Construct a new module map. /// - /// \param FileMgr The file manager used to find module files and headers. - /// This file manager should be shared with the header-search mechanism, since - /// they will refer to the same headers. + /// \param SourceMgr The source manager used to find module files and headers. + /// This source manager should be shared with the header-search mechanism, + /// since they will refer to the same headers. /// /// \param DC A diagnostic consumer that will be cloned for use in generating /// diagnostics. @@ -188,7 +188,7 @@ public: /// \param LangOpts Language options for this translation unit. /// /// \param Target The target for this translation unit. - ModuleMap(FileManager &FileMgr, DiagnosticConsumer &DC, + ModuleMap(SourceManager &SourceMgr, DiagnosticConsumer &DC, const LangOptions &LangOpts, const TargetInfo *Target, HeaderSearch &HeaderInfo); diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 610c20d9fb14..a8c587638a28 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -707,7 +707,7 @@ ASTUnit *ASTUnit::LoadFromASTFile(const std::string &Filename, AST->HSOpts = new HeaderSearchOptions(); AST->HeaderInfo.reset(new HeaderSearch(AST->HSOpts, - AST->getFileManager(), + AST->getSourceManager(), AST->getDiagnostics(), AST->ASTFileLangOpts, /*Target=*/0)); diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index 9f0ca3b31e92..5d3fd456c44b 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -218,7 +218,7 @@ void CompilerInstance::createPreprocessor() { // Create the Preprocessor. HeaderSearch *HeaderInfo = new HeaderSearch(&getHeaderSearchOpts(), - getFileManager(), + getSourceManager(), getDiagnostics(), getLangOpts(), &getTarget()); @@ -851,29 +851,6 @@ static void compileModule(CompilerInstance &ImportingInstance, FrontendOpts.Inputs.clear(); InputKind IK = getSourceInputKindFromOptions(*Invocation->getLangOpts()); - // Get or create the module map that we'll use to build this module. - SmallString<128> TempModuleMapFileName; - if (const FileEntry *ModuleMapFile - = ModMap.getContainingModuleMapFile(Module)) { - // Use the module map where this module resides. - FrontendOpts.Inputs.push_back(FrontendInputFile(ModuleMapFile->getName(), - IK)); - } else { - // Create a temporary module map file. - int FD; - if (llvm::sys::fs::createTemporaryFile(Module->Name, "map", FD, - TempModuleMapFileName)) { - ImportingInstance.getDiagnostics().Report(diag::err_module_map_temp_file) - << TempModuleMapFileName; - return; - } - // Print the module map to this file. - llvm::raw_fd_ostream OS(FD, /*shouldClose=*/true); - Module->print(OS); - FrontendOpts.Inputs.push_back( - FrontendInputFile(TempModuleMapFileName.str().str(), IK)); - } - // Don't free the remapped file buffers; they are owned by our caller. PPOpts.RetainRemappedFileBuffers = true; @@ -900,6 +877,26 @@ static void compileModule(CompilerInstance &ImportingInstance, SourceMgr.pushModuleBuildStack(Module->getTopLevelModuleName(), FullSourceLoc(ImportLoc, ImportingInstance.getSourceManager())); + // Get or create the module map that we'll use to build this module. + std::string InferredModuleMapContent; + if (const FileEntry *ModuleMapFile = + ModMap.getContainingModuleMapFile(Module)) { + // Use the module map where this module resides. + FrontendOpts.Inputs.push_back( + FrontendInputFile(ModuleMapFile->getName(), IK)); + } else { + llvm::raw_string_ostream OS(InferredModuleMapContent); + Module->print(OS); + OS.flush(); + FrontendOpts.Inputs.push_back( + FrontendInputFile("__inferred_module.map", IK)); + + const llvm::MemoryBuffer *ModuleMapBuffer = + llvm::MemoryBuffer::getMemBuffer(InferredModuleMapContent); + ModuleMapFile = Instance.getFileManager().getVirtualFile( + "__inferred_module.map", InferredModuleMapContent.size(), 0); + SourceMgr.overrideFileContents(ModuleMapFile, ModuleMapBuffer); + } // Construct a module-generating action. GenerateModuleAction CreateModuleAction(Module->IsSystem); @@ -917,8 +914,6 @@ static void compileModule(CompilerInstance &ImportingInstance, // be nice to do this with RemoveFileOnSignal when we can. However, that // doesn't make sense for all clients, so clean this up manually. Instance.clearOutputFiles(/*EraseFiles=*/true); - if (!TempModuleMapFileName.empty()) - llvm::sys::fs::remove(TempModuleMapFileName.str()); // We've rebuilt a module. If we're allowed to generate or update the global // module index, record that fact in the importing compiler instance. diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index 84d205acdaec..2da2c9efba9e 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -44,11 +44,11 @@ HeaderFileInfo::getControllingMacro(ExternalIdentifierLookup *External) { ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {} HeaderSearch::HeaderSearch(IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts, - FileManager &FM, DiagnosticsEngine &Diags, + SourceManager &SourceMgr, DiagnosticsEngine &Diags, const LangOptions &LangOpts, const TargetInfo *Target) - : HSOpts(HSOpts), FileMgr(FM), FrameworkMap(64), - ModMap(FileMgr, *Diags.getClient(), LangOpts, Target, *this) + : HSOpts(HSOpts), FileMgr(SourceMgr.getFileManager()), FrameworkMap(64), + ModMap(SourceMgr, *Diags.getClient(), LangOpts, Target, *this) { AngledDirIdx = 0; SystemDirIdx = 0; diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 25d68ace0f19..54007c78d839 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -83,18 +83,18 @@ Module *ModuleMap::resolveModuleId(const ModuleId &Id, Module *Mod, return Context; } -ModuleMap::ModuleMap(FileManager &FileMgr, DiagnosticConsumer &DC, +ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticConsumer &DC, const LangOptions &LangOpts, const TargetInfo *Target, HeaderSearch &HeaderInfo) - : LangOpts(LangOpts), Target(Target), HeaderInfo(HeaderInfo), - BuiltinIncludeDir(0), CompilingModule(0), SourceModule(0) -{ + : SourceMgr(SourceMgr), LangOpts(LangOpts), Target(Target), + HeaderInfo(HeaderInfo), BuiltinIncludeDir(0), CompilingModule(0), + SourceModule(0) { IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); Diags = IntrusiveRefCntPtr<DiagnosticsEngine>( new DiagnosticsEngine(DiagIDs, new DiagnosticOptions)); Diags->setClient(new ForwardingDiagnosticConsumer(DC), /*ShouldOwnClient=*/true); - SourceMgr = new SourceManager(*Diags, FileMgr); + Diags->setSourceManager(&SourceMgr); } ModuleMap::~ModuleMap() { @@ -103,8 +103,6 @@ ModuleMap::~ModuleMap() { I != IEnd; ++I) { delete I->getValue(); } - - delete SourceMgr; } void ModuleMap::setTarget(const TargetInfo &Target) { @@ -224,7 +222,7 @@ ModuleMap::findModuleForHeader(const FileEntry *File, // frameworks moving from top-level frameworks to embedded frameworks tend // to be symlinked from the top-level location to the embedded location, // and we need to resolve lookups as if we had found the embedded location. - StringRef DirName = SourceMgr->getFileManager().getCanonicalName(Dir); + StringRef DirName = SourceMgr.getFileManager().getCanonicalName(Dir); // Keep walking up the directory hierarchy, looking for a directory with // an umbrella header. @@ -301,7 +299,7 @@ ModuleMap::findModuleForHeader(const FileEntry *File, break; // Resolve the parent path to a directory entry. - Dir = SourceMgr->getFileManager().getDirectory(DirName); + Dir = SourceMgr.getFileManager().getDirectory(DirName); } while (Dir); return KnownHeader(); @@ -375,7 +373,7 @@ bool ModuleMap::isHeaderInUnavailableModule(const FileEntry *Header) const { break; // Resolve the parent path to a directory entry. - Dir = SourceMgr->getFileManager().getDirectory(DirName); + Dir = SourceMgr.getFileManager().getDirectory(DirName); } while (Dir); return false; @@ -480,7 +478,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, if (Module *Mod = lookupModuleQualified(ModuleName, Parent)) return Mod; - FileManager &FileMgr = SourceMgr->getFileManager(); + FileManager &FileMgr = SourceMgr.getFileManager(); // If the framework has a parent path from which we're allowed to infer // a framework module, do so. @@ -492,7 +490,7 @@ ModuleMap::inferFrameworkModule(StringRef ModuleName, // top-level framework, and we need to infer as if we were naming the // top-level framework. StringRef FrameworkDirName - = SourceMgr->getFileManager().getCanonicalName(FrameworkDir); + = SourceMgr.getFileManager().getCanonicalName(FrameworkDir); bool canInfer = false; if (llvm::sys::path::has_parent_path(FrameworkDirName)) { @@ -654,11 +652,11 @@ void ModuleMap::addHeader(Module *Mod, const FileEntry *Header, const FileEntry * ModuleMap::getContainingModuleMapFile(Module *Module) const { - if (Module->DefinitionLoc.isInvalid() || !SourceMgr) + if (Module->DefinitionLoc.isInvalid()) return 0; - return SourceMgr->getFileEntryForID( - SourceMgr->getFileID(Module->DefinitionLoc)); + return SourceMgr.getFileEntryForID( + SourceMgr.getFileID(Module->DefinitionLoc)); } void ModuleMap::dump() { @@ -2110,15 +2108,15 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File, bool IsSystem) { return Known->second; assert(Target != 0 && "Missing target information"); - FileID ID = SourceMgr->createFileID(File, SourceLocation(), SrcMgr::C_User); - const llvm::MemoryBuffer *Buffer = SourceMgr->getBuffer(ID); + FileID ID = SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User); + const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(ID); if (!Buffer) return ParsedModuleMap[File] = true; // Parse this module map file. - Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts); + Lexer L(ID, SourceMgr.getBuffer(ID), SourceMgr, MMapLangOpts); Diags->getClient()->BeginSourceFile(MMapLangOpts); - ModuleMapParser Parser(L, *SourceMgr, Target, *Diags, *this, File->getDir(), + ModuleMapParser Parser(L, SourceMgr, Target, *Diags, *this, File->getDir(), BuiltinIncludeDir, IsSystem); bool Result = Parser.parseModuleMapFile(); Diags->getClient()->EndSourceFile(); diff --git a/clang/test/Modules/Inputs/declare-use/module.map b/clang/test/Modules/Inputs/declare-use/module.map index ae3e90801ec0..774fc37760c9 100644 --- a/clang/test/Modules/Inputs/declare-use/module.map +++ b/clang/test/Modules/Inputs/declare-use/module.map @@ -1,43 +1,43 @@ -module A { +module XA { header "a.h" } -module B { +module XB { header "b.h" } -module C { +module XC { header "c.h" - use A + use XA } -module D { +module XD { header "d.h" - use A + use XA } -module E { +module XE { header "e.h" - use A - use B + use XA + use XB } -module F { +module XF { header "f.h" - use A - use B + use XA + use XB } -module G { +module XG { header "g.h" header "g1.h" - use C - use E + use XC + use XE } -module H { +module XH { header "h.h" header "h1.h" - use C - use E + use XC + use XE } diff --git a/clang/test/Modules/Inputs/private1/module.map b/clang/test/Modules/Inputs/private1/module.map index 445c8010db9b..0904fe68a62c 100644 --- a/clang/test/Modules/Inputs/private1/module.map +++ b/clang/test/Modules/Inputs/private1/module.map @@ -1,4 +1,4 @@ -module libPrivate1 { +module libPrivate { header "public1.h" private header "private1.h" } diff --git a/clang/test/Modules/Inputs/private2/module.map b/clang/test/Modules/Inputs/private2/module.map index 6c5efb60209d..3d2a5786f9b1 100644 --- a/clang/test/Modules/Inputs/private2/module.map +++ b/clang/test/Modules/Inputs/private2/module.map @@ -1,4 +1,4 @@ -module libPrivate2 { +module libPrivateN2 { header "public2.h" private header "private2.h" } diff --git a/clang/test/Modules/declare-use1.cpp b/clang/test/Modules/declare-use1.cpp index 5bb7e2a47aff..4508017c12d2 100644 --- a/clang/test/Modules/declare-use1.cpp +++ b/clang/test/Modules/declare-use1.cpp @@ -1,5 +1,5 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodules-decluse -fmodule-name=G -I %S/Inputs/declare-use %s -verify +// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodules-decluse -fmodule-name=XG -I %S/Inputs/declare-use %s -verify #include "g.h" #include "e.h" diff --git a/clang/test/Modules/declare-use2.cpp b/clang/test/Modules/declare-use2.cpp index 807962cbdb4a..a2ec55e5e5ca 100644 --- a/clang/test/Modules/declare-use2.cpp +++ b/clang/test/Modules/declare-use2.cpp @@ -1,5 +1,5 @@ // RUN: rm -rf %t -// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodules-decluse -fmodule-name=H -I %S/Inputs/declare-use %s -verify +// RUN: %clang_cc1 -x objective-c++ -fmodules-cache-path=%t -fmodules -fmodules-decluse -fmodule-name=XH -I %S/Inputs/declare-use %s -verify #include "h.h" #include "e.h" diff --git a/clang/test/Modules/private1.cpp b/clang/test/Modules/private1.cpp index e4eec0a515c8..811a2333d1db 100644 --- a/clang/test/Modules/private1.cpp +++ b/clang/test/Modules/private1.cpp @@ -2,7 +2,7 @@ // RUN: %clang_cc1 -x objective-c -fmodules-cache-path=%t -fmodules -I %S/Inputs/private0 -I %S/Inputs/private1 -I %S/Inputs/private2 %s -verify #include "common.h" -@import libPrivate1; +@import libPrivateN2; #include "private1.h" // expected-error {{use of private header from outside its module}} #include "public2.h" #include "private2.h" // expected-error {{use of private header from outside its module}} diff --git a/clang/unittests/Basic/SourceManagerTest.cpp b/clang/unittests/Basic/SourceManagerTest.cpp index 8e7f4a0371af..d94cfe9c3fab 100644 --- a/clang/unittests/Basic/SourceManagerTest.cpp +++ b/clang/unittests/Basic/SourceManagerTest.cpp @@ -73,7 +73,7 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnit) { FileID mainFileID = SourceMgr.createMainFileIDForMemBuffer(buf); VoidModuleLoader ModLoader; - HeaderSearch HeaderInfo(new HeaderSearchOptions, FileMgr, Diags, LangOpts, + HeaderSearch HeaderInfo(new HeaderSearchOptions, SourceMgr, Diags, LangOpts, &*Target); Preprocessor PP(new PreprocessorOptions(), Diags, LangOpts, Target.getPtr(), SourceMgr, HeaderInfo, ModLoader, @@ -188,7 +188,7 @@ TEST_F(SourceManagerTest, getMacroArgExpandedLocation) { SourceMgr.overrideFileContents(headerFile, headerBuf); VoidModuleLoader ModLoader; - HeaderSearch HeaderInfo(new HeaderSearchOptions, FileMgr, Diags, LangOpts, + HeaderSearch HeaderInfo(new HeaderSearchOptions, SourceMgr, Diags, LangOpts, &*Target); Preprocessor PP(new PreprocessorOptions(), Diags, LangOpts, Target.getPtr(), SourceMgr, HeaderInfo, ModLoader, @@ -286,7 +286,7 @@ TEST_F(SourceManagerTest, isBeforeInTranslationUnitWithMacroInInclude) { SourceMgr.overrideFileContents(headerFile, headerBuf); VoidModuleLoader ModLoader; - HeaderSearch HeaderInfo(new HeaderSearchOptions, FileMgr, Diags, LangOpts, + HeaderSearch HeaderInfo(new HeaderSearchOptions, SourceMgr, Diags, LangOpts, &*Target); Preprocessor PP(new PreprocessorOptions(), Diags, LangOpts, Target.getPtr(), SourceMgr, HeaderInfo, ModLoader, diff --git a/clang/unittests/Lex/LexerTest.cpp b/clang/unittests/Lex/LexerTest.cpp index a8e25cb2a394..40ce928014d5 100644 --- a/clang/unittests/Lex/LexerTest.cpp +++ b/clang/unittests/Lex/LexerTest.cpp @@ -62,7 +62,7 @@ protected: (void) SourceMgr.createMainFileIDForMemBuffer(buf); VoidModuleLoader ModLoader; - HeaderSearch HeaderInfo(new HeaderSearchOptions, FileMgr, Diags, LangOpts, + HeaderSearch HeaderInfo(new HeaderSearchOptions, SourceMgr, Diags, LangOpts, Target.getPtr()); Preprocessor PP(new PreprocessorOptions(), Diags, LangOpts, Target.getPtr(), SourceMgr, HeaderInfo, ModLoader, /*IILookup =*/ 0, diff --git a/clang/unittests/Lex/PPCallbacksTest.cpp b/clang/unittests/Lex/PPCallbacksTest.cpp index fd407b52c6eb..9405a84024bd 100644 --- a/clang/unittests/Lex/PPCallbacksTest.cpp +++ b/clang/unittests/Lex/PPCallbacksTest.cpp @@ -162,7 +162,8 @@ protected: VoidModuleLoader ModLoader; IntrusiveRefCntPtr<HeaderSearchOptions> HSOpts = new HeaderSearchOptions(); - HeaderSearch HeaderInfo(HSOpts, FileMgr, Diags, LangOpts, Target.getPtr()); + HeaderSearch HeaderInfo(HSOpts, SourceMgr, Diags, LangOpts, + Target.getPtr()); AddFakeHeader(HeaderInfo, HeaderPath, SystemHeader); IntrusiveRefCntPtr<PreprocessorOptions> PPOpts = new PreprocessorOptions(); @@ -198,7 +199,7 @@ protected: (void)SourceMgr.createMainFileIDForMemBuffer(sourceBuf); VoidModuleLoader ModLoader; - HeaderSearch HeaderInfo(new HeaderSearchOptions, FileMgr, Diags, + HeaderSearch HeaderInfo(new HeaderSearchOptions, SourceMgr, Diags, OpenCLLangOpts, Target.getPtr()); Preprocessor PP(new PreprocessorOptions(), Diags, OpenCLLangOpts, diff --git a/clang/unittests/Lex/PPConditionalDirectiveRecordTest.cpp b/clang/unittests/Lex/PPConditionalDirectiveRecordTest.cpp index 082eced2d854..58857fa5a133 100644 --- a/clang/unittests/Lex/PPConditionalDirectiveRecordTest.cpp +++ b/clang/unittests/Lex/PPConditionalDirectiveRecordTest.cpp @@ -90,7 +90,7 @@ TEST_F(PPConditionalDirectiveRecordTest, PPRecAPI) { SourceMgr.createMainFileIDForMemBuffer(buf); VoidModuleLoader ModLoader; - HeaderSearch HeaderInfo(new HeaderSearchOptions, FileMgr, Diags, LangOpts, + HeaderSearch HeaderInfo(new HeaderSearchOptions, SourceMgr, Diags, LangOpts, Target.getPtr()); Preprocessor PP(new PreprocessorOptions(), Diags, LangOpts,Target.getPtr(), SourceMgr, HeaderInfo, ModLoader, diff --git a/clang/unittests/Tooling/ToolingTest.cpp b/clang/unittests/Tooling/ToolingTest.cpp index e435ea92e235..412af7adda9b 100644 --- a/clang/unittests/Tooling/ToolingTest.cpp +++ b/clang/unittests/Tooling/ToolingTest.cpp @@ -131,6 +131,26 @@ TEST(ToolInvocation, TestMapVirtualFile) { EXPECT_TRUE(Invocation.run()); } +TEST(ToolInvocation, TestVirtualModulesCompilation) { + // FIXME: Currently, this only tests that we don't exit with an error if a + // mapped module.map is found on the include path. In the future, expand this + // test to run a full modules enabled compilation, so we make sure we can + // rerun modules compilations with a virtual file system. + clang::FileManager Files((clang::FileSystemOptions())); + std::vector<std::string> Args; + Args.push_back("tool-executable"); + Args.push_back("-Idef"); + Args.push_back("-fsyntax-only"); + Args.push_back("test.cpp"); + clang::tooling::ToolInvocation Invocation(Args, new SyntaxOnlyAction, &Files); + Invocation.mapVirtualFile("test.cpp", "#include <abc>\n"); + Invocation.mapVirtualFile("def/abc", "\n"); + // Add a module.map file in the include directory of our header, so we trigger + // the module.map header search logic. + Invocation.mapVirtualFile("def/module.map", "\n"); + EXPECT_TRUE(Invocation.run()); +} + struct VerifyEndCallback : public SourceFileCallbacks { VerifyEndCallback() : BeginCalled(0), EndCalled(0), Matched(false) {} virtual bool handleBeginSource(CompilerInstance &CI,