summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Lex/HeaderSearch.cpp47
-rw-r--r--clang/lib/Lex/ModuleMap.cpp6
-rw-r--r--clang/lib/Lex/PPDirectives.cpp1
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;
OpenPOWER on IntegriCloud