[libcxx] r249738 - Split <ctype.h> out of <cctype>.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 16 15:27:26 PDT 2015


On Thu, Oct 15, 2015 at 11:14 AM, Adrian Prantl <aprantl at apple.com> wrote:

>
> On Oct 14, 2015, at 5:07 PM, Richard Smith <richard at 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?
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20151016/ef80dba9/attachment.html>
-------------- next part --------------
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);


More information about the cfe-commits mailing list