summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2013-05-02 17:58:30 +0000
committerDouglas Gregor <dgregor@apple.com>2013-05-02 17:58:30 +0000
commit34d52749e4ead103644e571e16be1b539bfa64a5 (patch)
treeb90395f4a2c8b862b78074ecd2ce685020f5e2a6
parent5f99742632926b5870ddb418211de55f24228ea7 (diff)
downloadbcm5719-llvm-34d52749e4ead103644e571e16be1b539bfa64a5.tar.gz
bcm5719-llvm-34d52749e4ead103644e571e16be1b539bfa64a5.zip
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 <rdar://problem/13787184>. llvm-svn: 180934
-rw-r--r--clang/lib/Lex/ModuleMap.cpp55
-rw-r--r--clang/test/Modules/Inputs/System/usr/include/dbl_max.h1
-rw-r--r--clang/test/Modules/Inputs/System/usr/include/module.map11
-rw-r--r--clang/test/Modules/Inputs/System/usr/include/uses_other_constants.h3
-rw-r--r--clang/test/Modules/cstd.m7
5 files changed, 56 insertions, 21 deletions
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp
index 0c03201aa6d..1458a73a7d3 100644
--- a/clang/lib/Lex/ModuleMap.cpp
+++ b/clang/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<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);
+}
+
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<Module *, 4> 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<const DirectoryEntry *, 2> 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<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:
diff --git a/clang/test/Modules/Inputs/System/usr/include/dbl_max.h b/clang/test/Modules/Inputs/System/usr/include/dbl_max.h
new file mode 100644
index 00000000000..9a020d1bf53
--- /dev/null
+++ b/clang/test/Modules/Inputs/System/usr/include/dbl_max.h
@@ -0,0 +1 @@
+#define DBL_MAX __DBL_MAX__
diff --git a/clang/test/Modules/Inputs/System/usr/include/module.map b/clang/test/Modules/Inputs/System/usr/include/module.map
index 884b59c80cd..9b2f3af2bac 100644
--- a/clang/test/Modules/Inputs/System/usr/include/module.map
+++ b/clang/test/Modules/Inputs/System/usr/include/module.map
@@ -19,3 +19,14 @@ module cstd [system] {
header "stdint.h"
}
}
+
+module other_constants {
+ explicit module dbl_max {
+ header "dbl_max.h"
+ }
+}
+
+module uses_other_constants {
+ header "uses_other_constants.h"
+ export *
+}
diff --git a/clang/test/Modules/Inputs/System/usr/include/uses_other_constants.h b/clang/test/Modules/Inputs/System/usr/include/uses_other_constants.h
new file mode 100644
index 00000000000..f6d4cca9f8f
--- /dev/null
+++ b/clang/test/Modules/Inputs/System/usr/include/uses_other_constants.h
@@ -0,0 +1,3 @@
+@import other_constants;
+#include <float.h>
+
diff --git a/clang/test/Modules/cstd.m b/clang/test/Modules/cstd.m
index 6d896a91557..3d1dcf38e33 100644
--- a/clang/test/Modules/cstd.m
+++ b/clang/test/Modules/cstd.m
@@ -1,6 +1,9 @@
// RUN: rm -rf %t
// RUN: %clang -fsyntax-only -isystem %S/Inputs/System/usr/include -fmodules -fmodules-cache-path=%t -D__need_wint_t -Werror=implicit-function-declaration %s
+@import uses_other_constants;
+const double other_value = DBL_MAX;
+
// Supplied by compiler, but referenced from the "/usr/include" module map.
@import cstd.float_constants;
@@ -16,7 +19,7 @@ void test_fprintf(FILE *file) {
// Supplied by compiler, which forwards to the "/usr/include" version.
@import cstd.stdint;
-my_awesome_nonstandard_integer_type value;
+my_awesome_nonstandard_integer_type value2;
// Supplied by the compiler; that version wins.
@import cstd.stdbool;
@@ -25,5 +28,3 @@ my_awesome_nonstandard_integer_type value;
# error "bool was not defined!"
#endif
-
-
OpenPOWER on IntegriCloud