On Thu, Oct 15, 2015 at 11:14 AM, Adrian Prantl <apra...@apple.com> wrote:
> > On Oct 14, 2015, at 5:07 PM, Richard Smith <rich...@metafoo.co.uk> wrote: > > Ack, there are non-modular headers in the Darwin module. =( I seem to > recall that they're not version-locked to your compiler, so we've got to > support them as-is? > > If we can't turn on local submodule visibility, then we need a module map > for libc++ that covers all of its headers. I'll look into pruning the > include path when building a module from an implicitly-loaded module map. > > > The attached patch implements this in the most hacky way; with it I can > successfully compile the first few hundred files of LLVM. > Slightly less hacky approach attached, does this also unstick you?
Index: include/clang/Basic/Module.h =================================================================== --- include/clang/Basic/Module.h (revision 250139) +++ include/clang/Basic/Module.h (working copy) @@ -200,6 +200,10 @@ /// built. unsigned ConfigMacrosExhaustive : 1; + /// \brief Whether files in this module can only include files from used + /// modules. + unsigned NoUndeclaredIncludes : 1; + /// \brief Describes the visibility of the various names within a /// particular module. enum NameVisibilityKind { Index: include/clang/Lex/ModuleMap.h =================================================================== --- include/clang/Lex/ModuleMap.h (revision 250139) +++ include/clang/Lex/ModuleMap.h (working copy) @@ -157,7 +157,8 @@ /// \brief The set of attributes that can be attached to a module. struct Attributes { - Attributes() : IsSystem(), IsExternC(), IsExhaustive() {} + Attributes() + : IsSystem(), IsExternC(), IsExhaustive(), NoUndeclaredIncludes() {} /// \brief Whether this is a system module. unsigned IsSystem : 1; @@ -167,6 +168,10 @@ /// \brief Whether this is an exhaustive set of configuration macros. unsigned IsExhaustive : 1; + + /// \brief Whether files in this module can only include files from + /// explicit dependencies of the module. + unsigned NoUndeclaredIncludes : 1; }; /// \brief A directory for which framework modules can be inferred. Index: lib/Basic/Module.cpp =================================================================== --- lib/Basic/Module.cpp (revision 250139) +++ lib/Basic/Module.cpp (working copy) @@ -32,7 +32,8 @@ IsFramework(IsFramework), IsExplicit(IsExplicit), IsSystem(false), IsExternC(false), IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false), InferExportWildcard(false), - ConfigMacrosExhaustive(false), NameVisibility(Hidden) { + ConfigMacrosExhaustive(false), NoUndeclaredIncludes(false), + NameVisibility(Hidden) { if (Parent) { if (!Parent->isAvailable()) IsAvailable = false; @@ -40,6 +41,8 @@ IsSystem = true; if (Parent->IsExternC) IsExternC = true; + if (Parent->NoUndeclaredIncludes) + NoUndeclaredIncludes = true; IsMissingRequirement = Parent->IsMissingRequirement; Parent->SubModuleIndex[Name] = Parent->SubModules.size(); Index: lib/Lex/HeaderSearch.cpp =================================================================== --- lib/Lex/HeaderSearch.cpp (revision 250554) +++ lib/Lex/HeaderSearch.cpp (working copy) @@ -393,6 +393,12 @@ return TopFrameworkDir; } +static bool needModuleLookup(Module *RequestingModule, + bool HasSuggestedModule) { + return HasSuggestedModule || + (RequestingModule && RequestingModule->NoUndeclaredIncludes); +} + /// DoFrameworkLookup - Do a lookup of the specified file in the current /// DirectoryLookup, which is a framework directory. const FileEntry *DirectoryLookup::DoFrameworkLookup( @@ -488,7 +494,7 @@ } // If we found the header and are allowed to suggest a module, do so now. - if (FE && SuggestedModule) { + if (FE && needModuleLookup(RequestingModule, SuggestedModule)) { // Find the framework in which this header occurs. StringRef FrameworkPath = FE->getDir()->getName(); bool FoundFramework = false; @@ -1144,13 +1150,31 @@ return ModMap.findModuleForHeader(File); } +static bool suggestModule(HeaderSearch &HS, const FileEntry *File, + Module *RequestingModule, + ModuleMap::KnownHeader *SuggestedModule) { + ModuleMap::KnownHeader Module = HS.findModuleForHeader(File); + if (SuggestedModule) + *SuggestedModule = Module; + + // If this module specifies [no_undeclared_includes], we cannot find any + // file that's in a non-dependency module. + if (RequestingModule && Module && RequestingModule->NoUndeclaredIncludes) { + HS.getModuleMap().resolveUses(RequestingModule, /*Complain*/false); + if (!RequestingModule->directlyUses(Module.getModule())) + return false; + } + + return true; +} + bool HeaderSearch::findUsableModuleForHeader( const FileEntry *File, const DirectoryEntry *Root, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir) { - if (File && SuggestedModule) { + if (File && needModuleLookup(RequestingModule, SuggestedModule)) { // If there is a module that corresponds to this header, suggest it. hasModuleMap(File->getName(), Root, IsSystemHeaderDir); - *SuggestedModule = findModuleForHeader(File); + return suggestModule(*this, File, RequestingModule, SuggestedModule); } return true; } @@ -1159,7 +1183,7 @@ const FileEntry *File, StringRef FrameworkName, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework) { // If we're supposed to suggest a module, look for one now. - if (SuggestedModule) { + if (needModuleLookup(RequestingModule, SuggestedModule)) { // Find the top-level framework based on this framework. SmallVector<std::string, 4> SubmodulePath; const DirectoryEntry *TopFrameworkDir @@ -1176,7 +1200,7 @@ // important so that we're consistent about whether this header // corresponds to a module. Possibly we should lock down framework modules // so that this is not possible. - *SuggestedModule = findModuleForHeader(File); + return suggestModule(*this, File, RequestingModule, SuggestedModule); } return true; } Index: lib/Lex/ModuleMap.cpp =================================================================== --- lib/Lex/ModuleMap.cpp (revision 250139) +++ lib/Lex/ModuleMap.cpp (working copy) @@ -663,6 +663,8 @@ Attrs.IsSystem |= inferred->second.Attrs.IsSystem; Attrs.IsExternC |= inferred->second.Attrs.IsExternC; Attrs.IsExhaustive |= inferred->second.Attrs.IsExhaustive; + Attrs.NoUndeclaredIncludes |= + inferred->second.Attrs.NoUndeclaredIncludes; ModuleMapFile = inferred->second.ModuleMapFile; } } @@ -699,6 +701,7 @@ Result->IsSystem |= Attrs.IsSystem; Result->IsExternC |= Attrs.IsExternC; Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; + Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; Result->Directory = FrameworkDir; if (!Parent) @@ -1286,7 +1289,9 @@ /// \brief The 'extern_c' attribute. AT_extern_c, /// \brief The 'exhaustive' attribute. - AT_exhaustive + AT_exhaustive, + /// \brief The 'no_undeclared_includes' attribute. + AT_no_undeclared_includes }; } @@ -1454,6 +1459,9 @@ ActiveModule->IsSystem = true; if (Attrs.IsExternC) ActiveModule->IsExternC = true; + if (Attrs.NoUndeclaredIncludes || + (!ActiveModule->Parent && ModuleName == "Darwin")) + ActiveModule->NoUndeclaredIncludes = true; ActiveModule->Directory = Directory; bool Done = false; @@ -2345,6 +2353,7 @@ = llvm::StringSwitch<AttributeKind>(Tok.getString()) .Case("exhaustive", AT_exhaustive) .Case("extern_c", AT_extern_c) + .Case("no_undeclared_includes", AT_no_undeclared_includes) .Case("system", AT_system) .Default(AT_unknown); switch (Attribute) { @@ -2364,6 +2373,10 @@ case AT_exhaustive: Attrs.IsExhaustive = true; break; + + case AT_no_undeclared_includes: + Attrs.NoUndeclaredIncludes = true; + break; } consumeToken(); Index: test/Modules/Inputs/libc-libcxx/include/c++/math.h =================================================================== --- test/Modules/Inputs/libc-libcxx/include/c++/math.h (revision 0) +++ test/Modules/Inputs/libc-libcxx/include/c++/math.h (working copy) @@ -0,0 +1,2 @@ +#include_next <math.h> +template<typename T> T abs(T t) { return (t < 0) ? -t : t; } Index: test/Modules/Inputs/libc-libcxx/include/c++/module.modulemap =================================================================== --- test/Modules/Inputs/libc-libcxx/include/c++/module.modulemap (revision 0) +++ test/Modules/Inputs/libc-libcxx/include/c++/module.modulemap (working copy) @@ -0,0 +1,4 @@ +module "libc++" { + module math { header "math.h" export * } + module stdlib { header "stdlib.h" export * } +} Index: test/Modules/Inputs/libc-libcxx/include/c++/stdlib.h =================================================================== --- test/Modules/Inputs/libc-libcxx/include/c++/stdlib.h (revision 0) +++ test/Modules/Inputs/libc-libcxx/include/c++/stdlib.h (working copy) @@ -0,0 +1 @@ +#include_next "stdlib.h" Index: test/Modules/Inputs/libc-libcxx/include/math.h =================================================================== --- test/Modules/Inputs/libc-libcxx/include/math.h (revision 0) +++ test/Modules/Inputs/libc-libcxx/include/math.h (working copy) @@ -0,0 +1 @@ +int abs(int); Index: test/Modules/Inputs/libc-libcxx/include/module.modulemap =================================================================== --- test/Modules/Inputs/libc-libcxx/include/module.modulemap (revision 0) +++ test/Modules/Inputs/libc-libcxx/include/module.modulemap (working copy) @@ -0,0 +1,4 @@ +module libc [no_undeclared_includes] { + module math { header "math.h" export * } + module stdlib { header "stdlib.h" export * } +} Index: test/Modules/Inputs/libc-libcxx/include/stdlib.h =================================================================== --- test/Modules/Inputs/libc-libcxx/include/stdlib.h (revision 0) +++ test/Modules/Inputs/libc-libcxx/include/stdlib.h (working copy) @@ -0,0 +1 @@ +#include <math.h> Index: test/Modules/libc-libcxx.cpp =================================================================== --- test/Modules/libc-libcxx.cpp (revision 0) +++ test/Modules/libc-libcxx.cpp (working copy) @@ -0,0 +1,8 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -x c++ -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -I %S/Inputs/libc-libcxx/include/c++ -I %S/Inputs/libc-libcxx/include %s -verify +// expected-no-diagnostics + +#include "math.h" + +int n = abs(0); +float f = abs<float>(0.f);
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits