[cfe-commits] r149611 - in /cfe/trunk: include/clang/Lex/ lib/Basic/ lib/Frontend/ lib/Headers/ lib/Lex/ test/Modules/ test/Modules/Inputs/System/ test/Modules/Inputs/System/usr/ test/Modules/Inputs/System/usr/include/
Douglas Gregor
dgregor at apple.com
Thu Feb 2 10:42:49 PST 2012
Author: dgregor
Date: Thu Feb 2 12:42:48 2012
New Revision: 149611
URL: http://llvm.org/viewvc/llvm-project?rev=149611&view=rev
Log:
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.
Added:
cfe/trunk/test/Modules/Inputs/System/
cfe/trunk/test/Modules/Inputs/System/usr/
cfe/trunk/test/Modules/Inputs/System/usr/include/
cfe/trunk/test/Modules/Inputs/System/usr/include/module.map
cfe/trunk/test/Modules/Inputs/System/usr/include/stdbool.h
cfe/trunk/test/Modules/Inputs/System/usr/include/stdint.h
cfe/trunk/test/Modules/Inputs/System/usr/include/stdio.h
cfe/trunk/test/Modules/cstd.m
Modified:
cfe/trunk/include/clang/Lex/ModuleMap.h
cfe/trunk/lib/Basic/Module.cpp
cfe/trunk/lib/Frontend/FrontendActions.cpp
cfe/trunk/lib/Frontend/InitHeaderSearch.cpp
cfe/trunk/lib/Headers/module.map
cfe/trunk/lib/Lex/ModuleMap.cpp
cfe/trunk/test/Modules/compiler_builtins.m
Modified: cfe/trunk/include/clang/Lex/ModuleMap.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/ModuleMap.h?rev=149611&r1=149610&r2=149611&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/ModuleMap.h (original)
+++ cfe/trunk/include/clang/Lex/ModuleMap.h Thu Feb 2 12:42:48 2012
@@ -41,6 +41,10 @@
const LangOptions &LangOpts;
const TargetInfo *Target;
+ /// \brief The directory used for Clang-supplied, builtin include headers,
+ /// such as "stdint.h".
+ const DirectoryEntry *BuiltinIncludeDir;
+
/// \brief Language options used to parse the module map itself.
///
/// These are always simple C language options.
@@ -102,6 +106,12 @@
/// \brief Set the target information.
void setTarget(const TargetInfo &Target);
+ /// \brief Set the directory that contains Clang-supplied include
+ /// files, such as our stdarg.h or tgmath.h.
+ void setBuiltinIncludeDir(const DirectoryEntry *Dir) {
+ BuiltinIncludeDir = Dir;
+ }
+
/// \brief Retrieve the module that owns the given header file, if any.
///
/// \param File The header file that is likely to be included.
Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=149611&r1=149610&r2=149611&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Thu Feb 2 12:42:48 2012
@@ -32,6 +32,8 @@
if (Parent) {
if (!Parent->isAvailable())
IsAvailable = false;
+ if (Parent->IsSystem)
+ IsSystem = true;
Parent->SubModuleIndex[Name] = Parent->SubModules.size();
Parent->SubModules.push_back(this);
Modified: cfe/trunk/lib/Frontend/FrontendActions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/FrontendActions.cpp?rev=149611&r1=149610&r2=149611&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/FrontendActions.cpp (original)
+++ cfe/trunk/lib/Frontend/FrontendActions.cpp Thu Feb 2 12:42:48 2012
@@ -126,32 +126,6 @@
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 @@
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 @@
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 @@
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 @@
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.
Modified: cfe/trunk/lib/Frontend/InitHeaderSearch.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/InitHeaderSearch.cpp?rev=149611&r1=149610&r2=149611&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/InitHeaderSearch.cpp (original)
+++ cfe/trunk/lib/Frontend/InitHeaderSearch.cpp Thu Feb 2 12:42:48 2012
@@ -666,5 +666,13 @@
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);
}
Modified: cfe/trunk/lib/Headers/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Headers/module.map?rev=149611&r1=149610&r2=149611&view=diff
==============================================================================
--- cfe/trunk/lib/Headers/module.map (original)
+++ cfe/trunk/lib/Headers/module.map Thu Feb 2 12:42:48 2012
@@ -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 @@
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 @@
explicit module sse {
requires sse
export mmx
+ export * // note: for hackish <emmintrin.h> dependency
header "xmmintrin.h"
}
@@ -136,12 +104,5 @@
requires mm3dnow
header "mm3dnow.h"
}
-
- explicit module mm_malloc {
- header "mm_malloc.h"
- }
}
-
- // FIXME: tgmath.h
- // FIXME: unwind.h
}
Modified: cfe/trunk/lib/Lex/ModuleMap.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/ModuleMap.cpp?rev=149611&r1=149610&r2=149611&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/ModuleMap.cpp (original)
+++ cfe/trunk/lib/Lex/ModuleMap.cpp Thu Feb 2 12:42:48 2012
@@ -71,7 +71,7 @@
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 @@
/// \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 @@
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 @@
}
}
+/// \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 @@
// 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 @@
// 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 @@
} 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 @@
// 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();
Added: cfe/trunk/test/Modules/Inputs/System/usr/include/module.map
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/System/usr/include/module.map?rev=149611&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/System/usr/include/module.map (added)
+++ cfe/trunk/test/Modules/Inputs/System/usr/include/module.map Thu Feb 2 12:42:48 2012
@@ -0,0 +1,21 @@
+module cstd [system] {
+ // Only in compiler support directory
+ module float_constants {
+ header "float.h"
+ }
+
+ // Only in system headers directory
+ module stdio {
+ header "stdio.h"
+ }
+
+ // In both directories (compiler support version wins, does not forward)
+ module stdbool {
+ header "stdbool.h"
+ }
+
+ // In both directories (compiler support version wins, forwards)
+ module stdint {
+ header "stdint.h"
+ }
+}
Added: cfe/trunk/test/Modules/Inputs/System/usr/include/stdbool.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/System/usr/include/stdbool.h?rev=149611&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/System/usr/include/stdbool.h (added)
+++ cfe/trunk/test/Modules/Inputs/System/usr/include/stdbool.h Thu Feb 2 12:42:48 2012
@@ -0,0 +1 @@
+// Testing hack: does not define bool/true/false.
Added: cfe/trunk/test/Modules/Inputs/System/usr/include/stdint.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/System/usr/include/stdint.h?rev=149611&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/System/usr/include/stdint.h (added)
+++ cfe/trunk/test/Modules/Inputs/System/usr/include/stdint.h Thu Feb 2 12:42:48 2012
@@ -0,0 +1 @@
+typedef int my_awesome_nonstandard_integer_type;
Added: cfe/trunk/test/Modules/Inputs/System/usr/include/stdio.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/System/usr/include/stdio.h?rev=149611&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/System/usr/include/stdio.h (added)
+++ cfe/trunk/test/Modules/Inputs/System/usr/include/stdio.h Thu Feb 2 12:42:48 2012
@@ -0,0 +1,3 @@
+typedef struct { int id; } FILE;
+int fprintf(FILE*restrict, const char* restrict format, ...);
+
Modified: cfe/trunk/test/Modules/compiler_builtins.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/compiler_builtins.m?rev=149611&r1=149610&r2=149611&view=diff
==============================================================================
--- cfe/trunk/test/Modules/compiler_builtins.m (original)
+++ cfe/trunk/test/Modules/compiler_builtins.m Thu Feb 2 12:42:48 2012
@@ -1,22 +1,6 @@
// RUN: rm -rf %t
// RUN: %clang -fsyntax-only -fmodules -fmodule-cache-path %t -D__need_wint_t %s -Xclang -verify
- at import _Builtin_stdlib.float_constants;
-
-float getFltMax() { return FLT_MAX; }
-
- at import _Builtin_stdlib.limits;
-
-char getCharMax() { return CHAR_MAX; }
-
-// MS limits.h provides size_t.
-// XFAIL: win32
-size_t size; // expected-error{{unknown type name 'size_t'}}
-
- at import _Builtin_stdlib.stdint;
-
-intmax_t value;
-
#ifdef __SSE__
@import _Builtin_intrinsics.intel.sse;
#endif
Added: cfe/trunk/test/Modules/cstd.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/cstd.m?rev=149611&view=auto
==============================================================================
--- cfe/trunk/test/Modules/cstd.m (added)
+++ cfe/trunk/test/Modules/cstd.m Thu Feb 2 12:42:48 2012
@@ -0,0 +1,29 @@
+// RUN: rm -rf %t
+// RUN: %clang -fsyntax-only -isysroot %S/Inputs/System -fmodules -fmodule-cache-path %t -D__need_wint_t %s -Xclang -verify
+
+// Supplied by compiler, but referenced from the "/usr/include" module map.
+ at import cstd.float_constants;
+
+float getFltMax() { return FLT_MAX; }
+
+// Supplied by the "/usr/include" module map.
+ at import cstd.stdio;
+
+void test_fprintf(FILE *file) {
+ fprintf(file, "Hello, modules\n");
+}
+
+// Supplied by compiler, which forwards to the the "/usr/include" version.
+ at import cstd.stdint;
+
+my_awesome_nonstandard_integer_type value;
+
+// Supplied by the compiler; that version wins.
+ at import cstd.stdbool;
+
+#ifndef bool
+# error "bool was not defined!"
+#endif
+
+
+
More information about the cfe-commits
mailing list