diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/Lex/HeaderSearch.cpp | 47 | ||||
| -rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Lex/PPDirectives.cpp | 1 |
3 files changed, 47 insertions, 7 deletions
diff --git a/clang/lib/Lex/HeaderSearch.cpp b/clang/lib/Lex/HeaderSearch.cpp index fa2a76ef47c..c667f4bf220 100644 --- a/clang/lib/Lex/HeaderSearch.cpp +++ b/clang/lib/Lex/HeaderSearch.cpp @@ -1092,13 +1092,51 @@ void HeaderSearch::MarkFileModuleHeader(const FileEntry *FE, } bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, - const FileEntry *File, - bool isImport, Module *M) { + const FileEntry *File, bool isImport, + bool ModulesEnabled, Module *M) { ++NumIncluded; // Count # of attempted #includes. // Get information about this file. HeaderFileInfo &FileInfo = getFileInfo(File); + // FIXME: this is a workaround for the lack of proper modules-aware support + // for #import / #pragma once + auto TryEnterImported = [&](void) -> bool { + if (!ModulesEnabled) + return false; + // Modules with builtins are special; multiple modules use builtins as + // modular headers, example: + // + // module stddef { header "stddef.h" export * } + // + // After module map parsing, this expands to: + // + // module stddef { + // header "/path_to_builtin_dirs/stddef.h" + // textual "stddef.h" + // } + // + // It's common that libc++ and system modules will both define such + // submodules. Make sure cached results for a builtin header won't + // prevent other builtin modules to potentially enter the builtin header. + // Note that builtins are header guarded and the decision to actually + // enter them is postponed to the controlling macros logic below. + bool TryEnterHdr = false; + if (FileInfo.isCompilingModuleHeader && FileInfo.isModuleHeader) + TryEnterHdr = File->getDir() == ModMap.getBuiltinDir() && + ModuleMap::isBuiltinHeader( + llvm::sys::path::filename(File->getName())); + + // Textual headers can be #imported from different modules. Since ObjC + // headers find in the wild might rely only on #import and do not contain + // controlling macros, be conservative and only try to enter textual headers + // if such macro is present. + if (!FileInfo.isModuleHeader && + FileInfo.getControllingMacro(ExternalLookup)) + TryEnterHdr = true; + return TryEnterHdr; + }; + // If this is a #import directive, check that we have not already imported // this header. if (isImport) { @@ -1106,11 +1144,12 @@ bool HeaderSearch::ShouldEnterIncludeFile(Preprocessor &PP, FileInfo.isImport = true; // Has this already been #import'ed or #include'd? - if (FileInfo.NumIncludes) return false; + if (FileInfo.NumIncludes && !TryEnterImported()) + return false; } else { // Otherwise, if this is a #include of a file that was previously #import'd // or if this is the second #include of a #pragma once file, ignore it. - if (FileInfo.isImport) + if (FileInfo.isImport && !TryEnterImported()) return false; } diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index 9d0f2eb2fa7..db834ede022 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -144,7 +144,7 @@ static StringRef sanitizeFilenameAsIdentifier(StringRef Name, /// \brief Determine whether the given file name is the name of a builtin /// header, supplied by Clang to replace, override, or augment existing system /// headers. -static bool isBuiltinHeader(StringRef FileName) { +bool ModuleMap::isBuiltinHeader(StringRef FileName) { return llvm::StringSwitch<bool>(FileName) .Case("float.h", true) .Case("iso646.h", true) @@ -165,7 +165,7 @@ ModuleMap::findKnownHeader(const FileEntry *File) { HeadersMap::iterator Known = Headers.find(File); if (HeaderInfo.getHeaderSearchOpts().ImplicitModuleMaps && Known == Headers.end() && File->getDir() == BuiltinIncludeDir && - isBuiltinHeader(llvm::sys::path::filename(File->getName()))) { + ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName()))) { HeaderInfo.loadTopLevelSystemModules(); return Headers.find(File); } @@ -1879,7 +1879,7 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, // supplied by Clang. Find that builtin header. if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword && BuiltinIncludeDir && BuiltinIncludeDir != Directory && - isBuiltinHeader(Header.FileName)) { + ModuleMap::isBuiltinHeader(Header.FileName)) { SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); llvm::sys::path::append(BuiltinPathName, Header.FileName); BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); diff --git a/clang/lib/Lex/PPDirectives.cpp b/clang/lib/Lex/PPDirectives.cpp index 9661e7b13f7..322c5809cd2 100644 --- a/clang/lib/Lex/PPDirectives.cpp +++ b/clang/lib/Lex/PPDirectives.cpp @@ -1999,6 +1999,7 @@ void Preprocessor::HandleIncludeDirective(SourceLocation HashLoc, bool SkipHeader = false; if (ShouldEnter && !HeaderInfo.ShouldEnterIncludeFile(*this, File, isImport, + getLangOpts().Modules, SuggestedModule.getModule())) { ShouldEnter = false; SkipHeader = true; |

