@@ -420,7 +420,8 @@ GetWindowsAuxiliaryFile(StringRef modulemap, const SearchPathOptions &Options) {
420420
421421SmallVector<std::pair<std::string, std::string>, 2 > GetWindowsFileMappings (
422422 ASTContext &Context,
423- const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &driverVFS) {
423+ const llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &driverVFS,
424+ bool &requiresBuiltinHeadersInSystemModules) {
424425 const llvm::Triple &Triple = Context.LangOpts .Target ;
425426 const SearchPathOptions &SearchPathOpts = Context.SearchPathOpts ;
426427 SmallVector<std::pair<std::string, std::string>, 2 > Mappings;
@@ -468,8 +469,21 @@ SmallVector<std::pair<std::string, std::string>, 2> GetWindowsFileMappings(
468469 llvm::sys::path::append (UCRTInjection, " module.modulemap" );
469470
470471 AuxiliaryFile = GetWindowsAuxiliaryFile (" ucrt.modulemap" , SearchPathOpts);
471- if (!AuxiliaryFile.empty ())
472+ if (!AuxiliaryFile.empty ()) {
473+ // The ucrt module map has the C standard library headers all together.
474+ // That leads to module cycles with the clang _Builtin_ modules. e.g.
475+ // <fenv.h> on ucrt includes <float.h>. The clang builtin <float.h>
476+ // include-nexts <float.h>. When both of those UCRT headers are in the
477+ // ucrt module, there's a module cycle ucrt -> _Builtin_float -> ucrt
478+ // (i.e. fenv.h (ucrt) -> float.h (builtin) -> float.h (ucrt)). Until the
479+ // ucrt module map is updated, the builtin headers need to join the system
480+ // modules. i.e. when the builtin float.h is in the ucrt module too, the
481+ // cycle goes away. Note that -fbuiltin-headers-in-system-modules does
482+ // nothing to fix the same problem with C++ headers, and is generally
483+ // fragile.
472484 Mappings.emplace_back (std::string (UCRTInjection), AuxiliaryFile);
485+ requiresBuiltinHeadersInSystemModules = true ;
486+ }
473487 }
474488
475489 struct {
@@ -515,20 +529,36 @@ ClangInvocationFileMapping swift::getClangInvocationFileMapping(
515529
516530 const llvm::Triple &triple = ctx.LangOpts .Target ;
517531
532+ SmallVector<std::pair<std::string, std::string>, 2 > libcFileMapping;
518533 if (triple.isOSWASI ()) {
519534 // WASI Mappings
520- result. redirectedFiles . append (
521- getLibcFileMapping (ctx, " wasi-libc.modulemap" , std::nullopt , vfs)) ;
535+ libcFileMapping =
536+ getLibcFileMapping (ctx, " wasi-libc.modulemap" , std::nullopt , vfs);
522537 } else {
523538 // Android/BSD/Linux Mappings
524- result. redirectedFiles . append ( getLibcFileMapping (
525- ctx, " glibc.modulemap " , StringRef (" SwiftGlibc.h" ), vfs) );
539+ libcFileMapping = getLibcFileMapping (ctx, " glibc.modulemap " ,
540+ StringRef (" SwiftGlibc.h" ), vfs);
526541 }
542+ result.redirectedFiles .append (libcFileMapping);
543+ // Both libc module maps have the C standard library headers all together in a
544+ // SwiftLibc module. That leads to module cycles with the clang _Builtin_
545+ // modules. e.g. <inttypes.h> includes <stdint.h> on these platforms. The
546+ // clang builtin <stdint.h> include-nexts <stdint.h>. When both of those
547+ // platform headers are in the SwiftLibc module, there's a module cycle
548+ // SwiftLibc -> _Builtin_stdint -> SwiftLibc (i.e. inttypes.h (platform) ->
549+ // stdint.h (builtin) -> stdint.h (platform)). Until this can be fixed in
550+ // these module maps, the clang builtin headers need to join the "system"
551+ // modules (SwiftLibc). i.e. when the clang builtin stdint.h is in the
552+ // SwiftLibc module too, the cycle goes away. Note that
553+ // -fbuiltin-headers-in-system-modules does nothing to fix the same problem
554+ // with C++ headers, and is generally fragile.
555+ result.requiresBuiltinHeadersInSystemModules = !libcFileMapping.empty ();
527556
528557 if (ctx.LangOpts .EnableCXXInterop )
529558 getLibStdCxxFileMapping (result, ctx, vfs);
530559
531- result.redirectedFiles .append (GetWindowsFileMappings (ctx, vfs));
560+ result.redirectedFiles .append (GetWindowsFileMappings (
561+ ctx, vfs, result.requiresBuiltinHeadersInSystemModules ));
532562
533563 return result;
534564}
0 commit comments