diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-02 18:42:48 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-02 18:42:48 +0000 |
commit | 2f04f1843ca0ffca13b8b0d4dadd1f50dffb38b8 (patch) | |
tree | f2efcb1a10ca694d4f0e08451848f0b2a13aa649 /lib/Lex/ModuleMap.cpp | |
parent | 4f7dcdbdfc50a244c3f3ca66f15b0b39a56f8f64 (diff) |
Back out my heinous hack that tricked the module generation mechanism
into using non-absolute system includes (<foo>)...
... and introduce another hack that is simultaneously more heineous
and more effective. We whitelist Clang-supplied headers that augment
or override system headers (such as float.h, stdarg.h, and
tgmath.h). For these headers, Clang does not provide a module
mapping. Instead, a system-supplied module map can refer to these
headers in a system module, and Clang will look both in its own
include directory and wherever the system-supplied module map
suggests, then adds either or both headers. The end result is that
Clang-supplied headers get merged into the system-supplied module for
the C standard library.
As a drive-by, fix up a few dependencies in the _Builtin_instrinsics
module.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149611 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Lex/ModuleMap.cpp')
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/lib/Lex/ModuleMap.cpp b/lib/Lex/ModuleMap.cpp index 3583b034d5..c1c5066012 100644 --- a/lib/Lex/ModuleMap.cpp +++ b/lib/Lex/ModuleMap.cpp @@ -71,7 +71,7 @@ ModuleMap::resolveExport(Module *Mod, ModuleMap::ModuleMap(FileManager &FileMgr, const DiagnosticConsumer &DC, const LangOptions &LangOpts, const TargetInfo *Target) - : LangOpts(LangOpts), Target(Target) + : LangOpts(LangOpts), Target(Target), BuiltinIncludeDir(0) { llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs); Diags = llvm::IntrusiveRefCntPtr<DiagnosticsEngine>( @@ -499,7 +499,10 @@ namespace clang { /// \brief The directory that this module map resides in. const DirectoryEntry *Directory; - + + /// \brief The directory containing Clang-supplied headers. + const DirectoryEntry *BuiltinIncludeDir; + /// \brief Whether an error occurred. bool HadError; @@ -540,9 +543,11 @@ namespace clang { explicit ModuleMapParser(Lexer &L, SourceManager &SourceMgr, DiagnosticsEngine &Diags, ModuleMap &Map, - const DirectoryEntry *Directory) + const DirectoryEntry *Directory, + const DirectoryEntry *BuiltinIncludeDir) : L(L), SourceMgr(SourceMgr), Diags(Diags), Map(Map), - Directory(Directory), HadError(false), ActiveModule(0) + Directory(Directory), BuiltinIncludeDir(BuiltinIncludeDir), + HadError(false), ActiveModule(0) { TargetOptions TargetOpts; TargetOpts.Triple = llvm::sys::getDefaultTargetTriple(); @@ -1028,6 +1033,24 @@ void appendSubframeworkPaths(Module *Mod, llvm::SmallVectorImpl<char> &Path) { } } +/// \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<bool>(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: @@ -1058,6 +1081,7 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) { // Look for this file. const FileEntry *File = 0; + const FileEntry *BuiltinFile = 0; llvm::SmallString<128> PathName; if (llvm::sys::path::is_absolute(FileName)) { PathName = FileName; @@ -1090,6 +1114,24 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) { // Lookup for normal headers. llvm::sys::path::append(PathName, FileName); File = SourceMgr.getFileManager().getFile(PathName); + + // If this is a system module with a top-level header, this header + // may have a counterpart (or replacement) in the set of headers + // supplied by Clang. Find that builtin header. + if (ActiveModule->IsSystem && !Umbrella && BuiltinIncludeDir && + BuiltinIncludeDir != Directory && isBuiltinHeader(FileName)) { + llvm::SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); + llvm::sys::path::append(BuiltinPathName, FileName); + BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); + + // If Clang supplies this header but the underlying system does not, + // just silently swap in our builtin version. Otherwise, we'll end + // up adding both (later). + if (!File && BuiltinFile) { + File = BuiltinFile; + BuiltinFile = 0; + } + } } } @@ -1113,6 +1155,10 @@ void ModuleMapParser::parseHeaderDecl(SourceLocation UmbrellaLoc) { } else { // Record this header. Map.addHeader(ActiveModule, File); + + // If there is a builtin counterpart to this file, add it now. + if (BuiltinFile) + Map.addHeader(ActiveModule, BuiltinFile); } } else { Diags.Report(FileNameLoc, diag::err_mmap_header_not_found) @@ -1375,7 +1421,8 @@ bool ModuleMap::parseModuleMapFile(const FileEntry *File) { // Parse this module map file. Lexer L(ID, SourceMgr->getBuffer(ID), *SourceMgr, MMapLangOpts); Diags->getClient()->BeginSourceFile(MMapLangOpts); - ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir()); + ModuleMapParser Parser(L, *SourceMgr, *Diags, *this, File->getDir(), + BuiltinIncludeDir); bool Result = Parser.parseModuleMapFile(); Diags->getClient()->EndSourceFile(); |