Index: include/clang/Lex/HeaderSearch.h =================================================================== --- include/clang/Lex/HeaderSearch.h +++ include/clang/Lex/HeaderSearch.h @@ -95,6 +95,12 @@ /// external storage. const IdentifierInfo *ControllingMacro; + /// List of modules that import from this header. Since the number of modules + /// using the same FileEntry is usually small (2 or 3 at most, often related + /// to builtins) this should be enough. Choose a more appropriate data + /// structure in case the requirement changes. + llvm::SmallVector ModulesUsingHdr; + /// \brief If this header came from a framework include, this is the name /// of the framework. StringRef Framework; @@ -110,6 +116,15 @@ const IdentifierInfo * getControllingMacro(ExternalPreprocessorSource *External); + /// \brief Add a module \p M that uses this header. + void addModulesUsingHdr(const Module *M); + /// \brief Add modules that uses this header from \p OtherModulesUsingHdr. + void addModulesUsingHdr(ArrayRef OtherModulesUsingHdr); + /// \return The list of modules importing from this header. + ArrayRef getModulesUsingHdr() const; + /// \return true if \p M is imports this header. + bool isModuleUsingHdr(const Module *M); + /// \brief Determine whether this is a non-default header file info, e.g., /// it corresponds to an actual header we've included or tried to include. bool isNonDefault() const { Index: include/clang/Lex/Preprocessor.h =================================================================== --- include/clang/Lex/Preprocessor.h +++ include/clang/Lex/Preprocessor.h @@ -500,6 +500,7 @@ typedef llvm::DenseMap MacroMap; friend class ASTReader; + friend class HeaderSearch; struct SubmoduleState; Index: lib/Lex/HeaderSearch.cpp =================================================================== --- lib/Lex/HeaderSearch.cpp +++ lib/Lex/HeaderSearch.cpp @@ -52,6 +52,27 @@ return ControllingMacro; } +void HeaderFileInfo::addModulesUsingHdr(const Module *M) { + for (auto *Mod : ModulesUsingHdr) + if (Mod == M) + return; + ModulesUsingHdr.push_back(M); +} +void HeaderFileInfo::addModulesUsingHdr( + ArrayRef OtherModulesUsingHdr) { + for (auto *M : OtherModulesUsingHdr) + addModulesUsingHdr(M); +} +ArrayRef HeaderFileInfo::getModulesUsingHdr() const { + return ModulesUsingHdr; +} +bool HeaderFileInfo::isModuleUsingHdr(const Module *M) { + for (auto *Mod : ModulesUsingHdr) + if (Mod == M) + return true; + return false; +} + ExternalHeaderFileInfoSource::~ExternalHeaderFileInfoSource() {} HeaderSearch::HeaderSearch(IntrusiveRefCntPtr HSOpts, @@ -969,6 +990,8 @@ HFI.isPragmaOnce |= OtherHFI.isPragmaOnce; HFI.isModuleHeader |= OtherHFI.isModuleHeader; HFI.NumIncludes += OtherHFI.NumIncludes; + if (OtherHFI.isImport || OtherHFI.isPragmaOnce) + HFI.addModulesUsingHdr(OtherHFI.getModulesUsingHdr()); if (!HFI.ControllingMacro && !HFI.ControllingMacroID) { HFI.ControllingMacro = OtherHFI.ControllingMacro; @@ -1089,9 +1112,18 @@ if (FileInfo.NumIncludes) return false; } else { // Otherwise, if this is a #include of a file that was previously #import'd - // or if this is the second #include of a #pragma once file, ignore it. - if (FileInfo.isImport) - return false; + // or if this is the second #include of a #pragma once file, ignore it: + // - if there not associated module or the module already imports + // from this header. + // - if any module associated with this header is visible. + if (FileInfo.isImport) { + if (!M || FileInfo.isModuleUsingHdr(M)) + return false; + ArrayRef OtherMods = FileInfo.getModulesUsingHdr(); + for (auto *OtherMod : OtherMods) + if (PP.CurSubmoduleState->VisibleModules.isVisible(OtherMod)) + return false; + } } // Next, check to see if the file is wrapped with #ifndef guards. If so, and Index: lib/Serialization/ASTReader.cpp =================================================================== --- lib/Serialization/ASTReader.cpp +++ lib/Serialization/ASTReader.cpp @@ -1688,6 +1688,8 @@ Module::Header H = { key.Filename, FileMgr.getFile(Filename) }; ModMap.addHeader(Mod, H, HeaderRole, /*Imported*/true); HFI.isModuleHeader |= !(HeaderRole & ModuleMap::TextualHeader); + if (HFI.isImport) + HFI.addModulesUsingHdr(Mod); } // This HeaderFileInfo was externally loaded. 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,12 @@ +// 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 -std=c++11 -fmodules -fimplicit-module-maps -fmodules-cache-path=%t -x objective-c++ -fmodules-local-submodule-visibility %s + +#include +#include +#include + +typedef ptrdiff_t try1_ptrdiff_t; +typedef my_ptrdiff_t try2_ptrdiff_t; +