diff options
author | Ian Anderson <iana@apple.com> | 2023-09-06 22:24:40 -0700 |
---|---|---|
committer | Ian Anderson <iana@apple.com> | 2023-09-28 11:30:09 -0700 |
commit | 0ea3d88bdb16aa6e9a0043cc3ed93dcb88a89dea (patch) | |
tree | 3a0bc1879ad0060efe5eca8394c2a7d2c16489c1 /clang/lib/Lex/ModuleMap.cpp | |
parent | 6b03d8aa9432682343efae24dcf31d911e634320 (diff) | |
download | llvm-0ea3d88bdb16aa6e9a0043cc3ed93dcb88a89dea.zip llvm-0ea3d88bdb16aa6e9a0043cc3ed93dcb88a89dea.tar.gz llvm-0ea3d88bdb16aa6e9a0043cc3ed93dcb88a89dea.tar.bz2 |
[Modules] Add a flag to control builtin headers being in system modules
Including select builtin headers in system modules is a workaround for module cycles, primarily in Apple's Darwin module that includes all of its C standard library headers. The workaround is problematic because it doesn't include all of the builtin headers (inttypes.h is notably absent), and it also doesn't include C++ headers. The straightforward for for this is to make top level modules for all of the C standard library headers and unwind.h in C++, clang, and the OS.
However, doing so in clang before the OS modules are ready re-introduces the module cycles. Add a -fbuiltin-headers-in-system-modules option to control if the special builtin headers belong to system modules or builtin modules. Pass the option by default for Apple.
Reviewed By: ChuanqiXu, Bigcheese, benlangmuir
Differential Revision: https://reviews.llvm.org/D159483
Diffstat (limited to 'clang/lib/Lex/ModuleMap.cpp')
-rw-r--r-- | clang/lib/Lex/ModuleMap.cpp | 69 |
1 files changed, 46 insertions, 23 deletions
diff --git a/clang/lib/Lex/ModuleMap.cpp b/clang/lib/Lex/ModuleMap.cpp index bee3a48..4dcd911 100644 --- a/clang/lib/Lex/ModuleMap.cpp +++ b/clang/lib/Lex/ModuleMap.cpp @@ -253,6 +253,45 @@ OptionalFileEntryRef ModuleMap::findHeader( return NormalHdrFile; } +/// Determine whether the given file name is the name of a builtin +/// header, supplied by Clang to replace, override, or augment existing system +/// headers. +static bool isBuiltinHeaderName(StringRef FileName) { + return llvm::StringSwitch<bool>(FileName) + .Case("float.h", true) + .Case("iso646.h", true) + .Case("limits.h", true) + .Case("stdalign.h", true) + .Case("stdarg.h", true) + .Case("stdatomic.h", true) + .Case("stdbool.h", true) + .Case("stddef.h", true) + .Case("stdint.h", true) + .Case("tgmath.h", true) + .Case("unwind.h", true) + .Default(false); +} + +/// Determine whether the given module name is the name of a builtin +/// module that is cyclic with a system module on some platforms. +static bool isBuiltInModuleName(StringRef ModuleName) { + return llvm::StringSwitch<bool>(ModuleName) + .Case("_Builtin_float", true) + .Case("_Builtin_inttypes", true) + .Case("_Builtin_iso646", true) + .Case("_Builtin_limits", true) + .Case("_Builtin_stdalign", true) + .Case("_Builtin_stdarg", true) + .Case("_Builtin_stdatomic", true) + .Case("_Builtin_stdbool", true) + .Case("_Builtin_stddef", true) + .Case("_Builtin_stdint", true) + .Case("_Builtin_stdnoreturn", true) + .Case("_Builtin_tgmath", true) + .Case("_Builtin_unwind", true) + .Default(false); +} + void ModuleMap::resolveHeader(Module *Mod, const Module::UnresolvedHeaderDirective &Header, bool &NeedsFramework) { @@ -297,7 +336,7 @@ bool ModuleMap::resolveAsBuiltinHeader( llvm::sys::path::is_absolute(Header.FileName) || Mod->isPartOfFramework() || !Mod->IsSystem || Header.IsUmbrella || !BuiltinIncludeDir || BuiltinIncludeDir == Mod->Directory || - !isBuiltinHeader(Header.FileName)) + !LangOpts.BuiltinHeadersInSystemModules || !isBuiltinHeaderName(Header.FileName)) return false; // This is a system module with a top-level header. This header @@ -373,28 +412,9 @@ static StringRef sanitizeFilenameAsIdentifier(StringRef Name, return Name; } -/// Determine whether the given file name is the name of a builtin -/// header, supplied by Clang to replace, override, or augment existing system -/// headers. -bool ModuleMap::isBuiltinHeader(StringRef FileName) { - return llvm::StringSwitch<bool>(FileName) - .Case("float.h", true) - .Case("iso646.h", true) - .Case("limits.h", true) - .Case("stdalign.h", true) - .Case("stdarg.h", true) - .Case("stdatomic.h", true) - .Case("stdbool.h", true) - .Case("stddef.h", true) - .Case("stdint.h", true) - .Case("tgmath.h", true) - .Case("unwind.h", true) - .Default(false); -} - bool ModuleMap::isBuiltinHeader(const FileEntry *File) { - return File->getDir() == BuiltinIncludeDir && - ModuleMap::isBuiltinHeader(llvm::sys::path::filename(File->getName())); + return File->getDir() == BuiltinIncludeDir && LangOpts.BuiltinHeadersInSystemModules && + isBuiltinHeaderName(llvm::sys::path::filename(File->getName())); } ModuleMap::HeadersMap::iterator @@ -2472,7 +2492,10 @@ void ModuleMapParser::parseHeaderDecl(MMToken::TokenKind LeadingToken, } bool NeedsFramework = false; - Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); + // Don't add the top level headers to the builtin modules if the builtin headers + // belong to the system modules. + if (!Map.LangOpts.BuiltinHeadersInSystemModules || ActiveModule->isSubModule() || !isBuiltInModuleName(ActiveModule->Name)) + Map.addUnresolvedHeader(ActiveModule, std::move(Header), NeedsFramework); if (NeedsFramework) Diags.Report(CurrModuleDeclLoc, diag::note_mmap_add_framework_keyword) |