Index: include/clang/Lex/ModuleMap.h =================================================================== --- include/clang/Lex/ModuleMap.h +++ include/clang/Lex/ModuleMap.h @@ -272,6 +272,11 @@ /// umbrella directories and find or create a module for it. KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File); + /// \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); + /// \brief A convenience method to determine if \p File is (possibly nested) /// in an umbrella directory. bool isHeaderInUmbrellaDirs(const FileEntry *File) { Index: lib/Frontend/FrontendActions.cpp =================================================================== --- lib/Frontend/FrontendActions.cpp +++ lib/Frontend/FrontendActions.cpp @@ -177,10 +177,10 @@ static void addHeaderInclude(StringRef HeaderName, SmallVectorImpl &Includes, const LangOptions &LangOpts, - bool IsExternC) { + bool IsExternC, bool AlwaysInclude = false) { if (IsExternC && LangOpts.CPlusPlus) Includes += "extern \"C\" {\n"; - if (LangOpts.ObjC1) + if (LangOpts.ObjC1 && !AlwaysInclude) Includes += "#import \""; else Includes += "#include \""; @@ -215,7 +215,17 @@ // file relative to the module build directory (the directory containing // the module map file) so this will find the same file that we found // while parsing the module map. - addHeaderInclude(H.NameAsWritten, Includes, LangOpts, Module->IsExternC); + // Since builtins are treated as textual headers and there's no context + // leak in local submodule visibility, make sure we use #include + // instead of #import (even in ObjC/C++) and guarantee it's always + // included. + bool IsBuiltin = false; + if (LangOpts.ObjC1 && llvm::sys::path::is_absolute(H.NameAsWritten) && + ModuleMap::isBuiltinHeader( + llvm::sys::path::filename(H.NameAsWritten))) + IsBuiltin = true; + addHeaderInclude(H.NameAsWritten, Includes, LangOpts, Module->IsExternC, + IsBuiltin /*AlwaysInclude*/); } } // Note that Module->PrivateHeaders will not be a TopHeader. Index: lib/Lex/ModuleMap.cpp =================================================================== --- lib/Lex/ModuleMap.cpp +++ lib/Lex/ModuleMap.cpp @@ -144,7 +144,7 @@ /// \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) { +bool ModuleMap::isBuiltinHeader(StringRef FileName) { return llvm::StringSwitch(FileName) .Case("float.h", true) .Case("iso646.h", true) @@ -1847,7 +1847,7 @@ // supplied by Clang. Find that builtin header. if (ActiveModule->IsSystem && LeadingToken != MMToken::UmbrellaKeyword && BuiltinIncludeDir && BuiltinIncludeDir != Directory && - isBuiltinHeader(Header.FileName)) { + ModuleMap::isBuiltinHeader(Header.FileName)) { SmallString<128> BuiltinPathName(BuiltinIncludeDir->getName()); llvm::sys::path::append(BuiltinPathName, Header.FileName); BuiltinFile = SourceMgr.getFileManager().getFile(BuiltinPathName); Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/cstddef =================================================================== --- /dev/null +++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/cstddef @@ -0,0 +1,9 @@ +#ifndef _LIBCPP_CSTDDEF +#define _LIBCPP_CSTDDEF + +#include +#include + +typedef ptrdiff_t my_ptrdiff_t; + +#endif Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h =================================================================== --- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h +++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h @@ -4,4 +4,6 @@ #include_next template T abs(T t) { return (t < 0) ? -t : t; } +#include + #endif Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap =================================================================== --- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap +++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap @@ -6,5 +6,7 @@ // FIXME: remove "textual" from stdint module below once the issue // between umbrella headers and builtins is resolved. module stdint { textual header "stdint.h" export * } + module type_traits { header "type_traits" export * } + module cstddef { header "cstddef" export * } module __config { header "__config" export * } } Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h =================================================================== --- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h +++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h @@ -2,5 +2,6 @@ #define LIBCXX_STDDEF_H #include <__config> +#include_next #endif Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/type_traits =================================================================== --- /dev/null +++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/type_traits @@ -0,0 +1,6 @@ +#ifndef _LIBCPP_TYPE_TRAITS +#define _LIBCPP_TYPE_TRAITS + +#include + +#endif Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap =================================================================== --- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap +++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap @@ -5,4 +5,12 @@ module stdint { header "stdint.h" export * } module stdio { header "stdio.h" export * } module util { header "util.h" export * } + module POSIX { + module sys { + module types { + umbrella header "sys/_types/_types.h" + export * + } + } + } } Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h =================================================================== --- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h +++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h @@ -1 +1,6 @@ -// stddef.h +#ifndef __STDDEF_H__ +#define __STDDEF_H__ + +#include "sys/_types/_ptrdiff_t.h" + +#endif Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/sys/_types/_ptrdiff_t.h =================================================================== --- /dev/null +++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/sys/_types/_ptrdiff_t.h @@ -0,0 +1,4 @@ +#ifndef _PTRDIFF_T +#define _PTRDIFF_T +typedef int * ptrdiff_t; +#endif /* _PTRDIFF_T */ Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/sys/_types/_types.h =================================================================== --- /dev/null +++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/sys/_types/_types.h @@ -0,0 +1,6 @@ +#ifndef _SYS_TYPES_UMBRELLA +#define _SYS_TYPES_UMBRELLA + +#include "_ptrdiff_t.h" + +#endif Index: test/Modules/builtin-import.mm =================================================================== --- /dev/null +++ test/Modules/builtin-import.mm @@ -0,0 +1,6 @@ +// REQUIRES: system-darwin + +// RUN: rm -rf %t +// RUN: %clang -cc1 -fsyntax-only -nostdinc++ -isysroot %S/Inputs/libc-libcxx/sysroot -isystem %S/Inputs/libc-libcxx/sysroot/usr/include/c++/v1 -F%S/Inputs/libc-libcxx/sysroot/Frameworks -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c++ -fmodules-local-submodule-visibility %s + +#include