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 | |
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')
-rw-r--r-- | lib/Basic/Module.cpp | 2 | ||||
-rw-r--r-- | lib/Frontend/FrontendActions.cpp | 65 | ||||
-rw-r--r-- | lib/Frontend/InitHeaderSearch.cpp | 8 | ||||
-rw-r--r-- | lib/Headers/module.map | 53 | ||||
-rw-r--r-- | lib/Lex/ModuleMap.cpp | 57 |
5 files changed, 95 insertions, 90 deletions
diff --git a/lib/Basic/Module.cpp b/lib/Basic/Module.cpp index c5838fb65f..634884074e 100644 --- a/lib/Basic/Module.cpp +++ b/lib/Basic/Module.cpp @@ -32,6 +32,8 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, if (Parent) { if (!Parent->isAvailable()) IsAvailable = false; + if (Parent->IsSystem) + IsSystem = true; Parent->SubModuleIndex[Name] = Parent->SubModules.size(); Parent->SubModules.push_back(this); diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index edadf37766..c0302329c1 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -126,32 +126,6 @@ ASTConsumer *GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, Sysroot, OS); } -/// \brief Add an appropriate #include/#import for the given header within -/// the current module context. -static void addHeaderInclude(StringRef Header, - bool IsBuiltinModule, - const LangOptions &LangOpts, - llvm::SmallString<256> &Includes) { - if (IsBuiltinModule) { - // Our own builtin headers play some evil tricks that depend both on - // knowing that our headers will be found first and on include_next. To - // Make sure these include_next tricks work, we include with <> and - // just the filename itself rather than using an absolutely path. - // FIXME: Is there some sensible way to generalize this? - Includes += "#include <"; - Includes += llvm::sys::path::filename(Header); - Includes += ">\n"; - return; - } - - if (LangOpts.ObjC1) - Includes += "#import \""; - else - Includes += "#include \""; - Includes += Header; - Includes += "\"\n"; -} - /// \brief Collect the set of header includes needed to construct the given /// module. /// @@ -163,21 +137,31 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, FileManager &FileMgr, ModuleMap &ModMap, clang::Module *Module, - bool IsBuiltinModule, llvm::SmallString<256> &Includes) { // Don't collect any headers for unavailable modules. if (!Module->isAvailable()) return; // Add includes for each of these headers. - for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) - addHeaderInclude(Module->Headers[I]->getName(), IsBuiltinModule, LangOpts, - Includes); + for (unsigned I = 0, N = Module->Headers.size(); I != N; ++I) { + if (LangOpts.ObjC1) + Includes += "#import \""; + else + Includes += "#include \""; + Includes += Module->Headers[I]->getName(); + Includes += "\"\n"; + } if (const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader()) { - if (Module->Parent) - addHeaderInclude(UmbrellaHeader->getName(), IsBuiltinModule, LangOpts, - Includes); + if (Module->Parent) { + // Include the umbrella header for submodules. + if (LangOpts.ObjC1) + Includes += "#import \""; + else + Includes += "#include \""; + Includes += UmbrellaHeader->getName(); + Includes += "\"\n"; + } } else if (const DirectoryEntry *UmbrellaDir = Module->getUmbrellaDir()) { // Add all of the headers we find in this subdirectory. llvm::error_code EC; @@ -199,8 +183,13 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, if (ModMap.isHeaderInUnavailableModule(Header)) continue; - // Include this header. - addHeaderInclude(Dir->path(), IsBuiltinModule, LangOpts, Includes); + // Include this header umbrella header for submodules. + if (LangOpts.ObjC1) + Includes += "#import \""; + else + Includes += "#include \""; + Includes += Dir->path(); + Includes += "\"\n"; } } @@ -208,8 +197,7 @@ static void collectModuleHeaderIncludes(const LangOptions &LangOpts, for (clang::Module::submodule_iterator Sub = Module->submodule_begin(), SubEnd = Module->submodule_end(); Sub != SubEnd; ++Sub) - collectModuleHeaderIncludes(LangOpts, FileMgr, ModMap, *Sub, - IsBuiltinModule, Includes); + collectModuleHeaderIncludes(LangOpts, FileMgr, ModMap, *Sub, Includes); } bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, @@ -261,11 +249,10 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, const FileEntry *UmbrellaHeader = Module->getUmbrellaHeader(); // Collect the set of #includes we need to build the module. - bool IsBuiltinModule = StringRef(Module->Name).startswith("_Builtin_"); llvm::SmallString<256> HeaderContents; collectModuleHeaderIncludes(CI.getLangOpts(), CI.getFileManager(), CI.getPreprocessor().getHeaderSearchInfo().getModuleMap(), - Module, IsBuiltinModule, HeaderContents); + Module, HeaderContents); if (UmbrellaHeader && HeaderContents.empty()) { // Simple case: we have an umbrella header and there are no additional // includes, we can just parse the umbrella header directly. diff --git a/lib/Frontend/InitHeaderSearch.cpp b/lib/Frontend/InitHeaderSearch.cpp index ee75e6921d..9faa126755 100644 --- a/lib/Frontend/InitHeaderSearch.cpp +++ b/lib/Frontend/InitHeaderSearch.cpp @@ -666,5 +666,13 @@ void clang::ApplyHeaderSearchOptions(HeaderSearch &HS, Init.AddDefaultIncludePaths(Lang, Triple, HSOpts); + if (HSOpts.UseBuiltinIncludes) { + // Set up the builtin include directory in the module map. + llvm::sys::Path P(HSOpts.ResourceDir); + P.appendComponent("include"); + if (const DirectoryEntry *Dir = HS.getFileMgr().getDirectory(P.str())) + HS.getModuleMap().setBuiltinIncludeDir(Dir); + } + Init.Realize(Lang); } diff --git a/lib/Headers/module.map b/lib/Headers/module.map index e321ca3ca5..418ba50090 100644 --- a/lib/Headers/module.map +++ b/lib/Headers/module.map @@ -1,42 +1,3 @@ -module _Builtin_stdlib [system] { - explicit module float_constants { - header "float.h" - } - - explicit module iso646 { - header "iso646.h" - } - - explicit module limits { - header "limits.h" - } - - explicit module stdalign { - header "stdalign.h" - } - - explicit module stdarg { - header "stdarg.h" - } - - explicit module stdbool { - header "stdbool.h" - } - - explicit module stddef { - header "stddef.h" - } - - explicit module stdint { - header "stdint.h" - } - - explicit module varargs { - requires unavailable - header "varargs.h" - } -} - module _Builtin_intrinsics [system] { explicit module altivec { requires altivec @@ -45,10 +6,16 @@ module _Builtin_intrinsics [system] { explicit module intel { requires x86 + export * header "immintrin.h" header "x86intrin.h" + explicit module mm_malloc { + header "mm_malloc.h" + export * // note: for <stdlib.h> dependency + } + explicit module cpuid { header "cpuid.h" } @@ -61,6 +28,7 @@ module _Builtin_intrinsics [system] { explicit module sse { requires sse export mmx + export * // note: for hackish <emmintrin.h> dependency header "xmmintrin.h" } @@ -136,12 +104,5 @@ module _Builtin_intrinsics [system] { requires mm3dnow header "mm3dnow.h" } - - explicit module mm_malloc { - header "mm_malloc.h" - } } - - // FIXME: tgmath.h - // FIXME: unwind.h } 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(); |