diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2018-07-28 11:06:01 +0000 |
commit | 486754660bb926339aefcf012a3f848592babb8b (patch) | |
tree | ecdbc446c9876f4f120f701c243373cd3cb43db3 /lib/Frontend/CompilerInstance.cpp | |
parent | 55e6d896ad333f07bb3b1ba487df214fc268a4ab (diff) |
Notes
Diffstat (limited to 'lib/Frontend/CompilerInstance.cpp')
-rw-r--r-- | lib/Frontend/CompilerInstance.cpp | 181 |
1 files changed, 96 insertions, 85 deletions
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp index 7208177aa0126..155ead4ac8e85 100644 --- a/lib/Frontend/CompilerInstance.cpp +++ b/lib/Frontend/CompilerInstance.cpp @@ -16,6 +16,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/MemoryBufferCache.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/Stack.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/Config/config.h" @@ -302,11 +303,9 @@ CompilerInstance::createDiagnostics(DiagnosticOptions *Opts, FileManager *CompilerInstance::createFileManager() { if (!hasVirtualFileSystem()) { - if (IntrusiveRefCntPtr<vfs::FileSystem> VFS = - createVFSFromCompilerInvocation(getInvocation(), getDiagnostics())) - setVirtualFileSystem(VFS); - else - return nullptr; + IntrusiveRefCntPtr<vfs::FileSystem> VFS = + createVFSFromCompilerInvocation(getInvocation(), getDiagnostics()); + setVirtualFileSystem(VFS); } FileMgr = new FileManager(getFileSystemOpts(), VirtualFileSystem); return FileMgr.get(); @@ -464,7 +463,7 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { /*ShowDepth=*/false); } - if (DepOpts.PrintShowIncludes) { + if (DepOpts.ShowIncludesDest != ShowIncludesDestination::None) { AttachHeaderIncludeGen(*PP, DepOpts, /*ShowAllHeaders=*/true, /*OutputPath=*/"", /*ShowDepth=*/true, /*MSStyle=*/true); @@ -854,36 +853,7 @@ bool CompilerInstance::InitializeSourceManager( // Figure out where to get and map in the main file. if (InputFile != "-") { - const FileEntry *File; - if (Opts.FindPchSource.empty()) { - File = FileMgr.getFile(InputFile, /*OpenFile=*/true); - } else { - // When building a pch file in clang-cl mode, the .h file is built as if - // it was included by a cc file. Since the driver doesn't know about - // all include search directories, the frontend must search the input - // file through HeaderSearch here, as if it had been included by the - // cc file at Opts.FindPchSource. - const FileEntry *FindFile = FileMgr.getFile(Opts.FindPchSource); - if (!FindFile) { - Diags.Report(diag::err_fe_error_reading) << Opts.FindPchSource; - return false; - } - const DirectoryLookup *UnusedCurDir; - SmallVector<std::pair<const FileEntry *, const DirectoryEntry *>, 16> - Includers; - Includers.push_back(std::make_pair(FindFile, FindFile->getDir())); - File = HS->LookupFile(InputFile, SourceLocation(), /*isAngled=*/false, - /*FromDir=*/nullptr, - /*CurDir=*/UnusedCurDir, Includers, - /*SearchPath=*/nullptr, - /*RelativePath=*/nullptr, - /*RequestingModule=*/nullptr, - /*SuggestedModule=*/nullptr, /*IsMapped=*/nullptr, - /*SkipCache=*/true); - // Also add the header to /showIncludes output. - if (File) - DepOpts.ShowIncludesPretendHeader = File->getName(); - } + const FileEntry *File = FileMgr.getFile(InputFile, /*OpenFile=*/true); if (!File) { Diags.Report(diag::err_fe_error_reading) << InputFile; return false; @@ -1044,7 +1014,7 @@ bool CompilerInstance::ExecuteAction(FrontendAction &Act) { return !getDiagnostics().getClient()->getNumErrors(); } -/// \brief Determine the appropriate source input kind based on language +/// Determine the appropriate source input kind based on language /// options. static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) { if (LangOpts.OpenCL) @@ -1056,7 +1026,7 @@ static InputKind::Language getLanguageFromOptions(const LangOptions &LangOpts) { return LangOpts.CPlusPlus ? InputKind::CXX : InputKind::C; } -/// \brief Compile a module file for the given module, using the options +/// Compile a module file for the given module, using the options /// provided by the importing compiler instance. Returns true if the module /// was built without errors. static bool @@ -1090,6 +1060,10 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, }), PPOpts.Macros.end()); + // If the original compiler invocation had -fmodule-name, pass it through. + Invocation->getLangOpts()->ModuleName = + ImportingInstance.getInvocation().getLangOpts()->ModuleName; + // Note the name of the module we're building. Invocation->getLangOpts()->CurrentModule = ModuleName; @@ -1162,14 +1136,13 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, // Execute the action to actually build the module in-place. Use a separate // thread so that we get a stack large enough. - const unsigned ThreadStackSize = 8 << 20; llvm::CrashRecoveryContext CRC; CRC.RunSafelyOnThread( [&]() { GenerateModuleFromModuleMapAction Action; Instance.ExecuteAction(Action); }, - ThreadStackSize); + DesiredStackSize); PostBuildStep(Instance); @@ -1186,7 +1159,20 @@ compileModuleImpl(CompilerInstance &ImportingInstance, SourceLocation ImportLoc, return !Instance.getDiagnostics().hasErrorOccurred(); } -/// \brief Compile a module file for the given module, using the options +static const FileEntry *getPublicModuleMap(const FileEntry *File, + FileManager &FileMgr) { + StringRef Filename = llvm::sys::path::filename(File->getName()); + SmallString<128> PublicFilename(File->getDir()->getName()); + if (Filename == "module_private.map") + llvm::sys::path::append(PublicFilename, "module.map"); + else if (Filename == "module.private.modulemap") + llvm::sys::path::append(PublicFilename, "module.modulemap"); + else + return nullptr; + return FileMgr.getFile(PublicFilename); +} + +/// Compile a module file for the given module, using the options /// provided by the importing compiler instance. Returns true if the module /// was built without errors. static bool compileModuleImpl(CompilerInstance &ImportingInstance, @@ -1202,6 +1188,13 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, bool Result; if (const FileEntry *ModuleMapFile = ModMap.getContainingModuleMapFile(Module)) { + // Canonicalize compilation to start with the public module map. This is + // vital for submodules declarations in the private module maps to be + // correctly parsed when depending on a top level module in the public one. + if (const FileEntry *PublicMMFile = getPublicModuleMap( + ModuleMapFile, ImportingInstance.getFileManager())) + ModuleMapFile = PublicMMFile; + // Use the module map where this module resides. Result = compileModuleImpl( ImportingInstance, ImportLoc, Module->getTopLevelModuleName(), @@ -1298,7 +1291,7 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance, // case of timeout, build it ourselves. Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout) << Module->Name; - // Clear the lock file so that future invokations can make progress. + // Clear the lock file so that future invocations can make progress. Locked.unsafeRemoveLockFile(); continue; } @@ -1328,7 +1321,7 @@ static bool compileAndLoadModule(CompilerInstance &ImportingInstance, } } -/// \brief Diagnose differences between the current definition of the given +/// Diagnose differences between the current definition of the given /// configuration macro and the definition provided on the command line. static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, Module *Mod, SourceLocation ImportLoc) { @@ -1386,13 +1379,13 @@ static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro, } } -/// \brief Write a new timestamp file with the given path. +/// Write a new timestamp file with the given path. static void writeTimestampFile(StringRef TimestampFile) { std::error_code EC; llvm::raw_fd_ostream Out(TimestampFile.str(), EC, llvm::sys::fs::F_None); } -/// \brief Prune the module cache of modules that haven't been accessed in +/// Prune the module cache of modules that haven't been accessed in /// a long time. static void pruneModuleCache(const HeaderSearchOptions &HSOpts) { struct stat StatBuf; @@ -1580,15 +1573,22 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { if (!ModuleManager) createModuleManager(); + // If -Wmodule-file-config-mismatch is mapped as an error or worse, allow the + // ASTReader to diagnose it, since it can produce better errors that we can. + bool ConfigMismatchIsRecoverable = + getDiagnostics().getDiagnosticLevel(diag::warn_module_config_mismatch, + SourceLocation()) + <= DiagnosticsEngine::Warning; + auto Listener = llvm::make_unique<ReadModuleNames>(*this); auto &ListenerRef = *Listener; ASTReader::ListenerScope ReadModuleNamesListener(*ModuleManager, std::move(Listener)); // Try to load the module file. - switch (ModuleManager->ReadAST(FileName, serialization::MK_ExplicitModule, - SourceLocation(), - ASTReader::ARR_ConfigurationMismatch)) { + switch (ModuleManager->ReadAST( + FileName, serialization::MK_ExplicitModule, SourceLocation(), + ConfigMismatchIsRecoverable ? ASTReader::ARR_ConfigurationMismatch : 0)) { case ASTReader::Success: // We successfully loaded the module file; remember the set of provided // modules so that we don't try to load implicit modules for them. @@ -1653,8 +1653,10 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, // Retrieve the cached top-level module. Module = Known->second; } else if (ModuleName == getLangOpts().CurrentModule) { - // This is the module we're building. - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + // This is the module we're building. + Module = PP->getHeaderSearchInfo().lookupModule( + ModuleName, /*AllowSearch*/ true, + /*AllowExtraModuleMapSearch*/ !IsInclusionDirective); /// FIXME: perhaps we should (a) look for a module using the module name // to file map (PrebuiltModuleFiles) and (b) diagnose if still not found? //if (Module == nullptr) { @@ -1666,7 +1668,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Known = KnownModules.insert(std::make_pair(Path[0].first, Module)).first; } else { // Search for a module with the given name. - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, + !IsInclusionDirective); HeaderSearchOptions &HSOpts = PP->getHeaderSearchInfo().getHeaderSearchOpts(); @@ -1743,7 +1746,8 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, ImportLoc, ARRFlags)) { case ASTReader::Success: { if (Source != ModuleCache && !Module) { - Module = PP->getHeaderSearchInfo().lookupModule(ModuleName); + Module = PP->getHeaderSearchInfo().lookupModule(ModuleName, true, + !IsInclusionDirective); if (!Module || !Module->getASTFile() || FileMgr->getFile(ModuleFileName) != Module->getASTFile()) { // Error out if Module does not refer to the file in the prebuilt @@ -1859,6 +1863,40 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, for (unsigned I = 1, N = Path.size(); I != N; ++I) { StringRef Name = Path[I].first->getName(); clang::Module *Sub = Module->findSubmodule(Name); + + // If the user is requesting Foo.Private and it doesn't exist, try to + // match Foo_Private and emit a warning asking for the user to write + // @import Foo_Private instead. FIXME: remove this when existing clients + // migrate off of Foo.Private syntax. + if (!Sub && PP->getLangOpts().ImplicitModules && Name == "Private" && + Module == Module->getTopLevelModule()) { + SmallString<128> PrivateModule(Module->Name); + PrivateModule.append("_Private"); + + SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> PrivPath; + auto &II = PP->getIdentifierTable().get( + PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID()); + PrivPath.push_back(std::make_pair(&II, Path[0].second)); + + if (PP->getHeaderSearchInfo().lookupModule(PrivateModule, true, + !IsInclusionDirective)) + Sub = + loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective); + if (Sub) { + MapPrivateSubModToTopLevel = true; + if (!getDiagnostics().isIgnored( + diag::warn_no_priv_submodule_use_toplevel, ImportLoc)) { + getDiagnostics().Report(Path[I].second, + diag::warn_no_priv_submodule_use_toplevel) + << Path[I].first << Module->getFullModuleName() << PrivateModule + << SourceRange(Path[0].second, Path[I].second) + << FixItHint::CreateReplacement(SourceRange(Path[0].second), + PrivateModule); + getDiagnostics().Report(Sub->DefinitionLoc, + diag::note_private_top_level_defined); + } + } + } if (!Sub) { // Attempt to perform typo correction to find a module name that works. @@ -1894,39 +1932,6 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, } } - // If the user is requesting Foo.Private and it doesn't exist, try to - // match Foo_Private and emit a warning asking for the user to write - // @import Foo_Private instead. FIXME: remove this when existing clients - // migrate off of Foo.Private syntax. - if (!Sub && PP->getLangOpts().ImplicitModules && Name == "Private" && - Module == Module->getTopLevelModule()) { - SmallString<128> PrivateModule(Module->Name); - PrivateModule.append("_Private"); - - SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> PrivPath; - auto &II = PP->getIdentifierTable().get( - PrivateModule, PP->getIdentifierInfo(Module->Name)->getTokenID()); - PrivPath.push_back(std::make_pair(&II, Path[0].second)); - - if (PP->getHeaderSearchInfo().lookupModule(PrivateModule)) - Sub = - loadModule(ImportLoc, PrivPath, Visibility, IsInclusionDirective); - if (Sub) { - MapPrivateSubModToTopLevel = true; - if (!getDiagnostics().isIgnored( - diag::warn_no_priv_submodule_use_toplevel, ImportLoc)) { - getDiagnostics().Report(Path[I].second, - diag::warn_no_priv_submodule_use_toplevel) - << Path[I].first << Module->getFullModuleName() << PrivateModule - << SourceRange(Path[0].second, Path[I].second) - << FixItHint::CreateReplacement(SourceRange(Path[0].second), - PrivateModule); - getDiagnostics().Report(Sub->DefinitionLoc, - diag::note_private_top_level_defined); - } - } - } - if (!Sub) { // No submodule by this name. Complain, and don't look for further // submodules. @@ -1977,6 +1982,12 @@ CompilerInstance::loadModule(SourceLocation ImportLoc, Module, ImportLoc); } + // Resolve any remaining module using export_as for this one. + getPreprocessor() + .getHeaderSearchInfo() + .getModuleMap() + .resolveLinkAsDependencies(TopModule); + LastModuleImportLoc = ImportLoc; LastModuleImportResult = ModuleLoadResult(Module); return LastModuleImportResult; |