From db3910be2e30b3fa00474f0e1c0780f544469dee Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Thu, 2 May 2013 17:58:30 +0000 Subject: When looking for the module associated with one of our magical builtin headers, speculatively load module maps. The "magical" builtin headers are the headers we provide as part of the C standard library, which typically comes from /usr/include. We essentially merge our headers into that location (due to cyclic dependencies). This change makes sure that, when header search finds one of our builtin headers, we figure out which module it actually lives in. This case is fairly rare; one ends up having to include one of the few built-in C headers we provide before including anything from /usr/include to trigger it. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180934 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Lex/ModuleMap.cpp | 55 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 37 insertions(+), 18 deletions(-) (limited to 'lib/Lex/ModuleMap.cpp') diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 0c03201aa6..1458a73a7d 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -149,6 +149,24 @@ static StringRef sanitizeFilenameAsIdentifier(StringRef Name, return 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) { + return llvm::StringSwitch(FileName) + .Case("float.h", true) + .Case("iso646.h", true) + .Case("limits.h", true) + .Case("stdalign.h", true) + .Case("stdarg.h", true) + .Case("stdbool.h", true) + .Case("stddef.h", true) + .Case("stdint.h", true) + .Case("tgmath.h", true) + .Case("unwind.h", true) + .Default(false); +} + Module *ModuleMap::findModuleForHeader(const FileEntry *File) { HeadersMap::iterator Known = Headers.find(File); if (Known != Headers.end()) { @@ -158,6 +176,25 @@ Module *ModuleMap::findModuleForHeader(const FileEntry *File) { return Known->second.getModule(); } + + // If we've found a builtin header within Clang's builtin include directory, + // load all of the module maps to see if it will get associated with a + // specific module (e.g., in /usr/include). + if (File->getDir() == BuiltinIncludeDir && + isBuiltinHeader(llvm::sys::path::filename(File->getName()))) { + SmallVector AllModules; + HeaderInfo.collectAllModules(AllModules); + + // Check again. + Known = Headers.find(File); + if (Known != Headers.end()) { + // If a header is not available, don't report that it maps to anything. + if (!Known->second.isAvailable()) + return 0; + + return Known->second.getModule(); + } + } const DirectoryEntry *Dir = File->getDir(); SmallVector SkippedDirs; @@ -1266,24 +1303,6 @@ static void appendSubframeworkPaths(Module *Mod, } } -/// \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) { - return llvm::StringSwitch(FileName) - .Case("float.h", true) - .Case("iso646.h", true) - .Case("limits.h", true) - .Case("stdalign.h", true) - .Case("stdarg.h", true) - .Case("stdbool.h", true) - .Case("stddef.h", true) - .Case("stdint.h", true) - .Case("tgmath.h", true) - .Case("unwind.h", true) - .Default(false); -} - /// \brief Parse a header declaration. /// /// header-declaration: -- cgit v1.2.3-18-g5258