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

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Oct 14 15:09:33 PDT 2016


On Fri, Oct 14, 2016 at 11:44 AM, Bruno Cardoso Lopes <
bruno.cardoso at gmail.com> wrote:

> Hi Richard,
>
> I have a patch on top of your suggested patch from a year ago, that
> break the cyclic dependency we're seeing, with this (and a few changes
> to the SDK) we can bootstrap clang with submodule local visibility on
> darwin. I've attached the patch with a reduced, standalone testcase
> that doesn't depend on the SDK. The issues that are not covered by
> your patch, that I cover in mine, are related to built-in and textual
> headers: they can be found in paths where they don't map to any
> modules, triggering other cycles. I fix that by looking further to
> find a matching module for the header in question, instead the first
> found header in header search.
>

It looks like the 0002 patch is working around a bug in the 0001 patch:
with 0001 applied, a module with [no_undeclared_includes] can still include
a textual header from another module on which it doesn't declare a
dependency (in the testcase, the libc module is incorrectly permitted to
include the textual header <stdio.h> from libc++). Rather than preferring
non-modular headers over modular headers as the 0002 patch does, I wonder
if the issue could instead be resolved by fixing that apparent bug.

I gave that a go; the result is attached. I also had to change the way we
handle builtin headers -- instead of implicitly including (for instance)
the builtin <stddef.h> as a modular header in any module that provides its
own <stddef.h>, I now only include it as a textual header (this also lets
us use the same approach for this case whether or not we're using local
submodule visibility). That exposed a couple of testcases that were
(unreasonably, in my opinion) failing to include_next the real builtin
header from their wrapper header.

The attached patch causes your testcase to pass; I'd be interested to know
if it works in practice on Darwin.

Thanks!


> Can you take a look?
>
> Thanks,
>
>
> On Thu, Jul 28, 2016 at 3:55 PM, Adrian Prantl via cfe-commits
> <cfe-commits at lists.llvm.org> wrote:
> > +Bruno
> >
> > On Jul 27, 2016, at 11:58 PM, Nico Weber <thakis at chromium.org> wrote:
> >
> > I played with modules a bit today, and as far as I can tell this is still
> > broken. If this proves difficult to fix, should this change be reverted
> for
> > now? It breaks using modules on Darwin.
> >
> > On Sun, Mar 13, 2016 at 12:53 AM, Adrian Prantl via cfe-commits
> > <cfe-commits at lists.llvm.org> wrote:
> >>
> >> > On Mar 11, 2016, at 4:11 PM, Duncan P. N. Exon Smith
> >> > <dexonsmith at apple.com> wrote:
> >> >
> >> > Did anyone file a PR for this?
> >> >
> >>
> >> I filed PR 26928 - Prune the include path for modules
> >> https://llvm.org/bugs/show_bug.cgi?id=26928
> >> as a starting point.
> >>
> >> -- adrian
> >>
> >> _______________________________________________
> >> cfe-commits mailing list
> >> cfe-commits at lists.llvm.org
> >> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
> >
> >
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at lists.llvm.org
> > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
> >
>
>
>
> --
> Bruno Cardoso Lopes
> http://www.brunocardoso.cc
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161014/8dd75e50/attachment-0001.html>
-------------- next part --------------
Index: include/clang/Basic/Module.h
===================================================================
--- include/clang/Basic/Module.h	(revision 284181)
+++ include/clang/Basic/Module.h	(working copy)
@@ -201,6 +201,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/HeaderSearch.h
===================================================================
--- include/clang/Lex/HeaderSearch.h	(revision 284181)
+++ include/clang/Lex/HeaderSearch.h	(working copy)
@@ -523,8 +523,10 @@
   /// \brief Retrieve the module that corresponds to the given file, if any.
   ///
   /// \param File The header that we wish to map to a module.
-  ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File) const;
-  
+  /// \param AllowTextual Whether we want to find textual headers too.
+  ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File,
+                                             bool AllowTextual = false) const;
+
   /// \brief Read the contents of the given module map file.
   ///
   /// \param File The module map file.
Index: include/clang/Lex/ModuleMap.h
===================================================================
--- include/clang/Lex/ModuleMap.h	(revision 284181)
+++ include/clang/Lex/ModuleMap.h	(working copy)
@@ -171,7 +171,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;
@@ -181,6 +182,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.
@@ -315,10 +320,15 @@
   ///
   /// \param File The header file that is likely to be included.
   ///
+  /// \param AllowTextual If \c true and \p File is a textual header, return
+  /// its owning module. Otherwise, no KnownHeader will be returned if the
+  /// file is only known as a textual header.
+  ///
   /// \returns The module KnownHeader, which provides the module that owns the
   /// given header file.  The KnownHeader is default constructed to indicate
   /// that no module owns this header file.
-  KnownHeader findModuleForHeader(const FileEntry *File);
+  KnownHeader findModuleForHeader(const FileEntry *File,
+                                  bool AllowTextual = false);
 
   /// \brief Retrieve all the modules that contain the given header file. This
   /// may not include umbrella modules, nor information from external sources,
Index: lib/Basic/Module.cpp
===================================================================
--- lib/Basic/Module.cpp	(revision 284181)
+++ lib/Basic/Module.cpp	(working copy)
@@ -33,7 +33,7 @@
       IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
       IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
       InferExportWildcard(false), ConfigMacrosExhaustive(false),
-      NameVisibility(Hidden) {
+      NoUndeclaredIncludes(false), NameVisibility(Hidden) {
   if (Parent) {
     if (!Parent->isAvailable())
       IsAvailable = false;
@@ -41,6 +41,8 @@
       IsSystem = true;
     if (Parent->IsExternC)
       IsExternC = true;
+    if (Parent->NoUndeclaredIncludes)
+      NoUndeclaredIncludes = true;
     IsMissingRequirement = Parent->IsMissingRequirement;
     
     Parent->SubModuleIndex[Name] = Parent->SubModules.size();
@@ -181,6 +183,11 @@
   for (auto *Use : Top->DirectUses)
     if (Requested->isSubModuleOf(Use))
       return true;
+
+  // Anyone is allowed to use our builtin stddef.h and its accompanying module.
+  if (!Requested->Parent && Requested->Name == "_Builtin_stddef_max_align_t")
+    return true;
+
   return false;
 }
 
Index: lib/Lex/HeaderSearch.cpp
===================================================================
--- lib/Lex/HeaderSearch.cpp	(revision 284181)
+++ lib/Lex/HeaderSearch.cpp	(working copy)
@@ -413,6 +413,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(
@@ -508,7 +514,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;
@@ -1158,22 +1164,45 @@
 }
 
 ModuleMap::KnownHeader
-HeaderSearch::findModuleForHeader(const FileEntry *File) const {
+HeaderSearch::findModuleForHeader(const FileEntry *File,
+                                  bool AllowTextual) const {
   if (ExternalSource) {
     // Make sure the external source has handled header info about this file,
     // which includes whether the file is part of a module.
     (void)getExistingFileInfo(File);
   }
-  return ModMap.findModuleForHeader(File);
+  return ModMap.findModuleForHeader(File, AllowTextual);
 }
 
+static bool suggestModule(HeaderSearch &HS, const FileEntry *File,
+                          Module *RequestingModule,
+                          ModuleMap::KnownHeader *SuggestedModule) {
+  ModuleMap::KnownHeader Module =
+      HS.findModuleForHeader(File, /*AllowTextual*/true);
+  if (SuggestedModule)
+    *SuggestedModule = (Module.getRole() & ModuleMap::TextualHeader)
+                           ? ModuleMap::KnownHeader()
+                           : 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;
 }
@@ -1182,7 +1211,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
@@ -1199,7 +1228,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 284181)
+++ lib/Lex/ModuleMap.cpp	(working copy)
@@ -327,9 +327,10 @@
   return false;
 }
 
-ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File) {
+ModuleMap::KnownHeader ModuleMap::findModuleForHeader(const FileEntry *File,
+                                                      bool AllowTextual) {
   auto MakeResult = [&](ModuleMap::KnownHeader R) -> ModuleMap::KnownHeader {
-    if (R.getRole() & ModuleMap::TextualHeader)
+    if (!AllowTextual && R.getRole() & ModuleMap::TextualHeader)
       return ModuleMap::KnownHeader();
     return R;
   };
@@ -674,6 +675,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;
         }
       }
@@ -711,6 +714,7 @@
   Result->IsSystem |= Attrs.IsSystem;
   Result->IsExternC |= Attrs.IsExternC;
   Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive;
+  Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes;
   Result->Directory = FrameworkDir;
 
   // umbrella header "umbrella-header-name"
@@ -1309,7 +1313,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
   };
 }
 
@@ -1479,6 +1485,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;
@@ -1845,13 +1854,7 @@
         // If Clang supplies this header but the underlying system does not,
         // just silently swap in our builtin version. Otherwise, we'll end
         // up adding both (later).
-        //
-        // For local visibility, entirely replace the system file with our
-        // one and textually include the system one. We need to pass macros
-        // from our header to the system one if we #include_next it.
-        //
-        // FIXME: Can we do this in all cases?
-        if (BuiltinFile && (!File || Map.LangOpts.ModulesLocalVisibility)) {
+        if (BuiltinFile && !File) {
           File = BuiltinFile;
           RelativePathName = BuiltinPathName;
           BuiltinFile = nullptr;
@@ -1877,15 +1880,16 @@
       Module::Header H = {RelativePathName.str(), File};
       Map.excludeHeader(ActiveModule, H);
     } else {
-      // If there is a builtin counterpart to this file, add it now, before
-      // the "real" header, so we build the built-in one first when building
-      // the module.
+      // If there is a builtin counterpart to this file, add it now as a textual
+      // header, so it can be #include_next'd by the wrapper header, and can
+      // receive macros from the wrapper header.
       if (BuiltinFile) {
         // FIXME: Taking the name from the FileEntry is unstable and can give
         // different results depending on how we've previously named that file
         // in this build.
         Module::Header H = { BuiltinFile->getName(), BuiltinFile };
-        Map.addHeader(ActiveModule, H, Role);
+        Map.addHeader(ActiveModule, H, ModuleMap::ModuleHeaderRole(
+                                           Role | ModuleMap::TextualHeader));
       }
 
       // Record this header.
@@ -2375,6 +2379,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) {
@@ -2394,6 +2399,10 @@
     case AT_exhaustive:
       Attrs.IsExhaustive = true;
       break;
+
+    case AT_no_undeclared_includes:
+      Attrs.NoUndeclaredIncludes = true;
+      break;
     }
     consumeToken();
 
Index: test/Modules/Inputs/System/usr/include/stdbool.h
===================================================================
--- test/Modules/Inputs/System/usr/include/stdbool.h	(revision 284181)
+++ test/Modules/Inputs/System/usr/include/stdbool.h	(working copy)
@@ -1 +1 @@
-// Testing hack: does not define bool/true/false.
+#include_next <stdbool.h>
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/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/__config
===================================================================
--- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/__config	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/__config	(working copy)
@@ -0,0 +1,6 @@
+#ifndef _LIBCPP_CONFIG
+#define _LIBCPP_CONFIG
+
+#define __LIBCXX_CONFIG
+
+#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	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/math.h	(working copy)
@@ -0,0 +1,7 @@
+#ifndef LIBCXX_MATH_H
+#define LIBCXX_MATH_H
+
+#include_next <math.h>
+template<typename T> T abs(T t) { return (t < 0) ? -t : t; }
+
+#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	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/module.modulemap	(working copy)
@@ -0,0 +1,7 @@
+module "libc++" {
+  module math { header "math.h" export * }
+  module stdlib { header "stdlib.h" export * }
+  module stddef { header "stddef.h" export * }
+  module stdio { textual header "stdio.h" 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	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stddef.h	(working copy)
@@ -0,0 +1,6 @@
+#ifndef LIBCXX_STDDEF_H
+#define LIBCXX_STDDEF_H
+
+#include <__config>
+
+#endif
Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdio.h
===================================================================
--- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdio.h	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdio.h	(working copy)
@@ -0,0 +1,6 @@
+#ifndef LIBCXX_STDIO_H
+#define LIBCXX_STDIO_H
+
+#include <__config>
+
+#endif
Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdlib.h
===================================================================
--- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdlib.h	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/c++/v1/stdlib.h	(working copy)
@@ -0,0 +1,6 @@
+#ifndef LIBCXX_STDLIB_H
+#define LIBCXX_STDLIB_H
+
+#include_next "stdlib.h"
+
+#endif
Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/math.h
===================================================================
--- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/math.h	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/math.h	(working copy)
@@ -0,0 +1 @@
+int abs(int);
Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap
===================================================================
--- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/module.modulemap	(working copy)
@@ -0,0 +1,9 @@
+module libc [no_undeclared_includes] {
+  module math { header "math.h" export * }
+  module stdlib { header "stdlib.h" export * }
+  module stdatomic { header "stdatomic.h" export * }
+  module stddef { header "stddef.h" export * }
+  module stdint { header "stdint.h" export * }
+  module stdio { header "stdio.h" export * }
+  module util { header "util.h" export * }
+}
Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h
===================================================================
--- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stddef.h	(working copy)
@@ -0,0 +1,2 @@
+// stddef.h
+#include_next "stddef.h"
Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdint.h
===================================================================
--- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdint.h	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdint.h	(working copy)
@@ -0,0 +1,22 @@
+typedef char           int_least8_t;
+typedef short         int_least16_t;
+typedef int         int_least32_t;
+typedef long long int         int_least64_t;
+typedef unsigned char         uint_least8_t;
+typedef unsigned short       uint_least16_t;
+typedef unsigned int       uint_least32_t;
+typedef unsigned long long       uint_least64_t;
+
+typedef char           int_fast8_t;
+typedef short         int_fast16_t;
+typedef int         int_fast32_t;
+typedef long long int         int_fast64_t;
+typedef unsigned char         uint_fast8_t;
+typedef unsigned short       uint_fast16_t;
+typedef unsigned int       uint_fast32_t;
+typedef unsigned long long       uint_fast64_t;
+
+typedef int * intptr_t;
+typedef unsigned int * uintptr_t;
+typedef int intmax_t;
+typedef unsigned int uintmax_t;
Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdio.h
===================================================================
--- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdio.h	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdio.h	(working copy)
@@ -0,0 +1,4 @@
+#ifndef DARWIN_STDIO_H
+#define DARWIN_STDIO_H
+
+#endif
Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdlib.h
===================================================================
--- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdlib.h	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/stdlib.h	(working copy)
@@ -0,0 +1 @@
+#include <math.h>
Index: test/Modules/Inputs/libc-libcxx/sysroot/usr/include/util.h
===================================================================
--- test/Modules/Inputs/libc-libcxx/sysroot/usr/include/util.h	(revision 0)
+++ test/Modules/Inputs/libc-libcxx/sysroot/usr/include/util.h	(working copy)
@@ -0,0 +1,6 @@
+#ifndef DARWIN_UTIL_H
+#define DARWIN_UTIL_H
+
+#include <stdio.h>
+
+#endif
Index: test/Modules/libc-libcxx.cpp
===================================================================
--- test/Modules/libc-libcxx.cpp	(revision 0)
+++ test/Modules/libc-libcxx.cpp	(working copy)
@@ -0,0 +1,10 @@
+// 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
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -x c++ -fmodules-cache-path=%t -fmodules -fimplicit-module-maps -fmodules-local-submodule-visibility -nostdinc++ -isystem %S/Inputs/libc-libcxx/sysroot/usr/include/c++/v1 -isystem %S/Inputs/libc-libcxx/sysroot/usr/include -fsyntax-only %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