diff --git a/interpreter/cling/include/cling/std.modulemap b/interpreter/cling/include/cling/std.modulemap index d5bb22388e12b09f32a36af2e7cb2ee0e6e339a7..6f150355d8aa0f50863c2c5f632dd13132b40b25 100644 --- a/interpreter/cling/include/cling/std.modulemap +++ b/interpreter/cling/include/cling/std.modulemap @@ -429,8 +429,8 @@ module "std" [system] { export * header "bits/basic_ios.h" } - module "bits/chrono.h" { - requires cplusplus20 + module "bits/chrono.h" [optional] { + requires cplusplus17 export * header "bits/chrono.h" } diff --git a/interpreter/llvm/src/tools/clang/include/clang/Basic/Module.h b/interpreter/llvm/src/tools/clang/include/clang/Basic/Module.h index 3476b05d2e929ac22fc6e12db6d22b243baad578..f62e657fef7e6319fe710d8d51c549ccf4d7ab2a 100644 --- a/interpreter/llvm/src/tools/clang/include/clang/Basic/Module.h +++ b/interpreter/llvm/src/tools/clang/include/clang/Basic/Module.h @@ -303,6 +303,9 @@ public: /// and headers from used modules. unsigned NoUndeclaredIncludes : 1; + /// Whether the submodule is allowed to have missing headers. + unsigned IsOptional: 1; + /// Whether this module came from a "private" module map, found next /// to a regular (public) module map. unsigned ModuleMapIsPrivate : 1; diff --git a/interpreter/llvm/src/tools/clang/include/clang/Lex/ModuleMap.h b/interpreter/llvm/src/tools/clang/include/clang/Lex/ModuleMap.h index 41f85a1f572d7ae687ff2fdde25b98d143062ebe..26ed708c49effb77e1b1b3e65a5fbe7d5c9a4537 100644 --- a/interpreter/llvm/src/tools/clang/include/clang/Lex/ModuleMap.h +++ b/interpreter/llvm/src/tools/clang/include/clang/Lex/ModuleMap.h @@ -241,9 +241,12 @@ private: /// and headers from used modules. unsigned NoUndeclaredIncludes : 1; + /// Whether we can have a submodule with missing header files. + unsigned IsOptional : 1; + Attributes() : IsSystem(false), IsExternC(false), IsExhaustive(false), - NoUndeclaredIncludes(false) {} + NoUndeclaredIncludes(false), IsOptional(false) {} }; /// A directory for which framework modules can be inferred. diff --git a/interpreter/llvm/src/tools/clang/lib/Basic/Module.cpp b/interpreter/llvm/src/tools/clang/lib/Basic/Module.cpp index 07ee82ceb6041bd5e5c0011cdc8c1088539ceee5..ff91ddcc880dde5f35f7c8fbac87a30ab6dd5925 100644 --- a/interpreter/llvm/src/tools/clang/lib/Basic/Module.cpp +++ b/interpreter/llvm/src/tools/clang/lib/Basic/Module.cpp @@ -43,7 +43,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, IsSystem(false), IsExternC(false), IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false), InferExportWildcard(false), ConfigMacrosExhaustive(false), - NoUndeclaredIncludes(false), ModuleMapIsPrivate(false), + NoUndeclaredIncludes(false), IsOptional(false), ModuleMapIsPrivate(false), NameVisibility(Hidden) { if (Parent) { IsAvailable = Parent->isAvailable(); @@ -51,6 +51,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, IsSystem = Parent->IsSystem; IsExternC = Parent->IsExternC; NoUndeclaredIncludes = Parent->NoUndeclaredIncludes; + IsOptional = Parent->IsOptional; ModuleMapIsPrivate = Parent->ModuleMapIsPrivate; Parent->SubModuleIndex[Name] = Parent->SubModules.size(); diff --git a/interpreter/llvm/src/tools/clang/lib/Lex/ModuleMap.cpp b/interpreter/llvm/src/tools/clang/lib/Lex/ModuleMap.cpp index f9af7c2a24fb9bf5f13cba63ed101e2eabfcf522..7feb88508b9a20b82af7877cd9b8977b9c5efebc 100644 --- a/interpreter/llvm/src/tools/clang/lib/Lex/ModuleMap.cpp +++ b/interpreter/llvm/src/tools/clang/lib/Lex/ModuleMap.cpp @@ -274,6 +274,8 @@ void ModuleMap::resolveHeader(Module *Mod, // this was supposed to modularize the builtin header alone. } else if (Header.Kind == Module::HK_Excluded) { // Ignore missing excluded header files. They're optional anyway. + } else if (Mod->IsOptional) { + // Optional submodules can have missing headers. } else { // If we find a module that has a missing header, we mark this module as // unavailable and store the header directive for displaying diagnostics. @@ -1037,6 +1039,7 @@ Module *ModuleMap::inferFrameworkModule(const DirectoryEntry *FrameworkDir, Result->IsExternC |= Attrs.IsExternC; Result->ConfigMacrosExhaustive |= Attrs.IsExhaustive; Result->NoUndeclaredIncludes |= Attrs.NoUndeclaredIncludes; + Result->IsOptional |= Attrs.IsOptional; Result->Directory = FrameworkDir; // Chop off the first framework bit, as that is implied. @@ -1749,7 +1752,10 @@ namespace { AT_exhaustive, /// The 'no_undeclared_includes' attribute. - AT_no_undeclared_includes + AT_no_undeclared_includes, + + /// The 'optional' attribute. + AT_optional }; } // namespace @@ -2005,6 +2011,8 @@ void ModuleMapParser::parseModuleDecl() { ActiveModule->IsSystem = true; if (Attrs.IsExternC) ActiveModule->IsExternC = true; + if (Attrs.IsOptional) + ActiveModule->IsOptional = true; if (Attrs.NoUndeclaredIncludes || (!ActiveModule->Parent && ModuleName == "Darwin")) ActiveModule->NoUndeclaredIncludes = true; @@ -2905,6 +2913,7 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { .Case("exhaustive", AT_exhaustive) .Case("extern_c", AT_extern_c) .Case("no_undeclared_includes", AT_no_undeclared_includes) + .Case("optional", AT_optional) .Case("system", AT_system) .Default(AT_unknown); switch (Attribute) { @@ -2928,6 +2937,10 @@ bool ModuleMapParser::parseOptionalAttributes(Attributes &Attrs) { case AT_no_undeclared_includes: Attrs.NoUndeclaredIncludes = true; break; + + case AT_optional: + Attrs.IsOptional = true; + break; } consumeToken();