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();