It turns out we need to handle LangOptions separately from the rest of the options. LangOptions used to be conditionally parsed only when !(DashX.getFormat() == InputKind::Precompiled || DashX.getLanguage() == Language::LLVM_IR) and we need to restore this order (for more info, see D94682).
We could do this similarly to how DiagnosticOptions are handled: via a counterpart to the IsDiag mix-in (e.g. IsLang). These mix-ins would prefix the option key path with the appropriate CompilerInvocation::XxxOpts member. However, this solution would be problematic, as we'd now have two kinds of options (Lang and Diag) with seemingly incomplete key paths in the same file. To understand what CompilerInvocation member an option affects, one would need to read the whole option definition and notice the IsDiag or IsLang class.
Instead, this patch introduces more robust way to handle different kinds of options separately: via the KeyPathAndMacroPrefix class. We have one specialization of that class per CompilerInvocation member (e.g. LangOpts, DiagnosticOpts, etc.). Now, instead of specifying a key path with "LangOpts->UndefPrefixes", we use LangOpts<"UndefPrefixes">. This keeps the readability intact (you don't have to look for the IsLang mix-in, the key path is complete on its own) and allows us to specify a custom macro prefix within LangOpts.