Improve MSVC Crosstool

- Remove `/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS`: it disables warnings for deprecated C++ headers (`<stdext/*>`, `<hash_map>` etc.). Only useful for legacy codebase.
- Remove `/J`: `char` is signed according to ISO C++. There is no reason to make `char` unsigned by default.
- Remove default `/Gy`: moved to feature (`smaller_binary`).
- Remove default `/GF`: string pooling, enabled by default with `/O2`.
- Remove `/DDEBUG` in `dbg` mode: conflict with macros defined in some OSS projects such as LLVM. User should use standard `NDEBUG` to detect debug mode.

Implements a few general `feature` to abstract away details about the compiler:
- `treat_warnings_as_errors`: aka `-Werror`.
- `frame_pointer`: aka `-fno-omit-frame-pointer'.
- `determinism`: redact `__TIME__` macros etc.
- `disable_assertions`: allow user to have `assert/DCHECK` back even in `opt` mode.
- `smaller_binary`: common optimization enabled in `opt` mode. Still allow user to disable it in `opt` (such as when using ASAN).
- `ignore_noisy_warnings`: suppress a bunch of warnings most people don't care. If users want to be pedantic, they can still get those warnings back with `--features=-ignore_noisy_warnings`.

Closes #5519.

PiperOrigin-RevId: 203959555
diff --git a/tools/cpp/CROSSTOOL.tpl b/tools/cpp/CROSSTOOL.tpl
index 0a4b940..abeb2a2 100644
--- a/tools/cpp/CROSSTOOL.tpl
+++ b/tools/cpp/CROSSTOOL.tpl
@@ -211,19 +211,12 @@
   # Turn off warning messages.
   compiler_flag: "/D_CRT_SECURE_NO_DEPRECATE"
   compiler_flag: "/D_CRT_SECURE_NO_WARNINGS"
-  compiler_flag: "/D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS"
 
   # Useful options to have on for compilation.
   # Increase the capacity of object files to 2^32 sections.
   compiler_flag: "/bigobj"
   # Allocate 500MB for precomputed headers.
   compiler_flag: "/Zm500"
-  # Use unsigned char by default.
-  compiler_flag: "/J"
-  # Use function level linking.
-  compiler_flag: "/Gy"
-  # Use string pooling.
-  compiler_flag: "/GF"
   # Catch C++ exceptions only and tell the compiler to assume that functions declared
   # as extern "C" never throw a C++ exception.
   compiler_flag: "/EHsc"
@@ -881,7 +874,6 @@
       flag_group {
         flag: "/Od"
         flag: "/Z7"
-        flag: "/DDEBUG"
       }
     }
     flag_set {
@@ -904,7 +896,6 @@
       flag_group {
         flag: "/Od"
         flag: "/Z7"
-        flag: "/DDEBUG"
       }
     }
     flag_set {
@@ -925,13 +916,114 @@
       action: 'c-compile'
       action: 'c++-compile'
       flag_group {
-        flag: "/O2"
+        flag: "/O2" # Implies /Og /Oi /Ot /Oy /Ob2 /Gs /GF /Gy
+      }
+    }
+    implies: 'frame_pointer'
+  }
+
+  # Keep stack frames for debugging, even in opt mode.
+  # Must come after /O1, /O2 and /Ox.
+  feature {
+    name: "frame_pointer"
+    flag_set {
+      action: "c-compile"
+      action: "c++-compile"
+      flag_group {
+        flag: "/Oy-"
+      }
+    }
+  }
+
+  # Remove assert/DCHECKs in opt mode.
+  # You can have them back with --features=-disable_assertions.
+  feature {
+    name: 'disable_assertions'
+    enabled: true
+    flag_set {
+      action: 'c-compile'
+      action: 'c++-compile'
+      with_feature: {
+        feature: 'opt'
+      }
+      flag_group {
         flag: "/DNDEBUG"
       }
     }
   }
 
   feature {
+    name: "determinism"
+    enabled: true
+    flag_set {
+      action: "c-compile"
+      action: "c++-compile"
+      flag_group {
+        # Make C++ compilation deterministic. Use linkstamping instead of these
+        # compiler symbols.
+        # TODO: detect clang on Windows and use "-Wno-builtin-macro-redefined"
+        flag: "/wd4177" # Trying to define or undefine a predefined macro
+        flag: "-D__DATE__=\"redacted\""
+        flag: "-D__TIMESTAMP__=\"redacted\""
+        flag: "-D__TIME__=\"redacted\""
+      }
+    }
+  }
+
+  feature {
+    name: 'treat_warnings_as_errors'
+    flag_set {
+      action: 'c-compile'
+      action: 'c++-compile'
+      flag_group {
+        flag: "/WX"
+      }
+    }
+  }
+
+  # Trade slower build time for smaller binary
+  feature {
+    name: 'smaller_binary'
+    enabled: true
+    flag_set {
+      action: 'c-compile'
+      action: 'c++-compile'
+      with_feature: {
+        feature: 'opt'
+      }
+      flag_group {
+        flag: "/Gy" # Enable function-level linking (-ffunction-sections)
+        flag: "/Gw" # Optimize global data (-fdata-sections)
+      }
+    }
+    flag_set {
+      action: 'c++-link-executable'
+      action: 'c++-link-dynamic-library',
+      action: 'c++-link-nodeps-dynamic-library'
+      with_feature: {
+        feature: 'opt'
+      }
+      flag_group {
+        flag: '/OPT:ICF' # Fold identical functions
+        flag: '/OPT:REF' # Eliminate unreferenced functions and data
+      }
+    }
+  }
+
+  # Suppress warnings that most users do not care
+  feature {
+    name: 'ignore_noisy_warnings'
+    enabled: true
+    flag_set {
+      action: 'c++-link-static-library'
+      flag_group {
+        # Suppress 'object file does not define any public symbols' warning
+        flag: '/ignore:4221'
+      }
+    }
+  }
+
+  feature {
     name: 'user_compile_flags'
     flag_set {
       expand_if_all_available: 'user_compile_flags'